// The MIT License (MIT)
//
// Copyright (C) 2026 Scott Duensing
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

// 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 "dvxRes.h"
#include "dvxWm.h"
#include "box/box.h"
#include "button/button.h"
#include "imageButton/imgBtn.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
#define TBX_TOOLTIP_LEN  64   // tooltip text loaded from the .wgt "name" resource
#define TBX_RES_NAME_LEN 32   // resource name scratch buffer

// .wgt resource contract: a toolbox icon and display name per interface;
// the second and later interfaces in one .wgt use a "-N" suffix.
#define TBX_RES_ICON        "icon24"
#define TBX_RES_NAME        "name"
#define TBX_RES_SUFFIX_FMT  "%s-%d"

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

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

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

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

// Function prototypes
static void onTbxClose(WindowT *win);
static void onToolClick(WidgetT *w);


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


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;
    }
}


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

    WindowT *win = dvxCreateWindow(ctx, "Toolbox", 0, y, 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[TBX_RES_NAME_LEN];
            char nameResName[TBX_RES_NAME_LEN];

            if (pathIdx <= 1) {
                snprintf(iconResName, sizeof(iconResName), "%s", TBX_RES_ICON);
                snprintf(nameResName, sizeof(nameResName), "%s", TBX_RES_NAME);
            } else {
                snprintf(iconResName, sizeof(iconResName), TBX_RES_SUFFIX_FMT, TBX_RES_ICON, (int)pathIdx);
                snprintf(nameResName, sizeof(nameResName), TBX_RES_SUFFIX_FMT, TBX_RES_NAME, (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 = 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;
}


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

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