// ideToolbox.c -- DVX BASIC form designer toolbox window
//
// A small floating window with buttons for each registered widget
// type that has a basName (VB-style name). Built dynamically from
// the widget interface registry.

#include "ideToolbox.h"
#include "dvxApp.h"
#include "dvxResource.h"
#include "dvxWm.h"
#include "widgetBox.h"
#include "widgetButton.h"
#include "widgetImageButton.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

// ============================================================
// Constants
// ============================================================

#define TBX_COLS     4
#define TBX_WIN_W    120
#define TBX_WIN_H    250

// ============================================================
// Per-tool entry
// ============================================================

typedef struct {
    char typeName[DSGN_MAX_NAME];
    char tooltip[64];
} TbxToolEntryT;

// ============================================================
// Module state
// ============================================================

static DsgnStateT    *sDs      = NULL;
static TbxToolEntryT *sTbxTools = NULL; // stb_ds dynamic array

// ============================================================
// Callbacks
// ============================================================

static void onToolClick(WidgetT *w) {
    if (!sDs) {
        return;
    }

    int32_t toolIdx = (int32_t)(intptr_t)w->userData;

    if (toolIdx >= 0 && toolIdx < (int32_t)arrlen(sTbxTools)) {
        const char *typeName = sTbxTools[toolIdx].typeName;

        // Toggle: clicking the same tool again deselects it
        if (strcasecmp(sDs->activeTool, typeName) == 0) {
            sDs->activeTool[0] = '\0';
        } else {
            snprintf(sDs->activeTool, DSGN_MAX_NAME, "%s", typeName);
        }

        sDs->mode = DSGN_IDLE;
    }
}


static void onTbxClose(WindowT *win) {
    dvxHideWindow(sDs->ctx, win);
}


// ============================================================
// tbxCreate
// ============================================================

WindowT *tbxCreate(AppContextT *ctx, DsgnStateT *ds) {
    sDs = ds;
    arrsetlen(sTbxTools, 0);

    WindowT *win = dvxCreateWindow(ctx, "Toolbox", 0, 30, TBX_WIN_W, TBX_WIN_H, false);

    if (!win) {
        return NULL;
    }

    win->onClose = onTbxClose;

    WidgetT *root = wgtInitWindow(ctx, win);
    root->spacing = 0;

    // Enumerate all registered widget interfaces with a basName
    int32_t ifaceCount = wgtIfaceCount();
    int32_t col        = 0;
    WidgetT *row       = NULL;
    WidgetT **buttons  = NULL; // stb_ds array, parallel to sTbxTools

    for (int32_t i = 0; i < ifaceCount; i++) {
        const char *wgtName = NULL;
        const WgtIfaceT *iface = wgtIfaceAt(i, &wgtName);

        if (!iface || !iface->basName || !iface->basName[0]) {
            continue;
        }

        // Add tool entry
        TbxToolEntryT entry;
        memset(&entry, 0, sizeof(entry));
        snprintf(entry.typeName, DSGN_MAX_NAME, "%s", iface->basName);

        // Load icon data and tooltip from the .wgt file resources
        uint8_t *iconData  = NULL;
        int32_t  iconW     = 0;
        int32_t  iconH     = 0;
        int32_t  iconPitch = 0;
        const char *wgtPath = wgtIfaceGetPath(wgtName);
        int32_t pathIdx     = wgtIfaceGetPathIndex(wgtName);

        if (wgtPath) {
            // Build suffixed resource names: "icon24", "icon24-2", etc.
            char iconResName[32];
            char nameResName[32];

            if (pathIdx <= 1) {
                snprintf(iconResName, sizeof(iconResName), "icon24");
                snprintf(nameResName, sizeof(nameResName), "name");
            } else {
                snprintf(iconResName, sizeof(iconResName), "icon24-%d", (int)pathIdx);
                snprintf(nameResName, sizeof(nameResName), "name-%d", (int)pathIdx);
            }

            iconData = dvxResLoadIcon(ctx, wgtPath, iconResName, &iconW, &iconH, &iconPitch);
            dvxResLoadText(wgtPath, nameResName, entry.tooltip, sizeof(entry.tooltip));
        }

        if (!entry.tooltip[0]) {
            snprintf(entry.tooltip, sizeof(entry.tooltip), "%s", iface->basName);
        }

        arrput(sTbxTools, entry);
        int32_t toolIdx = (int32_t)arrlen(sTbxTools) - 1;

        // Start a new row every TBX_COLS buttons
        if (col == 0 || !row) {
            row = wgtHBox(root);
            row->spacing = 0;
        }

        // Create button in the current row
        WidgetT *btn = NULL;

        if (iconData) {
            btn = wgtImageButton(row, iconData, iconW, iconH, iconPitch);
        } else {
            btn = wgtButton(row, iface->basName);
        }

        btn->onClick  = onToolClick;
        btn->userData = (void *)(intptr_t)toolIdx;
        arrput(buttons, btn);

        col = (col + 1) % TBX_COLS;

        // Yield to keep the UI responsive while loading icons
        dvxUpdate(ctx);
    }

    // Set tooltips after array is finalized (arrput can reallocate)
    int32_t btnCount = (int32_t)arrlen(buttons);

    for (int32_t i = 0; i < btnCount; i++) {
        wgtSetTooltip(buttons[i], sTbxTools[i].tooltip);
    }

    arrfree(buttons);

    dvxFitWindow(ctx, win);
    return win;
}


// ============================================================
// tbxDestroy
// ============================================================

void tbxDestroy(AppContextT *ctx, WindowT *win) {
    if (win) {
        dvxDestroyWindow(ctx, win);
    }

    arrfree(sTbxTools);
    sTbxTools = NULL;
    sDs       = NULL;
}
