/*
 * wikipedia.h
 * Shared header for the MontaukOS Wikipedia GUI client
 * Copyright (c) 2026 Daniel Hammer
 */

#pragma once

#include <montauk/syscall.h>
#include <montauk/string.h>
#include <montauk/heap.h>
#include <gui/mtk.hpp>
#include <gui/mtk/settings.hpp>
#include <gui/standalone.hpp>
#include <gui/svg.hpp>
#include <gui/truetype.hpp>
#include <tls/tls.hpp>

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

using namespace gui;
using namespace gui::colors;

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

static constexpr int INIT_W       = 820;
static constexpr int INIT_H       = 580;
static constexpr int SCROLLBAR_W  = mtk::SCROLLBAR_W;
static constexpr int TEXT_PAD     = 16;
static constexpr int RESP_MAX     = 131072;
static constexpr int MAX_LINES    = 2000;

inline const char WIKI_HOST[] = "en.wikipedia.org";
inline const char DISPLAY_ICON_PATH[] = "0:/icons/cog.svg";

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

struct WikiLine {
    char         text[256];
    Color        color;
    int          font_size;
    TrueTypeFont* font;
    int          indent;
};

enum class AppPhase { WELCOME, IDLE, LOADING, DONE, ERR };
enum class ReaderTextSize : uint8_t { SMALL = 0, MEDIUM, LARGE, COUNT };
enum class ReaderFontFace : uint8_t { SANS = 0, SERIF, BOOK, COUNT };

struct ReaderPalette {
    Color page_bg;
    Color control_bg;
    Color toolbar_bg;
    Color border;
    Color text;
    Color heading;
    Color muted;
    Color accent;
    Color accent_hover;
    Color accent_soft;
    Color danger;
    Color danger_hover;
    Color disabled_bg;
    Color disabled_fg;
};

struct ReaderToolbarLayout {
    Rect search_field;
    Rect display_button;
    Rect search_button;
    Rect text_size_buttons[(int)ReaderTextSize::COUNT];
    Rect font_buttons[(int)ReaderFontFace::COUNT];
    Rect text_size_label;
    Rect font_face_label;
    int sep_x;
    bool show_labels;
};

static constexpr int READER_TEXT_SIZE_COUNT = (int)ReaderTextSize::COUNT;
static constexpr int READER_FONT_FACE_COUNT = (int)ReaderFontFace::COUNT;

// ============================================================================
// Global state (extern -- defined in state.cpp)
// ============================================================================

extern int           TOOLBAR_H;
extern int           FONT_SIZE;
extern int           TITLE_SIZE;
extern int           SECTION_SIZE;

extern AppPhase      g_phase;
extern char          g_query[256];
extern mtk::TextInputState g_query_input;
extern char          g_status[256];
extern int           g_scroll_y;
extern int           g_line_count;
extern int           g_line_h;
extern int           g_win_w;
extern int           g_win_h;
extern int           g_mouse_x;
extern int           g_mouse_y;
extern bool          g_search_focused;
extern bool          g_scroll_dragging;
extern int           g_scroll_drag_offset;
extern bool          g_display_controls_open;
extern ReaderTextSize g_reader_text_size;
extern ReaderFontFace g_reader_font_face;
extern char          g_title[512];
extern int           g_extract_len;
extern int           g_base_font_size;
extern int           g_base_title_size;
extern int           g_base_section_size;
extern Color         g_accent;
extern bool          g_welcome_feature_loaded;
extern char          g_welcome_feature_title[256];
extern char          g_welcome_feature_extract[1024];
extern char          g_welcome_status[192];
extern char          g_welcome_date[16];

extern WikiLine*     g_lines;
extern char*         g_resp_buf;
extern char*         g_extract_buf;

extern TrueTypeFont* g_font;
extern TrueTypeFont* g_font_serif;
extern TrueTypeFont* g_body_fonts[READER_FONT_FACE_COUNT];
extern TrueTypeFont* g_heading_fonts[READER_FONT_FACE_COUNT];
extern SvgIcon       g_display_icon;
extern SvgIcon       g_display_icon_active;

extern bool          g_tls_ready;
extern uint32_t      g_server_ip;
extern tls::TrustAnchors g_tas;

extern const char*   g_text_size_labels[READER_TEXT_SIZE_COUNT];
extern const char*   g_font_face_labels[READER_FONT_FACE_COUNT];

// ============================================================================
// theme.cpp -- palette, theme, layout, scaling
// ============================================================================

ReaderPalette reader_palette();
mtk::Theme    wiki_theme();
TrueTypeFont* current_body_font();
TrueTypeFont* current_heading_font();
void apply_reader_preferences();
void apply_scale(int scale);
void update_toolbar_height();
void reload_display_icons();

int  search_control_h();
int  reader_button_h();
int  display_toggle_icon_size();
int  display_toggle_button_w();
int  search_row_y();
int  reader_row_y();

ReaderToolbarLayout toolbar_layout();
Rect content_rect();
Rect article_column_rect();
Rect document_column_rect();
Rect search_button_rect();
Rect search_field_rect();
Rect scrollbar_track_rect();
Rect scrollbar_thumb_rect();

int  visible_line_count();
int  max_scroll_lines();
bool document_scrollable();
void clamp_scroll();
bool mouse_in_rect(const Rect& rect);
void set_scroll_from_thumb_top(int thumb_top);
int  document_top_pad();

// ============================================================================
// text.cpp -- encoding, HTTP/URL/JSON parsing
// ============================================================================

int      encode_single_byte_codepoint(unsigned codepoint);
void     append_codepoint(char* out, int* j, int maxOut, unsigned codepoint);
void     underscores_to_spaces(char* text);
bool     is_main_page_query(const char* query);
unsigned decode_utf8_codepoint(const char* buf, int len, int* consumed);

int find_header_end(const char* buf, int len);
int parse_status_code(const char* buf, int len);
int find_substr(const char* buf, int len, const char* needle);

int url_encode_title(const char* in, char* out, int maxLen);

int extract_json_string(const char* buf, int len, const char* key,
                        char* out, int maxOut);

// ============================================================================
// document.cpp -- display line building
// ============================================================================

void add_line(const char* text, int len, Color color, int size,
              TrueTypeFont* font, int indent = 0);
void add_spacer(int size);
void wrap_text(TrueTypeFont* font, int size, const char* text, int textLen,
               int max_px, Color color, int indent = 0);
void build_display_lines(const char* title, const char* extract, int extractLen,
                         bool preserve_scroll = false);
void build_welcome_lines(bool preserve_scroll = false);
void rebuild_current_document(bool preserve_scroll = true);
void apply_reader_setting_change();
bool handle_reader_option_click(int mx, int my);

// ============================================================================
// network.cpp -- TLS fetch, welcome fetch, search
// ============================================================================

int  wiki_fetch(const char* path, char* respBuf, int respMax);
bool ensure_wiki_tls_ready(char* err, int err_len);
bool welcome_feed_path(char* path, int path_len);
void do_welcome_fetch();
void do_search(const char* query);

// ============================================================================
// render.cpp -- drawing
// ============================================================================

void draw_display_toggle_button(Canvas& canvas,
                                const Rect& bounds,
                                const mtk::WidgetState& state,
                                const mtk::Theme& theme);
void render_message(Canvas& canvas, const Rect& content, const char* text, Color color);
void render(Canvas& canvas);
