// ideDesigner.h -- DVX BASIC form designer
//
// Design-time data model and design surface for visual form editing.
// Controls are stored as pure data (not live widgets) and rendered
// onto a Canvas widget. The designer reads and writes .frm files.

#ifndef IDE_DESIGNER_H
#define IDE_DESIGNER_H

#include "dvxApp.h"
#include "dvxWgt.h"
#include "canvas/canvas.h"
#include "../formrt/formrt.h"

#include "stb_ds_wrap.h"

#include <stdint.h>
#include <stdbool.h>

// ============================================================
// Limits
// ============================================================

#define DSGN_MAX_NAME       32
#define DSGN_MAX_TEXT       256
#define DSGN_MAX_PROPS      32
#define DSGN_GRID_SIZE       8
#define DSGN_HANDLE_SIZE     6
#define DSGN_MENU_ID_BASE    20000  // base ID for designer preview menu items

// ============================================================
// Design-time property (stored as key=value strings)
// ============================================================

typedef struct {
    char name[DSGN_MAX_NAME];
    char value[DSGN_MAX_TEXT];
} DsgnPropT;

// ============================================================
// Design-time menu item (flat array with level for tree structure)
// ============================================================

typedef struct {
    char    caption[DSGN_MAX_TEXT];  // "&File", "-" for separator
    char    name[DSGN_MAX_NAME];    // "mnuFile"
    int32_t level;                   // 0 = top-level menu, 1 = item, 2+ = submenu
    bool    checked;
    bool    radioCheck;              // true = radio bullet instead of checkmark
    bool    enabled;                 // default true
} DsgnMenuItemT;

// ============================================================
// Design-time control
// ============================================================

typedef struct {
    char       name[DSGN_MAX_NAME];
    char       typeName[DSGN_MAX_NAME];
    char       parentName[DSGN_MAX_NAME]; // empty = top-level (child of form)
    int32_t    index;       // control array index (-1 = not in array)
    int32_t    left;
    int32_t    top;
    int32_t    width;
    int32_t    height;
    int32_t    maxWidth;    // 0 = no cap (stretch to fill)
    int32_t    maxHeight;   // 0 = no cap (stretch to fill)
    int32_t    weight;      // layout weight (0 = fixed size, >0 = share extra space)
    char       helpTopic[DSGN_MAX_NAME]; // help topic ID for F1
    DsgnPropT  props[DSGN_MAX_PROPS];
    int32_t    propCount;
    WidgetT   *widget;      // live widget (created at design time for WYSIWYG)
} DsgnControlT;

// ============================================================
// Design-time form
// ============================================================

typedef struct {
    char            name[DSGN_MAX_NAME];
    char            caption[DSGN_MAX_TEXT];
    int32_t         width;
    int32_t         height;
    int32_t         left;           // initial X position (0 = default)
    int32_t         top;            // initial Y position (0 = default)
    char            layout[DSGN_MAX_NAME]; // "VBox" or "HBox" (contentBox type)
    bool            centered;       // true = center on screen, false = use left/top
    bool            autoSize;       // true = dvxFitWindow, false = use width/height
    bool            resizable;      // true = user can resize at runtime
    char            helpTopic[DSGN_MAX_NAME]; // form-level help topic
    DsgnControlT  **controls;      // stb_ds array of heap-allocated pointers
    DsgnMenuItemT  *menuItems;     // stb_ds dynamic array (NULL if no menus)
    bool            dirty;
    WidgetT        *contentBox;     // VBox parent for live widgets
    char           *code;           // BASIC code section (malloc'd, after End block)
} DsgnFormT;

// ============================================================
// Active tool
// ============================================================
//
// Empty string = pointer (select/move) mode.
// Non-empty = basName of the widget type to place.

#define DSGN_TOOL_NONE ""  // pointer mode

// ============================================================
// Grab handle IDs
// ============================================================

typedef enum {
    HANDLE_NONE = -1,
    HANDLE_E = 0,       // resize width
    HANDLE_S,           // resize height
    HANDLE_SE,          // resize both
    HANDLE_COUNT = 3
} DsgnHandleE;

// ============================================================
// Interaction mode
// ============================================================

typedef enum {
    DSGN_IDLE,
    DSGN_REORDERING,    // dragging control up/down in the VBox
    DSGN_RESIZING
} DsgnModeE;

