/*
 * input.cpp
 * Input handling
 * Copyright (c) 2026 Daniel Hammer
 */

#include "wordprocessor.hpp"
#include <gui/dialogs.hpp>
#include <gui/clipboard.hpp>

static void wp_set_status(WordProcessorState* wp, const char* msg) {
    if (!msg) msg = "";
    montauk::strncpy(wp->status_msg, msg, (int)sizeof(wp->status_msg) - 1);
    wp->status_msg[sizeof(wp->status_msg) - 1] = '\0';
}

static bool wp_copy_selection_to_clipboard(WordProcessorState* wp) {
    int len = 0;
    char* text = wp_selection_plain_text_alloc(wp, &len);
    if (text == nullptr || len <= 0) {
        if (text) montauk::mfree(text);
        wp_set_status(wp, "Nothing selected");
        return false;
    }

    bool ok = gui::clipboard_set_text(text, len);
    montauk::mfree(text);
    if (!ok) {
        wp_set_status(wp, "Copy failed");
        return false;
    }

    wp_set_status(wp, "Copied selection");
    return true;
}

static bool wp_cut_selection_to_clipboard(WordProcessorState* wp) {
    if (!wp_copy_selection_to_clipboard(wp))
        return false;

    wp_delete_selection(wp);
    wp_history_checkpoint(wp);
    wp_set_status(wp, "Cut selection");
    return true;
}

static bool wp_paste_from_clipboard(WordProcessorState* wp) {
    int len = 0;
    char* text = gui::clipboard_get_text_alloc(&len);
    if (text == nullptr || len <= 0) {
        if (text) montauk::mfree(text);
        wp_set_status(wp, "Clipboard is empty");
        return false;
    }

    bool ok = wp_replace_selection_with_text(wp, text, len);
    montauk::mfree(text);
    if (!ok) {
        wp_set_status(wp, "Clipboard text could not be inserted");
        return false;
    }

    wp_history_checkpoint(wp);
    wp_set_status(wp, "Pasted clipboard");
    return true;
}

bool wp_context_item_enabled(WordProcessorState* wp, int item) {
    switch (item) {
    case WP_CTX_CUT:
    case WP_CTX_COPY:
    case WP_CTX_DELETE:
        return wp && wp->has_selection;
    case WP_CTX_PASTE:
        return gui::clipboard_has_text();
    default:
        return false;
    }
}

void wp_build_context_items(WordProcessorState* wp,
                            mtk::ContextMenuItem items[WP_CTX_COUNT]) {
    items[WP_CTX_CUT] = {"Cut", WP_CTX_CUT,
                         wp_context_item_enabled(wp, WP_CTX_CUT)};
    items[WP_CTX_COPY] = {"Copy", WP_CTX_COPY,
                          wp_context_item_enabled(wp, WP_CTX_COPY)};
    items[WP_CTX_PASTE] = {"Paste", WP_CTX_PASTE,
                           wp_context_item_enabled(wp, WP_CTX_PASTE)};
    items[WP_CTX_DELETE] = {"Delete", WP_CTX_DELETE,
                            wp_context_item_enabled(wp, WP_CTX_DELETE)};
}

static bool wp_selection_contains_abs(WordProcessorState* wp, int abs) {
    if (!wp || !wp->has_selection) return false;
    int sel_s = 0;
    int sel_e = 0;
    wp_sel_range(wp, &sel_s, &sel_e);
    return abs >= sel_s && abs < sel_e;
}

static bool wp_perform_context_action(WordProcessorState* wp, int item) {
    if (!wp_context_item_enabled(wp, item)) return false;

    switch (item) {
    case WP_CTX_CUT:
        return wp_cut_selection_to_clipboard(wp);
    case WP_CTX_COPY:
        return wp_copy_selection_to_clipboard(wp);
    case WP_CTX_PASTE:
        return wp_paste_from_clipboard(wp);
    case WP_CTX_DELETE:
        wp_delete_selection(wp);
        wp_history_checkpoint(wp);
        wp_set_status(wp, "Deleted selection");
        return true;
    default:
        return false;
    }
}

static void wp_open_pathbar_for_open(WordProcessorState* wp) {
    char path[256] = {};
    char msg[160] = {};
    if (dialogs::open_file("Open Document", wp->filepath, path, sizeof(path), msg, sizeof(msg))) {
        wp_load_file(wp, path);
    } else if (msg[0]) {
        wp_start_pathbar(wp, false, wp->filepath);
    }
}

static void wp_open_print_dialog(WordProcessorState* wp) {
    char msg[160] = {};
    if (wp_print_document(wp, msg, sizeof(msg)) || msg[0])
        wp_set_status(wp, msg);
}

