<script lang="ts">
  /*** IMPORT ------------------------------------------- ***/
  import { tick, type Snippet } from "svelte";

  /*** UTILITY ------------------------------------------ ***/
  import type { Tab } from "../state/session.svelte.ts";

  type Props = {
    activeId: string;
    extras?: Snippet<[{ tab: Tab }]>;
    onAdd: () => void;
    onClose: (id: string) => void;
    onRename: (id: string, title: string) => void;
    onSelect: (id: string) => void;
    tabs: Tab[];
  };

  let {
    activeId,
    extras,
    onAdd,
    onClose,
    onRename,
    onSelect,
    tabs
  }: Props = $props();

  let draft = $state<string>("");
  let editingId = $state<string | null>(null);
  let inputEl = $state<HTMLInputElement | null>(null);

  /*** HELPER ------------------------------------------- ***/
  function cancel() {
    editingId = null;
    draft = "";
  }

  function commit() {
    if (editingId === null)
      return;

    onRename(editingId, draft);
    editingId = null;
    draft = "";
  }

  function handleClose(event: MouseEvent, id: string) {
    event.stopPropagation();
    onClose(id);
  }

  function onKeydown(event: KeyboardEvent) {
    if (event.key === "Enter") {
      event.preventDefault();
      commit();
    } else if (event.key === "Escape") {
      event.preventDefault();
      cancel();
    }
  }

  async function startEditing(tab: Tab) {
    editingId = tab.id;
    draft = tab.title;
    await tick();
    inputEl?.select();
  }
</script>

<style lang="scss">
  .tabbar {
    align-items: stretch;
    background-color: var(--uchu-gray-2);
    display: flex;
    font-size: 0.8rem;
    min-height: 2rem;
    overflow-x: auto;

    .tab {
      align-items: center;
      border: none;
      cursor: pointer;
      display: flex;
      gap: 0.5rem;
      padding: 0 0.75rem;

      &:not(:hover):not(.active) {
        color: var(--uchu-yin-5);
      }

      &:hover:not(.active) {
        color: var(--uchu-yin-8);
      }

      &:not(.active) {
        background-color: transparent;
      }

      &.active {
        background-color: var(--uchu-gray-3);
        color: var(--uchu-yin-8);
      }
    }
  }

  .title {
    white-space: nowrap;
  }

  .edit {
    background-color: var(--uchu-orange-5);
    border: 1px solid var(--uchu-orange-5);
    color: var(--uchu-yang);
    font-family: inherit;
    font-size: inherit;
    min-width: 6rem;
    outline: none;
    padding: 0.125rem 0.25rem;
  }

  .close {
    background: none;
    border: none;
    color: inherit;
    cursor: pointer;
    font-size: 1rem;
    line-height: 1;
    padding: 0;

    &:not(:hover) {
      opacity: 0.6;
    }

    &:hover {
      opacity: 1;
    }
  }

  .add {
    background: none;
    border: none;
    border-left: 1px solid var(--uchu-gray-3);
    cursor: pointer;
    font-size: 1rem;
    padding: 0 0.75rem;

    &:not(:hover) {
      color: var(--uchu-yin-5);
    }

    &:hover {
      color: var(--uchu-yin-8);
    }
  }
</style>

<div class="tabbar" role="tablist">
  {#each tabs as tab (tab.id)}
    <div
      aria-selected={tab.id === activeId}
      class="tab"
      class:active={tab.id === activeId}
      ondblclick={() => startEditing(tab)}
      onclick={() => onSelect(tab.id)}
      onkeydown={(e) => {
        if (e.key === "Enter" || e.key === " ") {
          e.preventDefault();
          onSelect(tab.id);
        }
      }}
      role="tab"
      tabindex="0">
      {#if editingId === tab.id}
        <input
          bind:this={inputEl}
          bind:value={draft}
          class="edit"
          onblur={commit}
          onclick={(e) => e.stopPropagation()}
          onkeydown={onKeydown}
          type="text"/>
      {:else}
        <span class="title">{tab.title}</span>
      {/if}

      {#if extras}{@render extras({ tab })}{/if}

      <button
        aria-label="Close tab"
        class="close"
        onclick={(e) => handleClose(e, tab.id)}>&times;</button>
    </div>
  {/each}

  <button aria-label="New tab" class="add" onclick={onAdd}>+</button>
</div>
