#pragma once

#include <library/cpp/logger/global/common.h>

class TComponentLog final: public TLog {
public:
    // main constructor
    TComponentLog(TAutoPtr<TLogBackend> backend);

    TComponentLog(const TStringBuf prefix, ELogPriority prio = LOG_MAX_PRIORITY);

    // fallback constructor for CreateDefaultLogger
    TComponentLog()
        : TComponentLog(TStringBuf())
    {
    }

public:
    inline static TLog& Default() {
        return TLoggerOperator<TComponentLog>::Log();
    }
};

template <>
inline TComponentLog* CreateDefaultLogger<TComponentLog>() {
    return new TComponentLog;
}

struct TOneLineLogElement: public TLogElement {
public:
    using TLogElement::TLogElement;

    // Must be the first operation
    inline TLogElement& operator<<(ELogPriority priority) {
        // Note: this whole class is a workaround to some Morozovian behavior in library/cpp/logger/global.
        // TLogElement::operator<<(ELogPriority) calls Flush() and interferes with Formatter - god knows why.
        Priority_ = priority;
        return *this;
    }
};

struct TComponentLogFormatter {
    inline static bool CheckLoggingContext(TLog&, const TLogRecordContext&) {
        return true;
    }

    static TSimpleSharedPtr<TOneLineLogElement> StartRecord(TLog& logger, const TLogRecordContext& context, TSimpleSharedPtr<TLogElement> earlier) noexcept;

    static TStringBuf RemoveFormatting(const TStringBuf logMessage) noexcept;
};


//
// Standard logging.
// Usage:
//     C_LOG(Log_) << TLOG_ERR << "My error message"; /* no Endl */
//
#define C_LOG(logger) LOGGER_CHECKED_GENERIC_LOG(logger, TComponentLogFormatter, LOG_DEF_PRIORITY, "")

//
// 'Builder object' for multi-line syntax.
// You do not really need it.
// Usage:
//      auto logMessage = C_LOG_BUILDER(logger, TLOG_INFO);
//      *logMessage << "a";
//      *logMessage << 10;
//      logMessage.Drop();
//
#define C_LOG_BUILDER(logger, prio) (::GetLoggerForce<TComponentLogFormatter>(logger, TLogRecordContext(__LOCATION__, "", prio)))

