#include "adapters/windows/diagnostics/WindowsConsoleLogSink.h"

#include <Windows.h>

#include <string>

namespace ta::adapters::windows::diagnostics
{
    namespace
    {
        int level_color(const ta::foundation::logger::Level level) noexcept
        {
            switch (level)
            {
            case ta::foundation::logger::Level::Path: return 8;
            case ta::foundation::logger::Level::Info: return 3;
            case ta::foundation::logger::Level::Warning: return 6;
            case ta::foundation::logger::Level::Error: return 4;
            case ta::foundation::logger::Level::Fatal: return 12;
            default: return 7;
            }
        }

        void write_text(const HANDLE output, const std::string& text)
        {
            if (!output || output == INVALID_HANDLE_VALUE || text.empty())
                return;
            DWORD written = 0;
            WriteConsoleA(output, text.c_str(), static_cast<DWORD>(text.size()), &written, nullptr);
        }
    }

    WindowsConsoleLogSink::WindowsConsoleLogSink(void* output) noexcept
        : output_(output)
    {
    }

    void WindowsConsoleLogSink::set_output(void* output) noexcept
    {
        output_ = output;
    }

    void WindowsConsoleLogSink::write(const ta::foundation::logger::Entry& entry)
    {
        const HANDLE output = static_cast<HANDLE>(output_);
        if (!output || output == INVALID_HANDLE_VALUE)
            return;

        write_text(output, entry.timestamp + " [");
        SetConsoleTextAttribute(output, static_cast<WORD>(level_color(entry.level)));
        write_text(output, ta::foundation::logger::level_name(entry.level));
        SetConsoleTextAttribute(output, static_cast<WORD>(7));
        write_text(output, "][" + entry.channel + "][T" +
            std::to_string(entry.thread_id) + "] " + entry.message + "\n");
    }
}