// ============================================================
// Designer state
// ============================================================

typedef struct {
    DsgnFormT     *form;
    int32_t        selectedIdx;     // -1 = form itself selected
    char           activeTool[DSGN_MAX_NAME]; // "" = pointer, else basName to place
    DsgnModeE      mode;
    DsgnHandleE    activeHandle;
    int32_t        dragStartY;      // mouse Y at drag start (for reorder)
    int32_t        dragOrigWidth;   // widget size at resize start
    int32_t        dragOrigHeight;
    int32_t        dragStartX;      // mouse X at resize start
    WindowT       *formWin;
    AppContextT   *ctx;
    const char    *projectDir;     // project directory (for resolving relative paths)
} DsgnStateT;

// ============================================================
// API
// ============================================================

// Initialize designer state.
void dsgnInit(DsgnStateT *ds, AppContextT *ctx);

// Set the canvas overlay widget (for grab handles).
void dsgnSetCanvas(DsgnStateT *ds, WidgetT *canvas);

// Create live widgets for all controls in the form.
// Call after dsgnLoadFrm or dsgnNewForm, with the form window's contentBox.
void dsgnCreateWidgets(DsgnStateT *ds, WidgetT *contentBox);

// Load a .frm file into the designer.
bool dsgnLoadFrm(DsgnStateT *ds, const char *source, int32_t sourceLen);

// Save the designer form to .frm text format.
// Returns the number of bytes written (excluding null), or -1 on error.
int32_t dsgnSaveFrm(const DsgnStateT *ds, char *buf, int32_t bufSize);

// Create a new blank form.
void dsgnNewForm(DsgnStateT *ds, const char *name);

// Repaint the design surface.
void dsgnPaint(DsgnStateT *ds);

// Draw selection handles over the painted window surface.
void dsgnPaintOverlay(DsgnStateT *ds, int32_t winX, int32_t winY);

// Handle mouse click on the design surface.
void dsgnOnMouse(DsgnStateT *ds, int32_t x, int32_t y, bool drag);

// Handle key press in design view.
void dsgnOnKey(DsgnStateT *ds, int32_t key);

// Get the name of the selected control (or form name if nothing selected).
const char *dsgnSelectedName(const DsgnStateT *ds);

// Get the default event name for a control type.
const char *dsgnDefaultEvent(const char *typeName);

// Auto-generate a unique control name for the given type.
void dsgnAutoName(const DsgnStateT *ds, const char *typeName, char *buf, int32_t bufSize);

// Check if a control type is a container (can hold children).
bool dsgnIsContainer(const char *typeName);

// Free designer resources.
void dsgnFree(DsgnStateT *ds);

// Create a live design-time widget for a given VB type name.
WidgetT *dsgnCreateDesignWidget(const char *vbTypeName, WidgetT *parent);

// Build a display-only menu bar on a window from the form's menuItems.
// Used in the form designer to preview the menu layout.
void dsgnBuildPreviewMenuBar(WindowT *win, const DsgnFormT *form);

// Create a layout container (VBox/HBox/WrapBox) from a layout name string.
// For VBox, reuses the root directly. For HBox/WrapBox, creates a child.
WidgetT *dsgnCreateContentBox(WidgetT *root, const char *layout);

// Create and configure a window from form properties.
// Shared by the designer and runtime to ensure consistent behavior.
// Creates the window, widget root, and layout container (VBox/HBox/WrapBox).
// Applies sizing (autoSize or explicit) and positioning (centered or explicit).
// On success, sets *outRoot and *outContentBox and returns the window.
// On failure, returns NULL.
WindowT *dsgnCreateFormWindow(AppContextT *ctx, const char *title, const char *layout, bool resizable, bool centered, bool autoSize, int32_t width, int32_t height, int32_t left, int32_t top, WidgetT **outRoot, WidgetT **outContentBox);

// ============================================================
// Code rename support (implemented in ideMain.c)
// ============================================================
//
// Rename all references to a form or control in project .bas files.
// Replaces OldName. -> NewName. and OldName_ -> NewName_ (case-insensitive,
// word-boundary aware). Also handles FormName.ControlName. patterns.

void ideRenameInCode(const char *oldName, const char *newName);

#endif // IDE_DESIGNER_H