static void wp_make_pdf_suggested_name(WordProcessorState* wp, char* out, int out_len) {
    if (!out || out_len <= 0) return;

    const char* src = (wp && wp->filename[0]) ? wp->filename : "document";
    int last_dot = -1;
    for (int i = 0; src[i]; i++) {
        if (src[i] == '.') last_dot = i;
    }

    int copy_len = (last_dot > 0) ? last_dot : montauk::slen(src);
    if (copy_len > out_len - 5) copy_len = out_len - 5;
    if (copy_len < 0) copy_len = 0;
    montauk::memcpy(out, src, (uint64_t)copy_len);
    out[copy_len] = '\0';
    montauk::strncpy(out + copy_len, ".pdf", out_len - copy_len - 1);
    out[out_len - 1] = '\0';
}

static void wp_open_export_dialog(WordProcessorState* wp) {
    char path[256] = {};
    char suggested_name[128] = {};
    char msg[160] = {};

    wp_make_pdf_suggested_name(wp, suggested_name, sizeof(suggested_name));
    if (dialogs::save_file("Export PDF",
                           wp->filepath,
                           suggested_name,
                           path, sizeof(path),
                           msg, sizeof(msg))) {
        if (wp_export_pdf_document(wp, path, msg, sizeof(msg)) || msg[0])
            wp_set_status(wp, msg);
    } else if (msg[0]) {
        wp_set_status(wp, msg);
    }
}

static void wp_commit_pathbar(WordProcessorState* wp) {
    if (!wp->pathbar_text[0]) return;
    if (wp->pathbar_save_mode) {
        wp_set_filepath(wp, wp->pathbar_text);
        wp_save_file(wp);
    } else {
        wp_load_file(wp, wp->pathbar_text);
    }
    wp->show_pathbar = false;
}

static int wp_special_char_flyout_x() {
    int dx = WP_BTN_SECTION_X + 24 - WP_SPECIAL_CHAR_FLYOUT_W;
    if (dx + WP_SPECIAL_CHAR_FLYOUT_W > g_win_w) dx = g_win_w - WP_SPECIAL_CHAR_FLYOUT_W;
    return dx < 0 ? 0 : dx;
}

static int wp_divider_flyout_x() {
    int dx = WP_BTN_DIVIDER_X + 24 - WP_DIVIDER_FLYOUT_W;
    if (dx + WP_DIVIDER_FLYOUT_W > g_win_w) dx = g_win_w - WP_DIVIDER_FLYOUT_W;
    return dx < 0 ? 0 : dx;
}

static void wp_close_dropdowns(WordProcessorState* wp) {
    wp->font_dropdown_open = false;
    wp->size_dropdown_open = false;
    wp->line_spacing_dropdown_open = false;
    wp->divider_flyout_open = false;
    wp->special_char_flyout_open = false;
}

static void wp_insert_special_char(WordProcessorState* wp, uint8_t ch) {
    if (wp->has_selection) wp_delete_selection(wp);
    wp_insert_char(wp, (char)ch);
    wp_history_checkpoint(wp);
}

static void wp_insert_divider_choice(WordProcessorState* wp, uint8_t divider_type) {
    wp_insert_divider(wp, divider_type);
    wp_history_checkpoint(wp);
}

static int wp_hit_test_text(WordProcessorState* wp, int local_x, int local_y, int edit_y,
                          int page_off_x, int page_off_y) {
    int click_y = local_y - edit_y + wp->scrollbar.scroll_offset;
    // In page view mode, subtract the page y offset
    if (wp->page_view_mode) {
        click_y = local_y - page_off_y + wp->scrollbar.scroll_offset;
    }

    int target_line = wp->wrap_line_count - 1;
    for (int i = 0; i < wp->wrap_line_count; i++) {
        if (click_y >= wp->wrap_lines[i].y &&
            click_y < wp->wrap_lines[i].y + wp->wrap_lines[i].height) {
            target_line = i;
            break;
        }
    }

    WrapLine* wl = &wp->wrap_lines[target_line];
    if (wl->divider_type != PARA_DIVIDER_NONE)
        return wp_wrap_line_start(wp, target_line);

    // In page view mode, subtract the page x offset from click x
    int click_x = local_x;
    if (wp->page_view_mode) {
        click_x = local_x - page_off_x;
    }
    click_x -= wl->x;
    int ri = wl->run_idx;
    int ro = wl->run_offset;
    int chars_left = wl->char_count;
    int x = 0;
    int best_abs = wp_wrap_line_start(wp, target_line);

    if (click_x <= 0) return best_abs;

    while (chars_left > 0 && ri < wp->run_count) {
        StyledRun* r = &wp->runs[ri];
        TrueTypeFont* font = wp_get_font(r->font_id, r->flags);
        if (!font || !font->valid) {
            ri++;
            ro = 0;
            continue;
        }

        GlyphCache* gc = font->get_cache(wp_screen_font_pixels(r->size));
        int avail = r->len - ro;
        int to_check = avail < chars_left ? avail : chars_left;

        for (int ci = 0; ci < to_check; ci++) {
            char ch = r->text[ro + ci];
            CachedGlyph* g = (ch >= 32 || ch < 0) && ch != '\n'
                ? font->get_glyph(gc, (unsigned char)ch) : nullptr;
            int char_w = g ? g->advance : 0;

            if (x + char_w / 2 > click_x) return best_abs;
            x += char_w;
            best_abs++;
        }

        chars_left -= to_check;
        ro += to_check;
        if (ro >= r->len) {
            ri++;
            ro = 0;
        }
    }

    return best_abs;
}

