#include "UIFramework.h"
#include "raylib.h"
#include "../Initialization/Initialization.h"
#include "../Backend/Font/FontManager.h"

// --- UIContext ---

void UIContext::NewFrame() {
    m_mousePressConsumed = false;
    m_mouseReleaseConsumed = false;
    if (RLIsMouseButtonPressed(MOUSE_LEFT_BUTTON))
        m_pressCaptured = false;
}

bool UIContext::ConsumeMousePress() {
    if (m_mousePressConsumed)
        return false;
    m_mousePressConsumed = true;
    return true;
}

bool UIContext::IsMousePressConsumed() const {
    return m_mousePressConsumed;
}

bool UIContext::ConsumeMouseRelease() {
    if (m_mouseReleaseConsumed)
        return false;
    m_mouseReleaseConsumed = true;
    m_pressCaptured = false;
    return true;
}

bool UIContext::IsMouseReleaseConsumed() const {
    return m_mouseReleaseConsumed;
}

void UIContext::CapturePressOn(RLRectangle rect) {
    m_pressCapturedRect = rect;
    m_pressCaptured = true;
}

bool UIContext::IsPressCapturedOn(RLRectangle rect) const {
    if (!m_pressCaptured)
        return false;
    return RLCheckCollisionPointRec(
        { rect.x + rect.width / 2, rect.y + rect.height / 2 },
        m_pressCapturedRect);
}

// --- WidgetManager ---

WidgetManager* WidgetManager::Get() {
    static WidgetManager instance;
    return &instance;
}

void WidgetManager::NewFrame() {
    m_ctx.NewFrame();
}

WidgetState WidgetManager::BeginWidget(RLRectangle rect) {
    Initialization::Get()->AddDragBlockRegion(rect);
    RLVector2 mouse = RLGetMousePosition();
    bool hover = RLCheckCollisionPointRec(mouse, rect);
    bool down = RLIsMouseButtonDown(MOUSE_LEFT_BUTTON);
    bool pressed = hover && down;
    bool clicked = hover && RLIsMouseButtonPressed(MOUSE_LEFT_BUTTON) && m_ctx.ConsumeMousePress();
    if (clicked)
        m_ctx.CapturePressOn(rect);
    bool released = hover && RLIsMouseButtonReleased(MOUSE_LEFT_BUTTON)
                    && m_ctx.IsPressCapturedOn(rect)
                    && m_ctx.ConsumeMouseRelease();
    return { hover, pressed, clicked, released };
}

// --- Framework (thin facade) ---

Framework* Framework::Get() {
    static Framework instance;
    return &instance;
}

void Framework::NewFrame() {
    WidgetManager::Get()->NewFrame();
}

// --- Render ---

Render* Render::Get() {
    static Render instance;
    return &instance;
}

void Render::Gradient(RLRectangle Rect, RLColor LColor, RLColor ROtherColor, bool Vertical, bool Antialias) {
    (void)Antialias;
    if (Vertical) RLDrawRectangleGradientV((int)Rect.x, (int)Rect.y, (int)Rect.width, (int)Rect.height, LColor, ROtherColor);
    else          RLDrawRectangleGradientH((int)Rect.x, (int)Rect.y, (int)Rect.width, (int)Rect.height, LColor, ROtherColor);
}

void Render::CustomGradientBar(int x, int y, int width, int height, GradientStop* stops, int stopCount){
    if (stopCount < 2) return;
    int x_scaled = x;
    int y_scaled = y;
    int width_scaled = width;
    int height_scaled = height;

    for (int i = 0; i < stopCount - 1; i++)
    {
        GradientStop startStop = stops[i];
        GradientStop endStop = stops[i + 1];

        int startPixel = (int)(startStop.offset * width_scaled);
        int endPixel = (int)(endStop.offset * width_scaled);
        int segmentWidth = endPixel - startPixel;

        if (segmentWidth <= 0) continue;

        for (int j = 0; j < segmentWidth; j++)
        {
            float t = (segmentWidth == 1) ? 0.0f : (float)j / (float)(segmentWidth - 1);

            RLColor c;
            c.r = (unsigned char)ClampInt(startStop.color.r + (endStop.color.r - startStop.color.r) * t, 0, 255);
            c.g = (unsigned char)ClampInt(startStop.color.g + (endStop.color.g - startStop.color.g) * t, 0, 255);
            c.b = (unsigned char)ClampInt(startStop.color.b + (endStop.color.b - startStop.color.b) * t, 0, 255);
            c.a = (unsigned char)ClampInt(startStop.color.a + (endStop.color.a - startStop.color.a) * t, 0, 255);

            int current_pixel_x = x_scaled + startPixel + j;

            RLDrawRectangle(current_pixel_x, y_scaled, 1, height_scaled, c);

            float darkFactor = 0.5f;
            RLColor c_dark = {
                (unsigned char)(c.r * darkFactor),
                (unsigned char)(c.g * darkFactor),
                (unsigned char)(c.b * darkFactor),
                c.a
            };
            RLDrawRectangle(current_pixel_x, y_scaled + 1, 1, height_scaled, c_dark);
        }
    }
}