#include "Logger.h"
#include <iostream>
#include <chrono>
#include <ctime>
#include <cstdarg>
#include "types/all.h"

namespace OX
{
    std::vector<Message> Logger::m_messages;
    std::string Logger::m_sectionName = "\033[35mONYX";

    inline const char *ToString(MessageType type)
    {
        switch (type) {
            case MessageType::Info: return "Info";
            case MessageType::Warning: return "Warning";
            case MessageType::Error: return "Error";
            case MessageType::Debug: return "Debug";
            case MessageType::Ok: return "Ok";
            case MessageType::Verbose: return "Verbose";
            default: return "Unknown";
        }
    }


    static std::string GetTimestamp()
    {
        auto now = std::chrono::system_clock::now();
        std::time_t t = std::chrono::system_clock::to_time_t(now);
        std::tm *tm = std::localtime(&t);
        char buffer[20];
        std::strftime(buffer, sizeof(buffer), "%H:%M:%S", tm);
        return buffer;
    }

    static const char *GetAnsiColor(MessageType type)
    {
        switch (type) {
            case MessageType::Info: return "\033[1;36m"; // Bright cyan
            case MessageType::Warning: return "\033[1;33m"; // Bright yellow
            case MessageType::Error: return "\033[1;91m"; // Bright red
            case MessageType::Debug: return "\033[1;90m"; // Bright gray
            case MessageType::Verbose: return "\033[0;37m"; // Standard gray (lighter than debug)
            case MessageType::Ok: return "\033[1;32m"; // Bright green
            default: return "\033[0m"; // Reset
        }
    }


    Color Logger::GetRGBColor(const MessageType type)
    {
        Color color;
        switch (type) {
            case MessageType::Info:
                color = {0.0f, 0.478f, 1.0f}; // Standard blue (iOS info blue / material blue)
                break;
            case MessageType::Warning:
                color = {1.0f, 0.647f, 0.0f}; // Orange / amber (alert warning)
                break;
            case MessageType::Error:
                color = {0.863f, 0.078f, 0.235f}; // Crimson / alert red
                break;
            case MessageType::Debug:
                color = {0.56f, 0.56f, 0.58f}; // Slate gray
                break;
            case MessageType::Ok:
                color = {0.0f, 0.8f, 0.4f}; // Vibrant green / success
                break;
            case MessageType::Verbose:
                color = {0.6f, 0.6f, 0.7f}; // Dim blue-gray
                break;
            default:
                color = {1.0f, 1.0f, 1.0f}; // Default white
                break;
        }
        return color;
    }


    void Logger::LogInternal(const std::string &text, MessageType type)
    {
        glm::vec3 color = Logger::GetRGBColor(type);
        float r = color.r;
        float g = color.g;
        float b = color.b;


        Message message{
            GetTimestamp(),
            text,
            type,
            r, g, b
        };

        m_messages.push_back(message);

        std::cout << "\033[37m[\033[0m" << m_sectionName << "\033[37m]\033[0m"
                << "\033[37m[\033[36m" << message.timestamp
                << "\033[37m]\033[37m[\033[33m"
                << GetAnsiColor(type)
                << ToString(message.type)
                << "\033[37m] "
                << GetAnsiColor(type)
                << text
                << "\033[0m\n";
    }

    void Logger::Logf(MessageType type, const char *format, ...)
    {
        char buffer[1024];

        va_list args;
        va_start(args, format);
        std::vsnprintf(buffer, sizeof(buffer), format, args);
        va_end(args);

        LogInternal(std::string(buffer), type);
    }

    void Logger::LogInfo(const char *format, ...)
    {
        va_list args;
        va_start(args, format);
        char buffer[1024];
        std::vsnprintf(buffer, sizeof(buffer), format, args);
        va_end(args);
        LogInternal(buffer, MessageType::Info);
    }

    void Logger::LogWarning(const char *format, ...)
    {
        va_list args;
        va_start(args, format);
        char buffer[1024];
        std::vsnprintf(buffer, sizeof(buffer), format, args);
        va_end(args);
        LogInternal(buffer, MessageType::Warning);
    }

    void Logger::LogError(const char *format, ...)
    {
        va_list args;
        va_start(args, format);
        char buffer[1024];
        std::vsnprintf(buffer, sizeof(buffer), format, args);
        va_end(args);
        LogInternal(buffer, MessageType::Error);
    }

    void Logger::LogDebug(const char *format, ...)
    {
        va_list args;
        va_start(args, format);
        char buffer[1024];
        std::vsnprintf(buffer, sizeof(buffer), format, args);
        va_end(args);
        LogInternal(buffer, MessageType::Debug);
    }

    void Logger::LogVerbose(const char *format, ...)
    {
        va_list args;
        va_start(args, format);
        char buffer[1024];
        std::vsnprintf(buffer, sizeof(buffer), format, args);
        va_end(args);
        LogInternal(buffer, MessageType::Verbose);
    }


    void Logger::LogOk(const char *format, ...)
    {
        va_list args;
        va_start(args, format);
        char buffer[1024];
        std::vsnprintf(buffer, sizeof(buffer), format, args);
        va_end(args);
        LogInternal(buffer, MessageType::Ok);
    }

    const std::vector<Message> &Logger::GetMessages()
    {
        return m_messages;
    }


    std::string Logger::MessageTypeToString(const MessageType type)
    {
        switch (type) {
            case MessageType::Info: return "Info";
            case MessageType::Warning: return "Warning";
            case MessageType::Error: return "Error";
            case MessageType::Debug: return "Debug";
            case MessageType::Verbose: return "Verbose";
            case MessageType::Ok: return "Ok";
            default: return "Unknown";
        }
    }
}
