/*********************************************************************
 * \file   Log.hpp
 *
 * \author Romain BOULLARD
 * \date   October 2025
 *********************************************************************/
#ifndef BIGFOOT_UTILS_LOG_LOG_HPP
#define BIGFOOT_UTILS_LOG_LOG_HPP
#include <Utils/Log/EASTLFormatters.hpp>

#if defined BIGFOOT_NOT_OPTIMIZED
#include <Utils/Log/Log_generated.hpp>

#include <EASTL/array.h>

#ifdef BIGFOOT_WINDOWS
#pragma warning(disable: 4702)
#endif
#include <quill/Backend.h>
#include <quill/Frontend.h>
#include <quill/LogMacros.h>
#include <quill/Logger.h>
#include <quill/sinks/ConsoleSink.h>
#if defined BIGFOOT_WINDOWS
#pragma warning(default: 4702)
#endif

namespace Bigfoot
{
class Log
{
  public:
    struct LoggerInfo
    {
        std::string m_name;
        Flat::LogLevel m_level;
    };

    Log();

    Log(const Log& p_logger) = delete;
    Log(Log&& p_logger) = delete;

    /**
     * Register a logger.
     *
     * \param p_loggerInfo The logger to register
     */
    [[nodiscard]]
    quill::Logger* RegisterLogger(const LoggerInfo& p_loggerInfo);

    /**
     * Unregister a logger.
     *
     * \param p_loggerInfo The logger to unregister
     */
    void UnregisterLogger(const LoggerInfo& p_loggerInfo);

    /**
     * Register a logger.
     *
     * \param p_loggerInfo The logger to get
     * \return The logger, nullptr if it does not exist
     */
    [[nodiscard]]
    quill::Logger* GetLogger(const LoggerInfo& p_loggerInfo);

    /**
     * Changes the loglevel of a Logger.
     *
     * \param p_loggerInfo The logger to change
     * \param p_level The new level
     */
    void ChangeLoggerLogLevel(LoggerInfo& p_loggerInfo, const Flat::LogLevel p_level);

    /*
     * Flush all the loggers
     *
     */
    void Flush();

    ~Log();

    Log& operator=(const Log& p_logger) = delete;
    Log& operator=(Log&& p_logger) = delete;

  private:
    /**
     * Set the LogLevel of a logger
     *
     * \param p_loggerInfo The logger to set
     */
    void SetLoggerLevel(const LoggerInfo& p_loggerInfo);

    /*
     * The sinks
     */
    eastl::array<std::shared_ptr<quill::Sink>, 1> m_sinks;
};
}   // namespace Bigfoot
#endif
#endif
