#pragma once

#include <string>

#include "fmt/format.h"
#include "fmt/args.h"

#include "DllDefines.h"

class UTILITYDLL CLogger
{
public:
    CLogger(const std::string& strName);
    virtual ~CLogger();

    void Start();
    void Stop();
    void SetEnable(bool bEnable) { m_bEnable = bEnable; }
    void Log(const std::string& strMsg);
    void Trace(const std::string& strMsg);
    void Info(const std::string& strMsg);
    void Error(const std::string& strMsg);

    template <typename... Args>
    void Log(fmt::format_string<Args...> _fmt, Args&&... args)
    {
        try
        {
            std::vector<char> buf;

            fmt::vformat_to(std::back_inserter(buf), _fmt, fmt::make_format_args(args...));

            std::string log_msg(std::string_view(buf.data(), buf.size()));
            Log(log_msg);
        }
        catch (...)
        {
        }
    }

    template <typename... Args>
    void Trace(fmt::format_string<Args...> _fmt, Args&&... args)
    {
        try
        {
            std::vector<char> buf;

            fmt::vformat_to(std::back_inserter(buf), _fmt, fmt::make_format_args(args...));

            std::string log_msg(std::string_view(buf.data(), buf.size()));
            Trace(log_msg);
        }
        catch (...)
        {
        }
    }

    template <typename... Args>
    void Info(fmt::format_string<Args...> _fmt, Args&&... args)
    {
        try
        {
            std::vector<char> buf;

            fmt::vformat_to(std::back_inserter(buf), _fmt, fmt::make_format_args(args...));

            std::string log_msg(std::string_view(buf.data(), buf.size()));
            Info(log_msg);
        }
        catch (...)
        {
        }
    }

    template <typename... Args>
    void Error(fmt::format_string<Args...> _fmt, Args&&... args)
    {
        try
        {
            std::vector<char> buf;

            fmt::vformat_to(std::back_inserter(buf), _fmt, fmt::make_format_args(args...));

            std::string log_msg(std::string_view(buf.data(), buf.size()));
            Error(log_msg);
        }
        catch (...)
        {
        }
    }


protected:
    bool        IsEnable() const { return m_bEnable; }
    std::string GetName() { return m_strName; }

private:
    virtual void DoStart()                            = 0;
    virtual void DoFlush()                            = 0;
    virtual void DoLogging(const std::string& strMsg) = 0;

    virtual void DoInfo(const std::string& strMsg){};
    virtual void DoTrace(const std::string& strMsg){};
    virtual void DoError(const std::string& strMsg){};

    std::string m_strName;
    bool        m_bEnable{ false };
    bool        m_bRotating{ true };
    int         m_nFileSizeMB{ 1 };

    //
};