void wp_handle_mouse(const Montauk::WinEvent& ev) {
    WordProcessorState* wp = &g_wp;
    int local_x = ev.mouse.x;
    int local_y = ev.mouse.y;
    int edit_y = WP_TOOLBAR_H + (wp->show_pathbar ? WP_PATHBAR_H : 0);
    int text_area_h = g_win_h - edit_y - WP_STATUS_H;

    // Handle pending page view toggle first (from toolbar button click)
    if (wp->pending_page_view_toggle) {
        wp->page_view_mode = !wp->page_view_mode;
        wp->pending_page_view_toggle = false;
        wp->wrap_dirty = true;
    }

    // Compute page offsets for hit testing (same logic as wp_render)
    int page_off_x = 0;
    int page_off_y = edit_y;
    int recompute_w = g_win_w;
    if (wp->page_view_mode) {
        page_off_x = (g_win_w - WP_A4_PAGE_W) / 2;
        if (page_off_x < 0) page_off_x = 0;
        page_off_y = edit_y + WP_PAGE_TOP_MARGIN;
        // Use A4 page width for wrap computation (to get proper margins)
        recompute_w = WP_A4_PAGE_W;
    }

    if (wp->context_menu.open) {
        if (ev.mouse.scroll != 0) {
            mtk::context_menu_close(wp->context_menu);
            return;
        }

        mtk::ContextMenuItem items[WP_CTX_COUNT];
        wp_build_context_items(wp, items);
        int action = mtk::context_menu_handle_mouse(wp->context_menu,
                                                    items, WP_CTX_COUNT,
                                                    local_x, local_y,
                                                    ev.mouse.buttons,
                                                    ev.mouse.prev_buttons,
                                                    g_win_w, g_win_h);
        if (action >= 0)
            wp_perform_context_action(wp, action);
        if (action != mtk::CONTEXT_MENU_NONE)
            return;
    }

    wp->scrollbar.handle_mouse(local_x, local_y, ev.mouse.buttons, ev.mouse.prev_buttons, ev.mouse.scroll);

    if (wp->font_dropdown_open && wp_left_pressed(ev.mouse.buttons, ev.mouse.prev_buttons)) {
        int dx = WP_FONT_DD_X;
        int dy = WP_TOOLBAR_H;
        int dh = FONT_COUNT * 26 + 4;
        if (local_x >= dx && local_x < dx + 110 && local_y >= dy && local_y < dy + dh) {
            int idx = (local_y - dy - 2) / 26;
            if (idx >= 0 && idx < FONT_COUNT) {
                if (wp->has_selection) wp_apply_style_to_selection(wp, 0, idx);
                wp->cur_font_id = (uint8_t)idx;
                if (wp->has_selection) wp_history_checkpoint(wp);
            }
        }
        wp->font_dropdown_open = false;
        return;
    }

    if (wp->size_dropdown_open && wp_left_pressed(ev.mouse.buttons, ev.mouse.prev_buttons)) {
        int dx = WP_SIZE_DD_X;
        int dy = WP_TOOLBAR_H;
        int dh = WP_SIZE_OPTION_COUNT * 26 + 4;
        if (local_x >= dx && local_x < dx + 56 && local_y >= dy && local_y < dy + dh) {
            int idx = (local_y - dy - 2) / 26;
            if (idx >= 0 && idx < WP_SIZE_OPTION_COUNT) {
                if (wp->has_selection) wp_apply_style_to_selection(wp, 1, WP_SIZE_OPTIONS[idx]);
                wp->cur_size = (uint8_t)WP_SIZE_OPTIONS[idx];
                wp->wrap_dirty = true;
                if (wp->has_selection) wp_history_checkpoint(wp);
            }
        }
        wp->size_dropdown_open = false;
        return;
    }

    if (wp->line_spacing_dropdown_open && wp_left_pressed(ev.mouse.buttons, ev.mouse.prev_buttons)) {
        int dx = WP_LINE_DD_X;
        int dy = WP_TOOLBAR_H;
        int dh = WP_LINE_SPACING_OPTION_COUNT * 26 + 4;
        if (local_x >= dx && local_x < dx + 64 && local_y >= dy && local_y < dy + dh) {
            int idx = (local_y - dy - 2) / 26;
            if (idx >= 0 && idx < WP_LINE_SPACING_OPTION_COUNT) {
                wp_set_line_spacing(wp, WP_LINE_SPACING_OPTIONS[idx]);
                wp_history_checkpoint(wp);
            }
        }
        wp->line_spacing_dropdown_open = false;
        return;
    }

    if (wp->divider_flyout_open && wp_left_pressed(ev.mouse.buttons, ev.mouse.prev_buttons)) {
        int dx = wp_divider_flyout_x();
        int dy = WP_TOOLBAR_H;
        int dh = WP_DIVIDER_OPTION_COUNT * WP_DIVIDER_ROW_H + 4;
        if (local_x >= dx && local_x < dx + WP_DIVIDER_FLYOUT_W && local_y >= dy && local_y < dy + dh) {
            int idx = (local_y - dy - 2) / WP_DIVIDER_ROW_H;
            if (idx >= 0 && idx < WP_DIVIDER_OPTION_COUNT)
                wp_insert_divider_choice(wp, WP_DIVIDER_OPTIONS[idx].type);
        }
        wp->divider_flyout_open = false;
        return;
    }

    if (wp->special_char_flyout_open && wp_left_pressed(ev.mouse.buttons, ev.mouse.prev_buttons)) {
        int dx = wp_special_char_flyout_x();
        int dy = WP_TOOLBAR_H;
        int dh = WP_SPECIAL_CHAR_OPTION_COUNT * WP_SPECIAL_CHAR_ROW_H + 4;
        if (local_x >= dx && local_x < dx + WP_SPECIAL_CHAR_FLYOUT_W && local_y >= dy && local_y < dy + dh) {
            int idx = (local_y - dy - 2) / WP_SPECIAL_CHAR_ROW_H;
            if (idx >= 0 && idx < WP_SPECIAL_CHAR_OPTION_COUNT)
                wp_insert_special_char(wp, WP_SPECIAL_CHAR_OPTIONS[idx].code);
        }
        wp->special_char_flyout_open = false;
        return;
    }

    if (wp_left_pressed(ev.mouse.buttons, ev.mouse.prev_buttons) && local_y < WP_TOOLBAR_H) {
        if (local_x >= WP_BTN_OPEN_X && local_x < WP_BTN_OPEN_X + 24 && local_y >= 6 && local_y < 30) {
            wp_open_pathbar_for_open(wp);
            return;
        }
        if (local_x >= WP_BTN_SAVE_X && local_x < WP_BTN_SAVE_X + 24 && local_y >= 6 && local_y < 30) {
            wp_save_file(wp);
            return;
        }
        if (local_x >= WP_BTN_PRINT_X && local_x < WP_BTN_PRINT_X + 24 && local_y >= 6 && local_y < 30) {
            wp_open_print_dialog(wp);
            return;
        }
        if (local_x >= WP_BTN_EXPORT_X && local_x < WP_BTN_EXPORT_X + 24 && local_y >= 6 && local_y < 30) {
            wp_open_export_dialog(wp);
            return;
        }
        if (local_x >= WP_BTN_UNDO_X && local_x < WP_BTN_UNDO_X + 24 && local_y >= 6 && local_y < 30) {
            wp_close_dropdowns(wp);
            wp_undo(wp);
            return;
        }
        if (local_x >= WP_BTN_REDO_X && local_x < WP_BTN_REDO_X + 24 && local_y >= 6 && local_y < 30) {
            wp_close_dropdowns(wp);
            wp_redo(wp);
            return;
        }
        if (local_x >= WP_BTN_BOLD_X && local_x < WP_BTN_BOLD_X + 24 && local_y >= 6 && local_y < 30) {
            if (wp->has_selection) wp_apply_style_to_selection(wp, 2, 0);
            wp->cur_flags ^= STYLE_BOLD;
            if (wp->has_selection) wp_history_checkpoint(wp);
            return;
        }
        if (local_x >= WP_BTN_ITALIC_X && local_x < WP_BTN_ITALIC_X + 24 && local_y >= 6 && local_y < 30) {
            if (wp->has_selection) wp_apply_style_to_selection(wp, 3, 0);
            wp->cur_flags ^= STYLE_ITALIC;
            if (wp->has_selection) wp_history_checkpoint(wp);
            return;
        }
        if (local_x >= WP_FONT_DD_X && local_x < WP_FONT_DD_X + WP_FONT_DD_W && local_y >= 6 && local_y < 30) {
            bool open = !wp->font_dropdown_open;
            wp_close_dropdowns(wp);
            wp->font_dropdown_open = open;
            return;
        }
        if (local_x >= WP_SIZE_DD_X && local_x < WP_SIZE_DD_X + WP_SIZE_DD_W && local_y >= 6 && local_y < 30) {
            bool open = !wp->size_dropdown_open;
            wp_close_dropdowns(wp);
            wp->size_dropdown_open = open;
            return;
        }
        if (local_x >= WP_BTN_ALIGN_L_X && local_x < WP_BTN_ALIGN_L_X + 24 && local_y >= 6 && local_y < 30) {
            wp_close_dropdowns(wp);
            wp_apply_alignment(wp, PARA_ALIGN_LEFT);
            wp_history_checkpoint(wp);
            return;
        }
        if (local_x >= WP_BTN_ALIGN_C_X && local_x < WP_BTN_ALIGN_C_X + 24 && local_y >= 6 && local_y < 30) {
            wp_close_dropdowns(wp);
            wp_apply_alignment(wp, PARA_ALIGN_CENTER);
            wp_history_checkpoint(wp);
            return;
        }
        if (local_x >= WP_BTN_ALIGN_R_X && local_x < WP_BTN_ALIGN_R_X + 24 && local_y >= 6 && local_y < 30) {
            wp_close_dropdowns(wp);
            wp_apply_alignment(wp, PARA_ALIGN_RIGHT);
            wp_history_checkpoint(wp);
            return;
        }
        if (local_x >= WP_BTN_BULLET_X && local_x < WP_BTN_BULLET_X + 24 && local_y >= 6 && local_y < 30) {
            wp_close_dropdowns(wp);
            wp_toggle_list(wp, PARA_LIST_BULLET);
            wp_history_checkpoint(wp);
            return;
        }
        if (local_x >= WP_BTN_NUMBER_X && local_x < WP_BTN_NUMBER_X + 24 && local_y >= 6 && local_y < 30) {
            wp_close_dropdowns(wp);
            wp_toggle_list(wp, PARA_LIST_NUMBER);
            wp_history_checkpoint(wp);
            return;
        }
        if (local_x >= WP_BTN_OUTDENT_X && local_x < WP_BTN_OUTDENT_X + 24 && local_y >= 6 && local_y < 30) {
            wp_close_dropdowns(wp);
            wp_adjust_paragraph_indent(wp, -WP_PARA_STEP);
            wp_history_checkpoint(wp);
            return;
        }
        if (local_x >= WP_BTN_INDENT_X && local_x < WP_BTN_INDENT_X + 24 && local_y >= 6 && local_y < 30) {
            wp_close_dropdowns(wp);
            wp_adjust_paragraph_indent(wp, WP_PARA_STEP);
            wp_history_checkpoint(wp);
            return;
        }
        if (local_x >= WP_LINE_DD_X && local_x < WP_LINE_DD_X + WP_LINE_DD_W && local_y >= 6 && local_y < 30) {
            bool open = !wp->line_spacing_dropdown_open;
            wp_close_dropdowns(wp);
            wp->line_spacing_dropdown_open = open;
            return;
        }
        if (local_x >= WP_BTN_DIVIDER_X && local_x < WP_BTN_DIVIDER_X + 24 && local_y >= 6 && local_y < 30) {
            bool open = !wp->divider_flyout_open;
            wp_close_dropdowns(wp);
            wp->divider_flyout_open = open;
            return;
        }
        if (local_x >= WP_BTN_SECTION_X && local_x < WP_BTN_SECTION_X + 24 && local_y >= 6 && local_y < 30) {
            bool open = !wp->special_char_flyout_open;
            wp_close_dropdowns(wp);
            wp->special_char_flyout_open = open;
            return;
        }
        if (local_x >= WP_BTN_PAGEVIEW_X && local_x < WP_BTN_PAGEVIEW_X + 24 && local_y >= 6 && local_y < 30) {
            wp_close_dropdowns(wp);
            wp->pending_page_view_toggle = true;
            return;
        }
        return;
    }

    if (wp->show_pathbar && local_y >= WP_TOOLBAR_H && local_y < WP_TOOLBAR_H + WP_PATHBAR_H) {
        if (wp_left_pressed(ev.mouse.buttons, ev.mouse.prev_buttons)) {
            int btn_w = 56;
            int inp_w = g_win_w - 8 - btn_w - 12;
            int btn_x = 8 + inp_w + 6;
            if (local_x >= btn_x && local_x < btn_x + btn_w) {
                wp_commit_pathbar(wp);
            }
        }
        return;
    }

    wp_recompute_wrap(wp, recompute_w, WP_SCREEN_DPI);

    bool right_pressed = wp_right_pressed(ev.mouse.buttons, ev.mouse.prev_buttons);
    bool in_text_area = local_y >= edit_y && local_y < edit_y + text_area_h &&
                        local_x >= 0 && local_x < g_win_w - WP_SCROLLBAR_W;
    if (in_text_area && wp->page_view_mode) {
        in_text_area = local_x >= page_off_x && local_x < page_off_x + WP_A4_PAGE_W &&
                       local_y >= page_off_y && local_y < page_off_y + WP_A4_PAGE_H;
    }

    if (right_pressed && in_text_area) {
        wp_close_dropdowns(wp);

        int abs = wp_hit_test_text(wp, local_x, local_y, edit_y, page_off_x, page_off_y);
        if (!wp_selection_contains_abs(wp, abs)) {
            wp_pos_to_run(wp, abs, &wp->cursor_run, &wp->cursor_offset);
            wp_clear_selection(wp);
        }
        wp->mouse_selecting = false;
        mtk::context_menu_open(wp->context_menu, local_x, local_y);
        return;
    }

    if (wp_left_pressed(ev.mouse.buttons, ev.mouse.prev_buttons) &&
        local_y >= edit_y && local_y < edit_y + text_area_h) {
        wp_close_dropdowns(wp);

        int abs = wp_hit_test_text(wp, local_x, local_y, edit_y, page_off_x, page_off_y);
        wp_pos_to_run(wp, abs, &wp->cursor_run, &wp->cursor_offset);
        wp->sel_anchor = abs;
        wp->sel_end = abs;
        wp->has_selection = false;
        wp->mouse_selecting = true;
        return;
    }

    if (wp->mouse_selecting && wp_left_held(ev.mouse.buttons) && local_y >= edit_y - 20) {
        int abs = wp_hit_test_text(wp, local_x, local_y, edit_y, page_off_x, page_off_y);
        wp->sel_end = abs;
        wp_pos_to_run(wp, abs, &wp->cursor_run, &wp->cursor_offset);
        wp->has_selection = (wp->sel_anchor != wp->sel_end);
        return;
    }

    if (wp->mouse_selecting && wp_left_released(ev.mouse.buttons, ev.mouse.prev_buttons)) {
        wp->mouse_selecting = false;
        return;
    }

    if (ev.mouse.scroll != 0 && local_y >= edit_y && local_y < edit_y + text_area_h) {
        wp->scrollbar.scroll_offset -= ev.mouse.scroll * 40;
        int ms = wp->scrollbar.max_scroll();
        if (wp->scrollbar.scroll_offset < 0) wp->scrollbar.scroll_offset = 0;
        if (wp->scrollbar.scroll_offset > ms) wp->scrollbar.scroll_offset = ms;
    }
}

