/*******************************************************************
 * \file   Log.cpp
 *
 * \author Romain BOULLARD
 * \date   October 2025
 *********************************************************************/
#include <Utils/Log/Log.hpp>

#if defined BIGFOOT_NOT_OPTIMIZED

namespace Bigfoot
{
Log::Log()
{
    quill::Backend::start();

    m_sinks[static_cast<std::size_t>(Flat::LogSinkType::Console)] =
        quill::Frontend::create_or_get_sink<quill::ConsoleSink>(
            std::string {Flat::EnumNameLogSinkType(Flat::LogSinkType::Console)});
}

/****************************************************************************************/

quill::Logger* Log::RegisterLogger(const LoggerInfo& p_loggerInfo)
{
    quill::Logger* logger = quill::Frontend::create_or_get_logger(
        p_loggerInfo.m_name,
        m_sinks[static_cast<std::size_t>(Flat::LogSinkType::Console)]);
    SetLoggerLevel(p_loggerInfo);

    return logger;
}

/****************************************************************************************/

void Log::UnregisterLogger(const LoggerInfo& p_loggerInfo)
{
    if (quill::Logger* logger = quill::Frontend::get_logger(p_loggerInfo.m_name))
    {
        quill::Frontend::remove_logger_blocking(logger);
    }
}

/****************************************************************************************/

quill::Logger* Log::GetLogger(const LoggerInfo& p_loggerInfo)
{
    return quill::Frontend::get_logger(p_loggerInfo.m_name);
}

/****************************************************************************************/

void Log::ChangeLoggerLogLevel(LoggerInfo& p_loggerInfo, const Flat::LogLevel p_level)
{
    p_loggerInfo.m_level = p_level;
    SetLoggerLevel(p_loggerInfo);
}

/****************************************************************************************/

void Log::SetLoggerLevel(const LoggerInfo& p_loggerInfo)
{
    constexpr auto logLevelToQuillLogLevel = [](const Flat::LogLevel p_level) constexpr -> quill::LogLevel
    {
        switch (p_level)
        {
        case Flat::LogLevel::Debug:
            return quill::LogLevel::Debug;
        case Flat::LogLevel::Trace:
            return quill::LogLevel::TraceL3;
        case Flat::LogLevel::Info:
            return quill::LogLevel::Info;
        case Flat::LogLevel::Warn:
            return quill::LogLevel::Warning;
        case Flat::LogLevel::Error:
            return quill::LogLevel::Error;
        case Flat::LogLevel::Critical:
            return quill::LogLevel::Critical;
        }

        return quill::LogLevel::TraceL3;
    };

    if (quill::Logger* logger = GetLogger(p_loggerInfo))
    {
        logger->set_log_level(logLevelToQuillLogLevel(p_loggerInfo.m_level));
    }
}

/****************************************************************************************/

void Log::Flush()
{
    for (quill::Logger* logger: quill::Frontend::get_all_loggers())
    {
        logger->flush_log();
    }
}

/****************************************************************************************/

Log::~Log()
{
    Flush();
    for (quill::Logger* logger: quill::Frontend::get_all_loggers())
    {
        quill::Frontend::remove_logger_blocking(logger);
    }
    quill::Backend::stop();
}
}   // namespace Bigfoot
#endif
