#include "ui_widgets.h"

#include "game_state.h"

#include <stdio.h>

f32 uiGetScale() {
    // Assuming 16:9 aspect
    f32 scaleX = GetScreenWidth() / 1280.0f;
    f32 scaleY = GetScreenHeight() / 720.0f;
    return BZ_MIN(scaleX, scaleY);
}

Font getFont() {
    static const Game *game = NULL;
    if (!game) {
        game = ecs_singleton_get(ECS, Game);
    }
    return game->font;
}

BzUINode *uiPushDivParentPercentage(f32 xPercent, f32 yPercent) {
    return bzUIPushDiv(UI, (BzUISize) {
            .kind = BZ_UI_SIZE_REL_PARENT,
            .value = xPercent,
    }, (BzUISize) {
            .kind = BZ_UI_SIZE_REL_PARENT,
            .value = yPercent
    });
}

void uiBaseLabel(const char *txt, Font font, f32 scl) {
    BzUINode *node = bzUINodeMake(UI, bzUIKeyFromString(txt), &(BzUINodeDesc) {
            .flags = BZ_UI_DRAW_TEXT | BZ_UI_DRAW_TEXT_SHADOW | BZ_UI_ALIGN_CENTER,
            .semanticSize[BZ_UI_AXIS_X] = {
                    .kind = BZ_UI_SIZE_FIT,
            },
            .semanticSize[BZ_UI_AXIS_Y] = {
                    .kind = BZ_UI_SIZE_FIT
            },
            .padding = {5, 5, 5, 5},
    });
    bzUISetTextStyle(UI, node, (BzUITextStyle) {
            .text = txt,
            .font = font,
            .fontSpacing = 2 * uiGetScale() * scl,
            .fontSize = 62 * uiGetScale() * scl,
            .normal = WHITE,
            .hover = WHITE,
            .active = WHITE,
    });
    bzUISetTextShadowStyle(UI, node, (BzUITextShadowStyle) {
            .offset[BZ_UI_AXIS_X] = 2 * uiGetScale() * scl,
            .offset[BZ_UI_AXIS_Y] = 2 * uiGetScale() * scl,
            .normal = BLACK,
            .hover = BLACK,
            .active = BLACK,
    });
}

bool uiBaseTextButton(const char *txt, Font font, f32 scl) {
    BzUINode *node = bzUINodeMake(UI, bzUIKeyFromString(txt), &(BzUINodeDesc) {
            .flags = BZ_UI_DRAW_TEXT | BZ_UI_DRAW_TEXT_SHADOW | BZ_UI_ALIGN_CENTER,
            .semanticSize[BZ_UI_AXIS_X] = {
                    .kind = BZ_UI_SIZE_FIT,
            },
            .semanticSize[BZ_UI_AXIS_Y] = {
                    .kind = BZ_UI_SIZE_FIT
            },
            .padding = {5, 0, 5, 0},
            .margin = {5, 5, 5, 5},
    });
    bzUISetTextStyle(UI, node, (BzUITextStyle) {
            .text = txt,
            .font = font,
            .fontSpacing = 2 * uiGetScale() * scl,
            .fontSize = 62 * uiGetScale() * scl,
            .normal = WHITE,
            .hover = GRAY,
            .active = YELLOW
    });
    bzUISetTextShadowStyle(UI, node, (BzUITextShadowStyle) {
            .offset[BZ_UI_AXIS_X] = 2 * uiGetScale() * scl,
            .offset[BZ_UI_AXIS_Y] = 2 * uiGetScale() * scl,
            .normal = BLACK,
            .hover = BLACK,
            .active = BLACK,
    });
    return bzUIGetInteraction(UI, node).clicked;
}
void uiBaseCheckbox(const char *txt, Font font, f32 scl, bool *check) {
    BZ_ASSERT(check);
    bzUIPushDiv(UI, (BzUISize) {BZ_UI_SIZE_CHILD_SUM}, (BzUISize) {BZ_UI_SIZE_CHILD_MAX});
    bzUISetParentLayout(UI, (BzUILayout) {
        BZ_UI_LAYOUT_FLEX_BOX,
        BZ_UI_FLEX_DIR_ROW | BZ_UI_FLEX_ALIGN_CENTER | BZ_UI_FLEX_JUSTIFY_START
    });

    f32 size = 16 * uiGetScale() * scl;
    BzUINode *checkbox = bzUINodeMake(UI, bzUIGetUniqueKey(UI), &(BzUINodeDesc) {
        .flags = BZ_UI_CLICKABLE | BZ_UI_DRAW_BACKGROUND | BZ_UI_DRAW_BORDER,
        .semanticSize[BZ_UI_AXIS_X] = (BzUISize) { BZ_UI_SIZE_PIXELS, size},
        .semanticSize[BZ_UI_AXIS_Y] = (BzUISize) { BZ_UI_SIZE_PIXELS, size},
        .margin = {0, 0, 10 * uiGetScale() * scl, 0 }
    });
    bzUISetBackgroundStyle(UI, checkbox, (BzUIBackgroundStyle) {
        .normal = *check ? WHITE : BLACK,
        .hover  = GRAY,
        .active = YELLOW,
    });
    bzUISetBorderStyle(UI, checkbox, (BzUIBorderStyle) {
        .thickness = 5.0f * uiGetScale() * scl,
        .normal = BLACK,
        .hover  = BLACK,
        .active = BLACK,
    });

    if (bzUIGetInteraction(UI, checkbox).clicked) {
        *check = !*check;
    }

    BzUINode *label = bzUINodeMake(UI, bzUIKeyFromString(txt), &(BzUINodeDesc) {
            .flags = BZ_UI_DRAW_TEXT | BZ_UI_DRAW_TEXT_SHADOW | BZ_UI_ALIGN_CENTER,
            .semanticSize[BZ_UI_AXIS_X] = {
                    .kind = BZ_UI_SIZE_FIT,
            },
            .semanticSize[BZ_UI_AXIS_Y] = {
                    .kind = BZ_UI_SIZE_FIT
            },
    });
    bzUISetTextStyle(UI, label, (BzUITextStyle) {
            .text = txt,
            .font = font,
            .fontSpacing = 2 * uiGetScale() * scl,
            .fontSize = 32 * uiGetScale() * scl,
            .normal = WHITE,
            .hover = GRAY,
            .active = YELLOW
    });
    bzUISetTextShadowStyle(UI, label, (BzUITextShadowStyle) {
            .offset[BZ_UI_AXIS_X] = 2 * uiGetScale() * scl,
            .offset[BZ_UI_AXIS_Y] = 2 * uiGetScale() * scl,
            .normal = BLACK,
            .hover = BLACK,
            .active = BLACK,
    });
    if (bzUIGetInteraction(UI, label).clicked) {
        *check = !*check;
    }

    bzUIPopParent(UI);
}
void uiBaseSlider(const char *txt, Font font, f32 scl, f32 *value, f32 min, f32 max) {
    BZ_ASSERT(value);
    bzUIPushDiv(UI, (BzUISize) {BZ_UI_SIZE_CHILD_SUM}, (BzUISize) {BZ_UI_SIZE_CHILD_MAX});
    bzUISetParentLayout(UI, (BzUILayout) {
            BZ_UI_LAYOUT_FLEX_BOX,
            BZ_UI_FLEX_DIR_ROW | BZ_UI_FLEX_ALIGN_CENTER | BZ_UI_FLEX_JUSTIFY_SPACE_BETWEEN
    });

    uiBaseLabel(txt, font, 0.6 * scl);

    bzUIPushDiv(UI, (BzUISize) {BZ_UI_SIZE_CHILD_SUM}, (BzUISize) { BZ_UI_SIZE_CHILD_MAX});
    bzUISetParentLayout(UI, (BzUILayout) {
        BZ_UI_LAYOUT_FLEX_BOX,
        BZ_UI_FLEX_DIR_ROW | BZ_UI_FLEX_ALIGN_CENTER | BZ_UI_FLEX_JUSTIFY_END
    });

    char buf[32];
    snprintf(buf, sizeof(buf), "-##%s", txt);
    if (uiBaseTextButton(buf, font, 0.6 * scl))
        (*value)--;
    *value = BZ_MAX(*value, min);

    snprintf(buf, sizeof(buf), "%2.0f##%s", *value, txt);
    uiBaseLabel(buf, font, 0.6 * scl);

    snprintf(buf, sizeof(buf), "+##%s", txt);
    if (uiBaseTextButton(buf, font, 0.6 * scl))
        (*value)++;
    *value = BZ_MIN(*value, max);
    bzUIPopParent(UI);

    bzUIPopParent(UI);
}

