#ifndef HUSH_KEYMAP_H
#define HUSH_KEYMAP_H

#include <SDL.h>
#include <stdbool.h>

/* Every user-rebindable shortcut. Plain text-editing keys (arrows, Enter, Backspace, Home/End,
   the mouse) are deliberately not in here -- they're not "shortcuts" in the chord sense, and
   letting them be rebound risks silently breaking normal typing. */
typedef enum {
    ACTION_SAVE,
    ACTION_OPEN,
    ACTION_COPY,
    ACTION_PASTE,
    ACTION_UNDO,
    ACTION_REDO,
    ACTION_QUIT,
    ACTION_HELP,
    ACTION_SOURCE_VIEW,
    ACTION_ZOOM_IN,
    ACTION_ZOOM_OUT,
    ACTION_ZOOM_RESET,
    ACTION_COUNT
} Action;

typedef struct {
    int key; /* an SDL_Keycode (SDLK_*) -- layout-aware, not a physical scancode */
    bool ctrl, shift, alt;
} KeyBinding;

/* Fills out[ACTION_COUNT] with hush's built-in default bindings. */
void keymap_set_defaults(KeyBinding *out);

/* Parses a binding spec like "ctrl+s", "ctrl+shift+z", "ctrl+/", or "f1" into `out`. Modifier
   names ("ctrl", "shift", "alt") are case-insensitive and may appear in any order, joined by
   '+'; the remaining token is the key name (single letters/digits, f1-f12, punctuation like
   "/" or "slash", or names like "enter"/"escape"/"tab"/"space"/"home"/"end"/"up"/"down"/
   "left"/"right"/"pageup"/"pagedown"/"insert" -- see keymap.c for the full list). Returns false
   (leaving `out` untouched) for an empty spec or an unrecognized key name. */
bool keymap_parse_spec(const char *spec, int len, KeyBinding *out);

/* If `key` names one of the actions above (its config-file key, e.g. "key.save"), parses
   `value` as a binding spec and stores it into keymap[that action]. Returns whether it matched
   and parsed -- used by config.c to dispatch "key.*" lines. */
bool keymap_parse_config_line(const char *key, int keyLen, const char *value, int valueLen, KeyBinding *keymap);

/* The bindings actually used by main.c's input loop: defaulted at startup, then overlaid by
   config_load() from the user's config file. */
extern KeyBinding g_keymap[ACTION_COUNT];

/* Clears the per-frame keydown buffer -- call once at the top of each frame, before draining
   SDL's event queue. */
void keymap_begin_frame(void);
/* Records one non-repeat SDL_KEYDOWN event's keycode into the per-frame buffer -- call once per
   such event while draining SDL_PollEvent (skip events where event.key.repeat is set, since
   that's OS-level auto-repeat, not a fresh press). */
void keymap_note_keydown(SDL_Keycode key);
/* True if `key` was recorded via keymap_note_keydown this frame. Used both by keymap_pressed
   (below) and by main.c's own ad-hoc fixed-key checks (F1, Escape, Enter, Home/End, ...) so
   there's a single source of truth for "was this keycode just pressed" rather than two parallel
   per-frame buffers. */
bool keymap_key_pressed_raw(SDL_Keycode key);

/* True on the frame `a`'s bound chord was just pressed (ctrl/shift/alt must match exactly). */
bool keymap_pressed(Action a, bool ctrl, bool shift, bool alt);
/* Same, but true again at a steady repeat rate while held. */
bool keymap_repeat(Action a, bool ctrl, bool shift, bool alt, double now, double *nextRepeatAt);

/* Shared scancode-based "is held, repeating at a steady rate" primitive: true on the frame `sc`
   goes down, then again every ~0.03s after an initial ~0.4s delay while still held, false (and
   resets `*nextRepeatAt`) once released. Backs keymap_repeat above; also exposed directly for
   main.c's fixed-scancode repeat needs (arrows, backspace, delete, the numpad zoom fallback) so
   there's one repeat-timer implementation, not two. */
bool keymap_repeat_scancode(SDL_Scancode sc, double now, double *nextRepeatAt);

#endif
