/*
 * spreadsheet.h
 * Shared header for the MontaukOS spreadsheet app
 * Copyright (c) 2026 Daniel Hammer
 */

#pragma once

#include <montauk/syscall.h>
#include <montauk/string.h>
#include <montauk/heap.h>
#include <gui/gui.hpp>
#include <gui/truetype.hpp>
#include <gui/stb_math.h>
#include <gui/svg.hpp>

extern "C" {
#include <string.h>
#include <stdio.h>
}

using namespace gui;

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

static constexpr int INIT_W        = 900;
static constexpr int INIT_H        = 600;
static constexpr int TOOLBAR_H     = 36;
static constexpr int FORMULA_BAR_H = 36;
static constexpr int COL_HEADER_H  = 28;
static constexpr int ROW_HEADER_W  = 48;
static constexpr int STATUS_BAR_H  = 24;
static constexpr int SCROLL_STEP   = 50;
static constexpr int TB_BTN_SIZE   = 24;
static constexpr int TB_BTN_Y      = 6;
static constexpr int TB_BTN_RAD    = 3;

static constexpr int MAX_COLS      = 26;   // A-Z
static constexpr int MAX_ROWS      = 100;
static constexpr int DEF_COL_W     = 100;
static constexpr int MIN_COL_W     = 30;
static constexpr int ROW_H         = 26;
static constexpr int COL_RESIZE_GRAB = 5;  // pixels from border edge for grab zone
static constexpr int FILL_HANDLE_SIZE = 6;
static constexpr int AC_MAX_MATCHES  = 8;
static constexpr int DBLCLICK_MS     = 400;

static constexpr int CELL_TEXT_MAX = 128;
static constexpr int FONT_SIZE     = 18;
static constexpr int HEADER_FONT   = 16;

static constexpr Color BG_COLOR       = Color::from_rgb(0xFF, 0xFF, 0xFF);
static constexpr Color GRID_COLOR     = Color::from_rgb(0xD0, 0xD0, 0xD0);
static constexpr Color HEADER_BG      = Color::from_rgb(0xF0, 0xF0, 0xF0);
static constexpr Color HEADER_TEXT    = Color::from_rgb(0x55, 0x55, 0x55);
static constexpr Color CELL_TEXT      = Color::from_rgb(0x22, 0x22, 0x22);
static constexpr Color SELECT_BORDER  = Color::from_rgb(0x36, 0x7B, 0xF0);
static constexpr Color SELECT_FILL    = Color::from_rgb(0xD8, 0xE8, 0xFD);
static constexpr Color FORMULA_BG     = Color::from_rgb(0xFF, 0xFF, 0xFF);
static constexpr Color FORMULA_BORDER = Color::from_rgb(0xCC, 0xCC, 0xCC);
static constexpr Color STATUS_BG      = Color::from_rgb(0x2B, 0x3E, 0x50);
static constexpr Color STATUS_TEXT    = Color::from_rgb(0xFF, 0xFF, 0xFF);
static constexpr Color NUM_COLOR      = Color::from_rgb(0x10, 0x50, 0x90);
static constexpr Color ERR_COLOR      = Color::from_rgb(0xCC, 0x22, 0x22);
static constexpr Color TOOLBAR_BG    = Color::from_rgb(0xF5, 0xF5, 0xF5);
static constexpr Color TB_BTN_BG     = Color::from_rgb(0xE8, 0xE8, 0xE8);
static constexpr Color TB_BTN_ACTIVE = Color::from_rgb(0xC0, 0xD0, 0xE8);
static constexpr Color TB_SEP_COLOR  = Color::from_rgb(0xCC, 0xCC, 0xCC);

// ============================================================================
// Types
// ============================================================================

enum CellAlign : uint8_t { ALIGN_AUTO = 0, ALIGN_LEFT = 1, ALIGN_CENTER = 2, ALIGN_RIGHT = 3 };
enum NumFormat : uint8_t { FMT_AUTO = 0, FMT_DECIMAL = 1, FMT_CURRENCY = 2, FMT_PERCENT = 3 };

enum CellType : uint8_t {
    CT_EMPTY = 0,
    CT_TEXT  = 1,
    CT_NUMBER = 2,
    CT_FORMULA = 3,
    CT_ERROR = 4,
};

struct Cell {
    char input[CELL_TEXT_MAX];   // raw user input
    char display[CELL_TEXT_MAX]; // computed display string
    double value;                // numeric value (for formulas/numbers)
    CellType type;
    CellAlign align;
    NumFormat fmt;
    bool bold;
};

static constexpr int CLIP_MAX_CELLS = 256;
struct ClipCell {
    char text[CELL_TEXT_MAX];
    int  rel_col;
    int  rel_row;
    CellAlign align;
    NumFormat fmt;
    bool bold;
};

static constexpr int UNDO_MAX = 6;
struct UndoCellData {
    char input[CELL_TEXT_MAX];
    CellAlign align;
    NumFormat fmt;
    bool bold;
};
struct UndoEntry {
    UndoCellData cells[MAX_ROWS][MAX_COLS];
};

static constexpr int PATHBAR_H = 32;

// ============================================================================
// Toolbar button IDs (must match handle_toolbar_click and render order)
// ============================================================================

