#define UNICODE
#define _UNICODE
#include "LoadingWindow.h"
#include <algorithm>

static const wchar_t* kWindowClass = L"LoadingWndClass";
static LoadingWindow* g_instance = nullptr;

void LoadingWindow::Create(const std::string& title)
{
    g_instance = this;
    windowTitle = std::wstring(title.begin(), title.end());

    WNDCLASS wc = {};
    wc.lpfnWndProc = WndProc;
    wc.hInstance = GetModuleHandle(nullptr);
    wc.lpszClassName = kWindowClass;
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    RegisterClass(&wc);

    hwnd = CreateWindowEx(
        0, kWindowClass, windowTitle.c_str(),
        WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME,
        CW_USEDEFAULT, CW_USEDEFAULT, 500, 200,
        nullptr, nullptr, GetModuleHandle(nullptr), nullptr
    );

    ShowWindow(hwnd, SW_SHOWNORMAL);
    UpdateWindow(hwnd);
}

void LoadingWindow::Update(const std::string& step, const std::string& detail, float progress)
{
    currentStep = step;
    currentDetail = detail;
    currentProgress = std::clamp(progress, 0.0f, 1.0f);

    InvalidateRect(hwnd, nullptr, TRUE);
    UpdateWindow(hwnd);

    MSG msg;
    while (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

void LoadingWindow::Destroy()
{
    if (hwnd)
    {
        DestroyWindow(hwnd);
        hwnd = nullptr;
    }
    UnregisterClass(kWindowClass, GetModuleHandle(nullptr));
}

LRESULT CALLBACK LoadingWindow::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    if (msg == WM_PAINT && g_instance)
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);

        RECT r;
        GetClientRect(hWnd, &r);

        std::wstring step = std::wstring(g_instance->currentStep.begin(), g_instance->currentStep.end());
        std::wstring detail = std::wstring(g_instance->currentDetail.begin(), g_instance->currentDetail.end());

        SetBkMode(hdc, TRANSPARENT);
        SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));

        RECT textRect = r;
        textRect.top += 10;
        textRect.left += 20;

        DrawTextW(hdc, step.c_str(), -1, &textRect, DT_LEFT | DT_TOP | DT_SINGLELINE);
        textRect.top += 30;
        DrawTextW(hdc, detail.c_str(), -1, &textRect, DT_LEFT | DT_TOP | DT_SINGLELINE);

        // Progress bar background
        RECT progressRect = { r.left + 20, r.bottom - 50, r.right - 20, r.bottom - 30 };
        HBRUSH bg = CreateSolidBrush(RGB(200, 200, 200));
        FillRect(hdc, &progressRect, bg);
        DeleteObject(bg);

        // Progress bar fill
        int barWidth = static_cast<int>((progressRect.right - progressRect.left) * g_instance->currentProgress);
        RECT fillRect = { progressRect.left, progressRect.top, progressRect.left + barWidth, progressRect.bottom };
        HBRUSH fill = CreateSolidBrush(RGB(70, 140, 255));
        FillRect(hdc, &fillRect, fill);
        DeleteObject(fill);

        EndPaint(hWnd, &ps);
        return 0;
    }

    return DefWindowProc(hWnd, msg, wParam, lParam);
}
