/**
 * LANE-UI — the keyboard map. ALL bindings live here; this file will grow.
 *
 * Round 2 map:
 *   1..9    select build slot N *within the active page*
 *   [ ]     previous / next build page
 *   R       rotate pending build dir
 *   ESC     clear selection / close inspector
 *   SPACE   toggle HALT
 *
 * WASD and the middle-drag pan belong to LANE-RENDER's camera (see render/camera.ts);
 * nothing here binds them. Keys match on `event.key` lowercased, so layout-shifted
 * digits still work.
 *
 * Split in two: `KeyRouter` is the pure map + dispatch (no window, testable in node),
 * `Hotkeys` is the thin binding to the real window.
 */

export type HotkeyHandler = (ev: KeyEventLike) => void;

/** The parts of KeyboardEvent this module actually reads. */
export interface KeyEventLike {
  key: string;
  metaKey?: boolean;
  ctrlKey?: boolean;
  altKey?: boolean;
  target?: unknown;
  preventDefault?(): void;
}

export interface KeyRouter {
  /** `key` is a lowercased `event.key`, e.g. "r", "escape", " ", "[", "1". */
  bind(key: string, handler: HotkeyHandler): void;
  /** Returns true if a binding ran. */
  handle(ev: KeyEventLike): boolean;
}

export interface Hotkeys extends KeyRouter {
  attach(): void;
  detach(): void;
}

/** Don't steal keys while the player is typing into something. */
export function isTypingTarget(t: unknown): boolean {
  if (typeof HTMLElement === 'undefined') return false;
  if (!(t instanceof HTMLElement)) return false;
  return t.isContentEditable || /^(INPUT|TEXTAREA|SELECT)$/.test(t.tagName);
}

/** Keys we swallow so the browser doesn't scroll or focus-walk the page. */
const SWALLOW = new Set([' ']);

export function createKeyRouter(): KeyRouter {
  const map = new Map<string, HotkeyHandler>();

  return {
    bind(key, handler) {
      map.set(key.toLowerCase(), handler);
    },
    handle(ev) {
      if (isTypingTarget(ev.target)) return false;
      // Leave the browser's own shortcuts alone (⌘R, ctrl-tab, …).
      if (ev.metaKey || ev.ctrlKey || ev.altKey) return false;

      const handler = map.get(ev.key.toLowerCase());
      if (!handler) return false;

      if (SWALLOW.has(ev.key.toLowerCase())) ev.preventDefault?.();
      handler(ev);
      return true;
    },
  };
}

export function createHotkeys(): Hotkeys {
  const router = createKeyRouter();
  const onKeyDown = (ev: KeyboardEvent) => router.handle(ev);

  return {
    bind: router.bind,
    handle: router.handle,
    attach() {
      window.addEventListener('keydown', onKeyDown);
    },
    detach() {
      window.removeEventListener('keydown', onKeyDown);
    },
  };
}
