// formrt.h -- DVX BASIC form runtime
//
// Bridges BASIC programs to the DVX widget system. Control types
// are resolved dynamically via WgtIfaceT interface descriptors
// registered by .wgt DXE files. Properties and methods are
// dispatched generically through descriptors. Events fire by
// looking up ControlName_EventName in the compiled module's
// procedure table and calling into the VM.

#ifndef DVXBASIC_FORMRT_H
#define DVXBASIC_FORMRT_H

#include "../runtime/vm.h"
#include "../runtime/values.h"
#include "dvxApp.h"
#include "dvxWgt.h"

// ============================================================
// Forward declarations
// ============================================================

typedef struct BasFormT BasFormT;
typedef struct BasControlT BasControlT;

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

#define BAS_MAX_CTRL_NAME        32
#define BAS_MAX_FRM_LINE_LEN    512
#define BAS_MAX_FRM_NESTING      16

// ============================================================
// Menu ID to name mapping for event dispatch
// ============================================================

typedef struct {
    int32_t         id;
    char            name[BAS_MAX_CTRL_NAME];
    BasControlT    *proxy;   // heap-allocated proxy for property access (widget=NULL, menuId stored)
} BasMenuIdMapT;

// ============================================================
// Control instance (a widget on a form)
// ============================================================

#define BAS_MAX_EVENT_OVERRIDES 16

// Event handler override (SetEvent)
typedef struct {
    char eventName[BAS_MAX_CTRL_NAME];    // e.g. "Click"
    char handlerName[BAS_MAX_CTRL_NAME];  // e.g. "HandleOkClick"
} BasEventOverrideT;

typedef struct BasControlT {
    char              name[BAS_MAX_CTRL_NAME];     // VB control name (e.g. "Command1")
    char              typeName[BAS_MAX_CTRL_NAME]; // VB type name (e.g. "CommandButton")
    int32_t           index;                       // control array index (-1 = not in array)
    WidgetT          *widget;                      // the DVX widget
    BasFormT         *form;                        // owning form
    const WgtIfaceT  *iface;                       // interface descriptor (from .wgt)
    char              dataSource[BAS_MAX_CTRL_NAME]; // name of Data control for binding
    char              dataField[BAS_MAX_CTRL_NAME];  // column name for binding
    char              helpTopic[BAS_MAX_CTRL_NAME];  // help topic ID for F1
    int32_t           menuId;                        // WM menu item ID (>0 for menu items, 0 for controls)
    BasEventOverrideT eventOverrides[BAS_MAX_EVENT_OVERRIDES];
    int32_t           eventOverrideCount;
} BasControlT;

// ============================================================
// Form instance (a DVX window with controls)
// ============================================================

typedef struct BasFormT {
    char              name[BAS_MAX_CTRL_NAME]; // form name (e.g. "Form1")
    WindowT          *window;                  // DVX window
    WidgetT          *root;                    // widget root (from wgtInitWindow)
    WidgetT          *contentBox;              // VBox/HBox for user controls
    AppContextT      *ctx;                     // DVX app context
    BasControlT     **controls;                // stb_ds array of heap-allocated pointers
    BasVmT           *vm;                      // VM for event dispatch
    BasModuleT       *module;                  // compiled module (for SUB lookup)
    // Form-level properties (accumulated during .frm parsing)
    int32_t           frmWidth;
    int32_t           frmHeight;
    int32_t           frmLeft;
    int32_t           frmTop;
    bool              frmResizable;
    bool              frmHasResizable;         // true if Resizable was explicitly set
    bool              frmCentered;
    bool              frmAutoSize;
    char              frmLayout[32];            // "VBox", "HBox", or "WrapBox"
    char              helpTopic[BAS_MAX_CTRL_NAME]; // form-level help topic
    // Per-form variable storage (allocated at load, freed at unload)
    BasValueT        *formVars;
    int32_t           formVarCount;
    // Menu ID to name mapping (for event dispatch)
    BasMenuIdMapT    *menuIdMap;
    int32_t           menuIdMapCount;
    // Synthetic control entry for the form itself, so that
    // FormName.Property works through the same getProp/setProp path.
    BasControlT       formCtrl;
} BasFormT;

// ============================================================
// Form runtime context
// ============================================================

// Cached .frm source for reload after unload
typedef struct {
    char    formName[BAS_MAX_CTRL_NAME];
    char   *frmSource;                         // malloc'd copy of .frm text
    int32_t frmSourceLen;
} BasFrmCacheT;

// Cached compiled form binary (for standalone apps)
typedef struct {
    char     formName[BAS_MAX_CTRL_NAME];
    uint8_t *data;                             // malloc'd binary data
    int32_t  dataLen;
} BasCfmCacheT;

