#pragma once
#include <string>
#include <vector>
#include <ostream>
#include <source_location>

#define LOG_DEPRECATED_USE(msg) \
    Logger::LogDepricated("%s (called from %s:%d in %s)", msg, __FILE__, __LINE__, __func__)

#define DEPRICATED(func, ...)                                                                 \
    Logger::LogDepricatedWithCaller(#func " is deprecated", std::source_location::current()); \
    func(__VA_ARGS__)

class Logger
{
public:
    enum Level
    {
        Ok,
        Info,
        Warning,
        Error,
        Debug,
        Verbose
    };
    static void Log(Level level, const char *fmt, ...);
    static void LogVA(Level level, const char *fmt, va_list args);

    static void LogOk(const char *fmt, ...);
    static void LogInfo(const char *fmt, ...);
    static void LogWarning(const char *fmt, ...);
    static void LogError(const char *fmt, ...);
    static void LogDebug(const char *fmt, ...);
    static void LogVerbose(const char *fmt, ...);
    static void LogDepricated(const char *fmt, ...);

    static void LogDepricatedWithCaller(
        const char *msg,
        const std::source_location location = std::source_location::current());

    static void LogDepricatedWithStackTrace(const char *msg);

    static void Clear();
    static void Draw(const char *title = "Console");

private:
    struct LogMessage
    {
        std::string text;
        Level level;
    };

    static std::vector<LogMessage> s_Messages;
    static bool s_AutoScroll;
    static bool s_ShowOk;
    static bool s_ShowInfo;
    static bool s_ShowWarning;
    static bool s_ShowError;
    static bool s_ShowDebug;
    static bool s_ShowVerbose;

    static const char *ToString(Level level);
    static const char *GetAnsiColor(Level level);
};
