import {
  player,
  togglePlay,
  skipNext,
  skipPrev,
  seekTo,
  setVolume,
  toggleMute
} from './store.svelte';

// Universal music-player keyboard conventions, attached at window
// level from +layout.svelte. Skipped when focus is in a text input
// (or contenteditable surface) so typing in the search box, playlist
// rename field, etc. behaves normally.
//
// Convention map:
//   Space        play / pause
//   K            play / pause (YouTube convention; same as Space)
//   ArrowLeft    previous track
//   ArrowRight   next track
//   J            seek -10s
//   L            seek +10s
//   ArrowUp      volume +5%
//   ArrowDown    volume -5%
//   M            mute / unmute
//   /            focus the global search input
//
// Escape on the queue drawer is already handled in +layout.svelte; we
// intentionally don't claim Escape here so menus, modals, and the
// queue close as they do today.

const SEEK_STEP_SEC = 10;
const VOLUME_STEP = 0.05;

function isTypingTarget(el: EventTarget | null): boolean {
  if (!(el instanceof HTMLElement)) return false;
  const tag = el.tagName;
  if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return true;
  if (el.isContentEditable) return true;
  return false;
}

function adjustVolume(delta: number): void {
  setVolume(Math.max(0, Math.min(1, player.volume + delta)));
}

function adjustPosition(delta: number): void {
  const target = Math.max(0, Math.min(player.duration, player.position + delta));
  seekTo(target);
}

function focusSearch(): void {
  // Top-bar SearchInput renders <input type="search" aria-label="Search">.
  // querySelector is the simplest reach into a component whose internal
  // ref isn't exported.
  const el = document.querySelector<HTMLInputElement>('input[type="search"]');
  el?.focus();
  el?.select();
}

export function useGlobalShortcuts(): void {
  if (typeof window === 'undefined') return;

  const handler = (e: KeyboardEvent) => {
    // Don't claim shortcuts when modifier-only (would conflict with
    // browser hotkeys) or when the user is typing.
    if (e.ctrlKey || e.metaKey || e.altKey) return;
    if (isTypingTarget(e.target)) return;

    switch (e.key) {
      case ' ':
      case 'k':
      case 'K':
        e.preventDefault();
        togglePlay();
        break;
      case 'ArrowLeft':
        e.preventDefault();
        skipPrev();
        break;
      case 'ArrowRight':
        e.preventDefault();
        skipNext();
        break;
      case 'j':
      case 'J':
        e.preventDefault();
        adjustPosition(-SEEK_STEP_SEC);
        break;
      case 'l':
      case 'L':
        e.preventDefault();
        adjustPosition(SEEK_STEP_SEC);
        break;
      case 'ArrowUp':
        e.preventDefault();
        adjustVolume(VOLUME_STEP);
        break;
      case 'ArrowDown':
        e.preventDefault();
        adjustVolume(-VOLUME_STEP);
        break;
      case 'm':
      case 'M':
        e.preventDefault();
        toggleMute();
        break;
      case '/':
        // The "/" key has historically been the focus-search hotkey
        // (Gmail, GitHub, Vim). preventDefault stops it from typing
        // into whichever element ends up focused after.
        e.preventDefault();
        focusSearch();
        break;
      default:
        return;
    }
  };

  $effect(() => {
    window.addEventListener('keydown', handler);
    return () => window.removeEventListener('keydown', handler);
  });
}
