#include "tile/base/logging/splitter_sink.h"
#include <cassert>

namespace tile {
std::shared_ptr<SplitterSink>
SplitterSink::Create()
{
    return std::shared_ptr<SplitterSink>(new SplitterSink());
}

std::shared_ptr<SplitterSink>
SplitterSink::Create(std::initializer_list<std::shared_ptr<LogSink>> init_list)
{
    auto sink = Create();
    for (auto &s : init_list) { sink->AddSink(s); }
    return sink;
}

SplitterSink::SplitterSink() {}

SplitterSink::~SplitterSink() {}

void
SplitterSink::Send(LogSeverity severity,
                   const char *full_filename,
                   const char *base_filename,
                   int line,
                   const LogMessageTime &logmsgtime,
                   const char *message,
                   size_t message_len)
{
    assert(!doing_ && "SplitterSink::send() should not be called recursively");
    std::lock_guard<std::mutex> _(sinks_mutex_);
    doing_ = true;
    for (auto &sink : sinks_) {
        sink->Send(severity, full_filename, base_filename, line, logmsgtime, message, message_len);
    }
    doing_ = false;
}

void
SplitterSink::Flush()
{
    assert(!doing_ && "SplitterSink::send() should not be called recursively");
    std::lock_guard<std::mutex> _(sinks_mutex_);
    doing_ = true;
    for (auto &sink : sinks_) { sink->Flush(); }
    doing_ = false;
}

void
SplitterSink::AddSink(std::shared_ptr<LogSink> sink)
{
    std::lock_guard<std::mutex> _(sinks_mutex_);
    sinks_.insert(sink);
}

void
SplitterSink::RemoveSink(std::shared_ptr<LogSink> sink)
{
    std::lock_guard<std::mutex> _(sinks_mutex_);
    sinks_.erase(sink);
}

void
SplitterSink::ClearSinks()
{
    std::lock_guard<std::mutex> _(sinks_mutex_);
    sinks_.clear();
}

std::set<LogSink::Ptr>
SplitterSink::sinks()
{
    std::lock_guard<std::mutex> _(sinks_mutex_);
    return sinks_;
}

}// namespace tile