void wp_handle_key(const Montauk::KeyEvent& key) {
    WordProcessorState* wp = &g_wp;
    if (!key.pressed) return;

    if (wp->context_menu.open) {
        mtk::context_menu_close(wp->context_menu);
        if (key.scancode == 0x01) return;
    }

    if (wp->show_pathbar) {
        if (key.ascii == '\n' || key.ascii == '\r') {
            wp_commit_pathbar(wp);
            return;
        }
        if (key.scancode == 0x01) {
            wp->show_pathbar = false;
            return;
        }
        if (key.ascii == '\b' || key.scancode == 0x0E) {
            if (wp->pathbar_cursor > 0) {
                for (int i = wp->pathbar_cursor - 1; i < wp->pathbar_len - 1; i++)
                    wp->pathbar_text[i] = wp->pathbar_text[i + 1];
                wp->pathbar_len--;
                wp->pathbar_cursor--;
                wp->pathbar_text[wp->pathbar_len] = '\0';
            }
            return;
        }
        if (key.scancode == 0x4B) {
            if (wp->pathbar_cursor > 0) wp->pathbar_cursor--;
            return;
        }
        if (key.scancode == 0x4D) {
            if (wp->pathbar_cursor < wp->pathbar_len) wp->pathbar_cursor++;
            return;
        }
        if (key.ascii >= 32 && key.ascii < 127 && wp->pathbar_len < 254) {
            for (int i = wp->pathbar_len; i > wp->pathbar_cursor; i--)
                wp->pathbar_text[i] = wp->pathbar_text[i - 1];
            wp->pathbar_text[wp->pathbar_cursor] = key.ascii;
            wp->pathbar_cursor++;
            wp->pathbar_len++;
            wp->pathbar_text[wp->pathbar_len] = '\0';
        }
        return;
    }

    wp_close_dropdowns(wp);
    wp_recompute_wrap(wp, g_win_w, WP_SCREEN_DPI);

    if (key.ctrl && (key.ascii == 's' || key.ascii == 'S')) {
        wp_save_file(wp);
        return;
    }
    if (key.ctrl && (key.ascii == 'o' || key.ascii == 'O')) {
        wp_open_pathbar_for_open(wp);
        return;
    }
    if (key.ctrl && key.alt && (key.ascii == 'p' || key.ascii == 'P')) {
        wp_open_export_dialog(wp);
        return;
    }
    if (key.ctrl && !key.alt && (key.ascii == 'p' || key.ascii == 'P')) {
        wp_open_print_dialog(wp);
        return;
    }

    if (key.ctrl && !key.alt &&
        (key.ascii == 'z' || key.ascii == 'Z')) {
        if (key.shift) wp_redo(wp);
        else wp_undo(wp);
        return;
    }
    if (key.ctrl && !key.alt && (key.ascii == 'y' || key.ascii == 'Y')) {
        wp_redo(wp);
        return;
    }

    if (key.ctrl && key.alt && (key.ascii == 'b' || key.ascii == 'B')) {
        wp_toggle_list(wp, PARA_LIST_BULLET);
        wp_history_checkpoint(wp);
        return;
    }
    if (key.ctrl && key.alt && (key.ascii == 'n' || key.ascii == 'N')) {
        wp_toggle_list(wp, PARA_LIST_NUMBER);
        wp_history_checkpoint(wp);
        return;
    }

    if (key.ctrl && !key.alt && (key.ascii == 'l' || key.ascii == 'L')) {
        wp_apply_alignment(wp, PARA_ALIGN_LEFT);
        wp_history_checkpoint(wp);
        return;
    }
    if (key.ctrl && !key.alt && (key.ascii == 'e' || key.ascii == 'E')) {
        wp_apply_alignment(wp, PARA_ALIGN_CENTER);
        wp_history_checkpoint(wp);
        return;
    }
    if (key.ctrl && !key.alt && (key.ascii == 'r' || key.ascii == 'R')) {
        wp_apply_alignment(wp, PARA_ALIGN_RIGHT);
        wp_history_checkpoint(wp);
        return;
    }

    if (key.ctrl && !key.alt && (key.ascii == '1')) {
        wp_set_line_spacing(wp, 100);
        wp_history_checkpoint(wp);
        return;
    }
    if (key.ctrl && !key.alt && (key.ascii == '2')) {
        wp_set_line_spacing(wp, 125);
        wp_history_checkpoint(wp);
        return;
    }
    if (key.ctrl && !key.alt && (key.ascii == '3')) {
        wp_set_line_spacing(wp, 150);
        wp_history_checkpoint(wp);
        return;
    }
    if (key.ctrl && !key.alt && (key.ascii == '4')) {
        wp_set_line_spacing(wp, 200);
        wp_history_checkpoint(wp);
        return;
    }

    if (key.ctrl && !key.alt && (key.ascii == '[' || key.ascii == '{')) {
        if (key.shift || key.ascii == '{')
            wp_adjust_paragraph_first_line_indent(wp, -WP_PARA_STEP);
        else
            wp_adjust_paragraph_indent(wp, -WP_PARA_STEP);
        wp_history_checkpoint(wp);
        return;
    }
    if (key.ctrl && !key.alt && (key.ascii == ']' || key.ascii == '}')) {
        if (key.shift || key.ascii == '}')
            wp_adjust_paragraph_first_line_indent(wp, WP_PARA_STEP);
        else
            wp_adjust_paragraph_indent(wp, WP_PARA_STEP);
        wp_history_checkpoint(wp);
        return;
    }

    if (key.ctrl && key.alt && key.scancode == 0x48) {
        wp_adjust_paragraph_spacing_before(wp, -WP_SPACE_STEP);
        wp_history_checkpoint(wp);
        return;
    }
    if (key.ctrl && key.alt && key.scancode == 0x50) {
        wp_adjust_paragraph_spacing_before(wp, WP_SPACE_STEP);
        wp_history_checkpoint(wp);
        return;
    }
    if (key.ctrl && key.shift && key.scancode == 0x48) {
        wp_adjust_paragraph_spacing_after(wp, -WP_SPACE_STEP);
        wp_history_checkpoint(wp);
        return;
    }
    if (key.ctrl && key.shift && key.scancode == 0x50) {
        wp_adjust_paragraph_spacing_after(wp, WP_SPACE_STEP);
        wp_history_checkpoint(wp);
        return;
    }

    if (key.ctrl && !key.alt && (key.ascii == 'b' || key.ascii == 'B')) {
        if (wp->has_selection) wp_apply_style_to_selection(wp, 2, 0);
        wp->cur_flags ^= STYLE_BOLD;
        if (wp->has_selection) wp_history_checkpoint(wp);
        return;
    }
    if (key.ctrl && !key.alt && (key.ascii == 'i' || key.ascii == 'I')) {
        if (wp->has_selection) wp_apply_style_to_selection(wp, 3, 0);
        wp->cur_flags ^= STYLE_ITALIC;
        if (wp->has_selection) wp_history_checkpoint(wp);
        return;
    }

    if (key.ctrl && !key.alt && (key.ascii == 'c' || key.ascii == 'C')) {
        wp_copy_selection_to_clipboard(wp);
        return;
    }
    if (key.ctrl && !key.alt && (key.ascii == 'x' || key.ascii == 'X')) {
        wp_cut_selection_to_clipboard(wp);
        return;
    }
    if (key.ctrl && !key.alt && (key.ascii == 'v' || key.ascii == 'V')) {
        wp_paste_from_clipboard(wp);
        return;
    }

    if (key.scancode == 0x48) {
        if (key.shift) wp_start_selection(wp);
        else wp_clear_selection(wp);
        wp_cursor_up(wp);
        if (key.shift) wp_update_selection_to_cursor(wp);
        return;
    }
    if (key.scancode == 0x50) {
        if (key.shift) wp_start_selection(wp);
        else wp_clear_selection(wp);
        wp_cursor_down(wp);
        if (key.shift) wp_update_selection_to_cursor(wp);
        return;
    }
    if (key.scancode == 0x4B) {
        if (key.shift) wp_start_selection(wp);
        else if (wp->has_selection) {
            int s, e;
            wp_sel_range(wp, &s, &e);
            wp_pos_to_run(wp, s, &wp->cursor_run, &wp->cursor_offset);
            wp_clear_selection(wp);
            return;
        }
        wp_cursor_left(wp);
        if (key.shift) wp_update_selection_to_cursor(wp);
        return;
    }
    if (key.scancode == 0x4D) {
        if (key.shift) wp_start_selection(wp);
        else if (wp->has_selection) {
            int s, e;
            wp_sel_range(wp, &s, &e);
            wp_pos_to_run(wp, e, &wp->cursor_run, &wp->cursor_offset);
            wp_clear_selection(wp);
            return;
        }
        wp_cursor_right(wp);
        if (key.shift) wp_update_selection_to_cursor(wp);
        return;
    }

    if (key.scancode == 0x47) {
        if (key.shift) wp_start_selection(wp);
        else wp_clear_selection(wp);
        int abs = wp_abs_pos(wp, wp->cursor_run, wp->cursor_offset);
        int line = wp_find_wrap_line(wp, abs);
        int start = wp_wrap_line_start(wp, line);
        wp_pos_to_run(wp, start, &wp->cursor_run, &wp->cursor_offset);
        if (key.shift) wp_update_selection_to_cursor(wp);
        return;
    }
    if (key.scancode == 0x4F) {
        if (key.shift) wp_start_selection(wp);
        else wp_clear_selection(wp);
        int abs = wp_abs_pos(wp, wp->cursor_run, wp->cursor_offset);
        int line = wp_find_wrap_line(wp, abs);
        int start = wp_wrap_line_start(wp, line);
        int end = start + wp->wrap_lines[line].char_count;
        if (end > start) {
            char ch = wp_char_at(wp, end - 1);
            if (ch == '\n') end--;
        }
        wp_pos_to_run(wp, end, &wp->cursor_run, &wp->cursor_offset);
        if (key.shift) wp_update_selection_to_cursor(wp);
        return;
    }

    if (key.ctrl && (key.ascii == 'a' || key.ascii == 'A')) {
        wp->sel_anchor = 0;
        wp->sel_end = wp->total_text_len;
        wp->has_selection = (wp->total_text_len > 0);
        wp_pos_to_run(wp, wp->total_text_len, &wp->cursor_run, &wp->cursor_offset);
        return;
    }

    if (key.scancode == 0x53) {
        if (wp->has_selection) wp_delete_selection(wp);
        else wp_delete_char(wp);
        wp_history_checkpoint(wp);
        return;
    }

    if (key.ascii == '\b' || key.scancode == 0x0E) {
        if (wp->has_selection) wp_delete_selection(wp);
        else wp_backspace(wp);
        wp_history_checkpoint(wp);
        return;
    }

    if (key.ascii == '\n' || key.ascii == '\r') {
        if (wp->has_selection) wp_delete_selection(wp);
        wp_insert_char(wp, '\n');
        wp_history_checkpoint(wp);
        return;
    }

    if (key.ascii == '\t') {
        if (wp->has_selection) wp_delete_selection(wp);
        for (int i = 0; i < 4; i++) wp_insert_char(wp, ' ');
        wp_history_checkpoint(wp);
        return;
    }

    if (key.ascii >= 32 && key.ascii < 127) {
        if (wp->has_selection) wp_delete_selection(wp);
        wp_insert_char(wp, key.ascii);
        wp_history_checkpoint(wp);
    }
}
