/*
 * Copyright 2020 Bloomberg Finance LP
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <buildboxcommon_standardoutputstreamer.h>

#include <buildboxcommon_logging.h>

#include <functional>
#include <utility>

namespace buildboxcommon {

StandardOutputStreamer::StandardOutputStreamer(
    std::string path, const ConnectionOptions &connectionOptions,
    std::string resourceName)
    : d_filePath(std::move(path)), d_url(connectionOptions.d_url),
      d_resourceName(std::move(resourceName)),
      d_logstreamWriter(d_resourceName, connectionOptions),
      d_fileMonitor(
          std::make_unique<StreamingStandardOutputIfstreamFileMonitor>(
              d_filePath, std::bind(&StandardOutputStreamer::streamLogChunk,
                                    this, std::placeholders::_1))),
      d_stopRequested(false)
{
}

StandardOutputStreamer::~StandardOutputStreamer()
{
    if (!d_stopRequested) {
        BUILDBOX_LOG_WARNING("Destroying `StandardOutputStreamer` instance "
                             "without invoking `stop()`, outputs may be lost");
    }
}

bool StandardOutputStreamer::stop()
{
    if (d_stopRequested) {
        return false;
    }
    d_stopRequested = true;

    BUILDBOX_LOG_DEBUG("Stopping the monitoring of ["
                       << d_filePath << "] and committing the log");

    // destroy the monitoring thread
    d_fileMonitor.reset();
    return d_logstreamWriter.commit();
}

bool StandardOutputStreamer::streamLogChunk(
    const StreamingStandardOutputFileMonitor::FileChunk &chunk)
{
    BUILDBOX_LOG_TRACE("File monitor reported ["
                       << d_filePath << "] has " << chunk.size()
                       << " bytes available, streaming to "
                       << "[" << d_url << "/" << d_resourceName << "]");

    const bool write_suceeded =
        d_logstreamWriter.write(std::string(chunk.ptr(), chunk.size()));

    if (!write_suceeded) {
        BUILDBOX_LOG_DEBUG(
            "`Write()` call failed, stopping the monitoring thread");
        d_stopRequested = true;
    }
    return write_suceeded;
}

} // namespace buildboxcommon
