#pragma once

#include <util/stream/null.h>
#include <util/stream/output.h>

namespace NSrvKernel {

    struct TAccessLogSummary {
        TString AnsweredModule;
        TString AnswerReason;
    };

    class TAccessLogOutput {
    public:
        TAccessLogOutput(IOutputStream* slave, TAccessLogSummary* summary = nullptr) noexcept
            : Slave_(slave)
            , Summary_(summary)
        {}

        TAccessLogOutput() noexcept
            : Slave_(&Cnull)
            , Summary_(nullptr)
        {}

        bool operator==(const TAccessLogOutput& b) const noexcept {
            return Slave_ == b.Slave_ && Summary_ == b.Summary_;
        }

        bool HasNullSlave() const noexcept {
            return Slave_ == &Cnull;
        }

        IOutputStream* Slave() const noexcept {
            return Slave_;
        }

        TAccessLogSummary* Summary() const noexcept {
            return Summary_;
        }

        void SetSummary(TString module, TString reason) const noexcept {
            if (Summary_) {
                Summary_->AnsweredModule = std::move(module);
                Summary_->AnswerReason = std::move(reason);
            }
        }

        template <typename T>
        TAccessLogOutput& operator<<(T&& value) noexcept {
            try {
                *Slave_ << std::forward<T>(value);
            } catch (...) {}
            return *this;
        }

        template <typename T>
        const TAccessLogOutput& operator<<(T&& value) const noexcept {
            try {
                *Slave_ << std::forward<T>(value);
            } catch (...) {}
            return *this;
        }

    private:
        IOutputStream* Slave_ = nullptr;
        TAccessLogSummary* Summary_ = nullptr;
    };
    static_assert(sizeof(TAccessLogOutput) <= 16, "TAccessLogOutput has become too big");

}
