<script lang="ts">
  import { tick } from 'svelte';
  import { commands } from '$lib/data/commands';

  export let open = false;
  export let runCommand: (command: string, source?: 'terminal' | 'palette') => string | void;

  let query = '';
  let inputElement: HTMLInputElement;

  $: matches = commands.filter((command) => {
    const haystack = `${command.name} ${command.description} ${command.aliases?.join(' ') ?? ''}`.toLowerCase();
    return haystack.includes(query.trim().toLowerCase());
  });

  $: if (open) {
    tick().then(() => inputElement?.focus());
  }

  function choose(command: string) {
    runCommand(command, 'palette');
    query = '';
    open = false;
  }

  function keydown(event: KeyboardEvent) {
    if (event.key === 'Escape') {
      open = false;
      query = '';
    }

    if (event.key === 'Enter' && matches[0]) {
      choose(matches[0].name);
    }
  }
</script>

{#if open}
  <div class="palette-backdrop" role="presentation" on:click={() => (open = false)}>
    <div
      class="command-palette"
      role="dialog"
      aria-modal="true"
      aria-label="Command palette"
      tabindex="-1"
      on:click|stopPropagation
      on:keydown|stopPropagation
    >
      <label for="command-search">Command</label>
      <input
        id="command-search"
        bind:this={inputElement}
        bind:value={query}
        on:keydown={keydown}
        placeholder="Type a command or app name"
        autocomplete="off"
      />
      <div class="command-list" role="listbox">
        {#each matches as command}
          <button type="button" on:click={() => choose(command.name)}>
            <span>{command.name}</span>
            <small>{command.description}</small>
          </button>
        {/each}
      </div>
    </div>
  </div>
{/if}