typedef struct {
    AppContextT      *ctx;                     // DVX app context
    BasVmT           *vm;                      // shared VM instance
    BasModuleT       *module;                  // compiled module
    BasFormT        **forms;                    // stb_ds array of heap-allocated pointers
    BasFormT         *currentForm;             // form currently dispatching events
    char              helpFile[256];            // project help file path (for F1)
    BasFrmCacheT     *frmCache;                // stb_ds array of cached .frm sources
    int32_t           frmCacheCount;
    BasCfmCacheT     *cfmCache;                // stb_ds array of compiled form binaries
    int32_t           cfmCacheCount;
} BasFormRtT;

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

// Initialize the form runtime with a DVX context and a compiled module.
BasFormRtT *basFormRtCreate(AppContextT *ctx, BasVmT *vm, BasModuleT *module);

// Load all cached forms (.frm text and compiled binaries) and show the
// startup form. Called before bytecode execution begins.
void basFormRtLoadAllForms(BasFormRtT *rt, const char *startupFormName);

// VB-style event loop: pump DVX events until all forms are closed.
// Called after bytecode halts to keep the app alive for event handlers.
void basFormRtEventLoop(BasFormRtT *rt);

// Simple non-debug execution: run bytecode in slices with dvxUpdate
// between slices, then enter the event loop. Used by the standalone stub.
void basFormRtRunSimple(BasFormRtT *rt);

// Destroy the form runtime and all forms/controls.
void basFormRtDestroy(BasFormRtT *rt);

// Wire up the VM's UI callbacks to this form runtime.
void basFormRtBindVm(BasFormRtT *rt);

// ---- UI callback implementations (match BasUiCallbacksT) ----

BasValueT basFormRtGetProp(void *ctx, void *ctrlRef, const char *propName);
void      basFormRtSetProp(void *ctx, void *ctrlRef, const char *propName, BasValueT value);
BasValueT basFormRtCallMethod(void *ctx, void *ctrlRef, const char *methodName, BasValueT *args, int32_t argc);
void     *basFormRtCreateCtrl(void *ctx, void *formRef, const char *typeName, const char *ctrlName);
void     *basFormRtFindCtrl(void *ctx, void *formRef, const char *ctrlName);
void     *basFormRtFindCtrlIdx(void *ctx, void *formRef, const char *ctrlName, int32_t index);
void     *basFormRtLoadForm(void *ctx, const char *formName);
void      basFormRtUnloadForm(void *ctx, void *formRef);
void      basFormRtShowForm(void *ctx, void *formRef, bool modal);
void      basFormRtHideForm(void *ctx, void *formRef);
int32_t   basFormRtMsgBox(void *ctx, const char *message, int32_t flags, const char *title);

// ---- Extern call callbacks (shared by IDE and stub) ----

void *basExternResolve(void *ctx, const char *libName, const char *funcName);
BasValueT basExternCall(void *ctx, void *funcPtr, const char *libName, const char *funcName, BasValueT *args, int32_t argc, uint8_t retType);

// ---- Form caching ----

// Register .frm source text for lazy loading when bytecode calls Load.
void basFormRtRegisterFrm(BasFormRtT *rt, const char *formName, const char *source, int32_t sourceLen);

// Register a compiled form binary for lazy loading when bytecode calls Load.
void basFormRtRegisterCfm(BasFormRtT *rt, const char *formName, const uint8_t *data, int32_t dataLen);

// ---- Widget creation ----

WidgetT  *createWidget(const char *wgtTypeName, WidgetT *parent);

// ---- Form window creation ----

WidgetT  *basFormRtCreateContentBox(WidgetT *root, const char *layout);
WindowT  *basFormRtCreateFormWindow(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);

// ---- Dynamic form/control API ----

void     *basFormRtCreateForm(void *ctx, const char *formName, int32_t width, int32_t height);
void     *basFormRtCreateCtrlEx(void *ctx, void *formRef, const char *typeName, const char *ctrlName, void *parentRef);
void      basFormRtSetEvent(void *ctx, void *ctrlRef, const char *eventName, const char *handlerName);
void      basFormRtRemoveCtrl(void *ctx, void *formRef, const char *ctrlName);

// ---- Event dispatch ----

bool basFormRtFireEvent(BasFormRtT *rt, BasFormT *form, const char *ctrlName, const char *eventName);
bool basFormRtFireEventArgs(BasFormRtT *rt, BasFormT *form, const char *ctrlName, const char *eventName, const BasValueT *args, int32_t argCount);

// ---- Form file loading ----

BasFormT *basFormRtLoadFrm(BasFormRtT *rt, const char *source, int32_t sourceLen);

#endif // DVXBASIC_FORMRT_H
