#pragma once
// ui_widgets.h - Immediate-mode widgets built on top of Clay.
//
// Each widget function takes a unique string ID, the value to display/edit,
// and returns whether the value was changed (or the widget was activated).
// The caller owns all data — the widget layer only stores transient UI state
// like which text field is focused or which dropdown is open.

#include "ui/ui_core.h"
#include "ui/ui_icons.h"
#include "platform/platform.h"

////////////////////////////////
// Widget state (global, managed by widget layer)

#define UI_WIDGET_MAX_DROPDOWN_ITEMS 32
#define UI_WIDGET_MAX_TEXT_INPUTS    16
#define UI_WIDGET_MAX_WINDOWS       16

struct UI_ModalState {
    B32      active;
    U32 id;       // Hash of the modal's string ID
    S32      result;   // Button index pressed, -1 = pending
};

struct UI_WindowSlot {
    U32 id;       // Hash of the window's string ID (0 = unused)
    Vec2F32  position;
    Vec2F32  size;
    B32      open;
    S16  z_order;
};

struct UI_KnobDragState {
    U32 dragging_id;   // Hash of the knob being dragged (0 = none)
    F32      drag_start_y;  // Mouse Y when drag started
    F32      drag_start_x;  // Mouse X when drag started (for h-slider)
    F32      value_at_start; // Value when drag started
    B32      was_shift;     // Shift state last frame (to re-anchor on change)
    U32 last_click_id; // Knob hash of last click (for F64-click detection)
    S32      last_click_frame; // Frame number of last click
};

struct UI_DragState {
    U32 dragging_id;  // Window ID currently being dragged (0 = none)
    Vec2F32  drag_anchor;  // Mouse position when drag started
    Vec2F32  pos_anchor;   // Window position when drag started
};

struct UI_WidgetState {
    // Text input focus
    U32 focused_id;       // Clay element ID hash of the focused text input (0 = none)
    S32  cursor_pos;       // Cursor position in focused text input
    F32      cursor_blink;     // Blink timer (seconds)

    // Text selection (sel_start == sel_end means no selection)
    S32  sel_start;        // Selection anchor (where selection began)
    S32  sel_end;          // Selection extent (moves with cursor)

    // Tab cycling: registered text input IDs in order of declaration
    U32 text_input_ids[UI_WIDGET_MAX_TEXT_INPUTS];
    S32  text_input_count;
    B32      tab_pressed;      // True on the frame Tab was pressed

    // Dropdown
    U32 open_dropdown_id; // Clay element ID hash of the open dropdown (0 = none)

    // Input for this frame
    PlatformInput input;

    // Click detection
    B32 mouse_clicked; // true on the frame mouse transitions from up->down

    // Modal state
    UI_ModalState modal;

    // Window state
    UI_WindowSlot windows[UI_WIDGET_MAX_WINDOWS];
    S32           window_count;
    S16       next_z;
    UI_DragState  drag;

    // Knob drag state
    UI_KnobDragState knob_drag;

    // Knob text edit state
    U32 knob_edit_id;         // Hash of knob in text edit mode (0 = none)
    char     knob_edit_buf[32];    // Text buffer for numeric entry
    S32      knob_edit_cursor;     // Cursor position in edit buffer
    S32      knob_edit_sel_start;  // Selection anchor
    S32      knob_edit_sel_end;    // Selection extent
};

extern UI_WidgetState g_wstate;

// Call once at startup
void ui_widgets_init();

// Call each frame before building widgets. Pass in the frame's input.
void ui_widgets_begin_frame(PlatformInput input);

// Call after changing theme to force text config refresh
void ui_widgets_theme_changed();

// Reset per-frame text input display buffer allocator (called by begin_frame, but
// can also be called manually if needed)
void ui_text_input_reset_display_bufs();

////////////////////////////////
// Widgets
// All IDs must be unique string literals (passed to CLAY_ID internally).

// Icon element (rendered via icon atlas)
void ui_icon(UI_IconID icon, F32 size, Clay_Color color);

// Simple label
void ui_label(const char *id, const char *text);

// Clickable button. Returns true on the frame it was clicked.
B32 ui_button(const char *id, const char *text);

// Checkbox. Toggles *value on click. Returns true if value changed.
B32 ui_checkbox(const char *id, const char *label, B32 *value);

// Radio button group. Sets *selected to the clicked index. Returns true if changed.
// options is an array of label strings, count is the number of options.
B32 ui_radio_group(const char *id, const char **options, S32 count, S32 *selected);

// Single-line text input. Edits buf in-place (null-terminated, max buf_size-1 chars).
// Returns true if the text changed this frame.
B32 ui_text_input(const char *id, char *buf, S32 buf_size);

// Dropdown / combo box. Sets *selected to chosen index. Returns true if changed.
// options is an array of label strings, count is the number of options.
B32 ui_dropdown(const char *id, const char **options, S32 count, S32 *selected);

// Modal dialog. Returns button index pressed (0-based), -1 if pending, -2 if Escape dismissed.
// Call every frame while active — it draws the overlay and dialog box.
S32 ui_modal(const char *id, const char *title, const char *message,
             const char **buttons, S32 button_count);
B32 ui_modal_is_active();

// Tab bar. Renders a row of tabs with active/inactive states.
// Returns the currently selected index. Clicking an inactive tab updates *selected.
S32 ui_tab_bar(const char *id, const char **labels, S32 count, S32 *selected);

// Draggable floating window. content_fn is called inside the window body each frame.
// *open is set to 0 when the close button is clicked. Returns true while window is open.
typedef void (*UI_WindowContentFn)(void *user_data);
B32 ui_window(const char *id, const char *title, B32 *open,
              Vec2F32 initial_pos, Vec2F32 initial_size,
              UI_WindowContentFn content_fn, void *user_data);

// Knob / potentiometer. Vertical drag to change value.
// unsigned (is_signed=0): value in [0, max_val]
// signed   (is_signed=1): value in [-max_val, +max_val]
// default_val: value restored on F64-click.
// editable: if true, clicking the value text opens a text input for direct entry.
// Hold Shift while dragging for fine control.
// Returns true if value changed this frame.
B32 ui_knob(const char *id, const char *label, F32 *value, F32 max_val, B32 is_signed, F32 default_val, B32 editable = 0);

// Horizontal slider. Drag left/right to change value.
B32 ui_slider_h(const char *id, const char *label, F32 *value, F32 max_val, B32 is_signed, F32 default_val, B32 editable = 0);

// Vertical slider. Drag up/down to change value.
B32 ui_slider_v(const char *id, const char *label, F32 *value, F32 max_val, B32 is_signed, F32 default_val, B32 editable = 0);

// DAW-style fader (vertical slider with fader cap icon).
B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_signed, F32 default_val, B32 editable = 0);