void uiMainMenuLabel(const char *txt) {
    uiBaseLabel(txt, getFont(), 1.8f);
}

bool uiMainMenuButton(const char *txt) {
    return uiBaseTextButton(txt, getFont(), 0.8f);
}

void uiSettingsLabel(const char *txt) {
    uiBaseLabel(txt, getFont(), 0.8f);
}
bool uiSettingsButton(const char *txt) {
    return uiBaseTextButton(txt, getFont(), 0.7f);
}
void uiSettingsCheckbox(const char *txt, bool *check) {
    uiBaseCheckbox(txt, getFont(), 1.0f, check);
}
void uiSettingsSlider(const char *txt, f32 *value) {
    uiBaseSlider(txt, getFont(), 1.0f, value, 0, 10);
}

void uiGameResCount(i32 amount, i32 capacity, Rectangle icon, Texture2D texture) {
    bzUIPushDiv(UI, (BzUISize) { BZ_UI_SIZE_CHILD_SUM },
                (BzUISize) { BZ_UI_SIZE_CHILD_MAX });
    bzUISetParentLayout(UI, (BzUILayout) {
        BZ_UI_LAYOUT_FLEX_BOX,
        BZ_UI_FLEX_DIR_ROW | BZ_UI_FLEX_ALIGN_CENTER
    });
    char buf[64];
    BzUIKey id = bzUIGetUniqueKey(UI);
    if (capacity == -1)
        snprintf(buf, sizeof(buf), "%d##%d", amount, id);
    else
        snprintf(buf, sizeof(buf), "%d/%d##%d", amount, capacity, id);
    const f32 scl = 0.4f;
    uiBaseLabel(buf, getFont(), scl);

    BzUINode *iconNode = bzUINodeMake(UI, id, &(BzUINodeDesc) {
        .flags = BZ_UI_DRAW_SPRITE | BZ_UI_ALIGN_CENTER,
        .semanticSize[BZ_UI_AXIS_X] = {
                BZ_UI_SIZE_PIXELS, 80 * scl * uiGetScale(),
        },
        .semanticSize[BZ_UI_AXIS_Y] = {
                BZ_UI_SIZE_PIXELS, 80 * scl * uiGetScale(),
        },
        .margin = {0, 0, 20 * uiGetScale(), 0}
    });
    bzUISetSpriteStyle(UI, iconNode, (BzUISpriteStyle) {
        .rec = icon,
        .texture = texture,
        .tintNormal = WHITE,
        .tintHover = WHITE,
        .tintActive = WHITE,
    });

    bzUIPopParent(UI);
}