enum ToolBtnId {
    TB_OPEN,
    TB_SAVE,
    TB_CUT,
    TB_COPY,
    TB_PASTE,
    TB_BOLD,
    TB_AL,
    TB_AC,
    TB_AR,
    TB_FMT,
    TB_UNDO,
    TB_REDO,
    TB_COUNT
};
int tb_btn_x0(ToolBtnId id);
int tb_btn_x1(ToolBtnId id);

// ============================================================================
// Global state (extern — defined in main.cpp)
// ============================================================================

extern int g_win_w, g_win_h;
extern Cell g_cells[MAX_ROWS][MAX_COLS];
extern int g_sel_col, g_sel_row;
extern int g_scroll_x, g_scroll_y;
extern int g_col_widths[MAX_COLS];

extern bool g_editing;
extern char g_edit_buf[CELL_TEXT_MAX];
extern int  g_edit_len;
extern int  g_edit_cursor;

extern bool g_has_selection;
extern int  g_anchor_col, g_anchor_row;

extern ClipCell g_clipboard[CLIP_MAX_CELLS];
extern int  g_clip_count;
extern int  g_clip_cols, g_clip_rows;

extern char g_filepath[256];
extern bool g_modified;

extern bool g_pathbar_open;
extern bool g_pathbar_save;
extern char g_pathbar_text[256];
extern int  g_pathbar_len;
extern int  g_pathbar_cursor;

extern TrueTypeFont* g_font;
extern TrueTypeFont* g_font_bold;

extern bool g_fmt_dropdown_open;

extern bool g_col_resizing;
extern int  g_col_resize_idx;
extern int  g_col_resize_start_x;
extern int  g_col_resize_start_w;

extern UndoEntry* g_undo[UNDO_MAX + 1];
extern int g_undo_count;
extern int g_undo_pos;

// Formula autocomplete
extern bool g_ac_open;
extern int  g_ac_sel;
extern int  g_ac_count;
extern char g_ac_matches[AC_MAX_MATCHES][16];
extern char g_ac_hints[AC_MAX_MATCHES][32];

// Fill handle
extern bool g_fill_dragging;
extern int  g_fill_target_row;

// Mouse drag selection
extern bool g_mouse_selecting;

// Double-click detection
extern uint64_t g_last_click_ms;
extern int  g_last_click_col;
extern int  g_last_click_row;

// ============================================================================
// Function declarations — helpers.cpp
// ============================================================================

void px_fill(uint32_t* px, int bw, int bh, int x, int y, int w, int h, Color c);
void px_hline(uint32_t* px, int bw, int bh, int x, int y, int w, Color c);
void px_vline(uint32_t* px, int bw, int bh, int x, int y, int h, Color c);
void px_rect(uint32_t* px, int bw, int bh, int x, int y, int w, int h, Color c);
void px_fill_rounded(uint32_t* px, int bw, int bh, int x, int y, int w, int h, int r, Color c);

int  str_len(const char* s);
void str_cpy(char* dst, const char* src, int max);
bool is_digit(char c);
bool is_alpha(char c);
char to_upper(char c);
double str_to_double(const char* s, bool* ok);
void double_to_str(char* buf, int max, double v);
bool str_is_int(const char* s);
int  str_to_int(const char* s);
void int_to_str(char* dst, int max, int v);

// ============================================================================
// Function declarations — formula.cpp
// ============================================================================

void eval_cell(int col, int row);
void eval_all_cells();
int  col_x(int col);
int  content_width();
int  content_height();
void cell_name(char* buf, int col, int row);
void format_value(char* buf, int max, double val, NumFormat fmt);
void update_autocomplete();
void accept_autocomplete();
void adjust_formula_refs(const char* src, char* dst, int max, int dcol, int drow);

// ============================================================================
// Function declarations — fileio.cpp
// ============================================================================

void save_file();
void load_file(const char* path);

// ============================================================================
// Function declarations — edit.cpp
// ============================================================================

void undo_push();
void undo_do();
void redo_do();
void start_editing();
void commit_edit();
void cancel_edit();
void sel_range(int* c0, int* r0, int* c1, int* r1);
void clear_selection();
void copy_selection();
void cut_selection();
void paste_at_cursor();
void apply_bold_toggle();
void apply_align(CellAlign a);
void apply_format(NumFormat f);
void clamp_scroll();
void ensure_sel_visible();
void fill_down(int src_r0, int src_c0, int src_r1, int src_c1, int dst_r1);
void auto_fit_column(int col);

// ============================================================================
// Function declarations — render.cpp
// ============================================================================

void render(uint32_t* pixels);

// ============================================================================
// Icons
// ============================================================================

extern SvgIcon g_icon_folder;
extern SvgIcon g_icon_save;
extern SvgIcon g_icon_cut;
extern SvgIcon g_icon_copy;
extern SvgIcon g_icon_paste;

void ss_load_icons();
void ss_unload_icons();

// ============================================================================
// Function declarations — main.cpp
// ============================================================================

bool hit_cell(int mx, int my, int* out_col, int* out_row);
bool hit_fill_handle(int mx, int my);
bool handle_toolbar_click(int mx, int my);
bool handle_fmt_dropdown_click(int mx, int my);
