<script lang="ts">
  import { onDestroy } from "svelte";
  import type { LeafNode } from "./tree";
  import { useOrchestration } from "./orchestration.svelte";
  import XtermPane from "../../components/XtermPane.svelte";

  let { leaf }: { leaf: LeafNode } = $props();

  const orch = useOrchestration();

  // Derives directly from orch.activeLeafId — Svelte 5 tracks the class
  // field access on every re-evaluation. No prop drilling involved.
  const active = $derived(orch.activeLeafId === leaf.id);

  let status = $state("starting…");
  let statusOk = $state(true);

  // ---- label editing -------------------------------------------------------
  let editingLabel = $state(false);
  let labelDraft = $state("");
  let labelInputEl: HTMLInputElement | null = $state(null);

  function startEditLabel(e: MouseEvent) {
    e.stopPropagation();
    labelDraft = leaf.label ?? "";
    editingLabel = true;
    queueMicrotask(() => labelInputEl?.select());
  }

  function commitLabel() {
    if (!editingLabel) return;
    orch.setLabel(leaf.id, labelDraft);
    editingLabel = false;
  }

  function cancelLabel() {
    editingLabel = false;
  }

  function onLabelKey(e: KeyboardEvent) {
    if (e.key === "Enter") {
      e.preventDefault();
      commitLabel();
    } else if (e.key === "Escape") {
      e.preventDefault();
      cancelLabel();
    }
  }

  // ---- distro popover ------------------------------------------------------
  let distroOpen = $state(false);

  function toggleDistroMenu(e: MouseEvent) {
    e.stopPropagation();
    distroOpen = !distroOpen;
  }

  function pickDistro(d: string) {
    distroOpen = false;
    if (d !== leaf.distro) orch.setDistro(leaf.id, d);
  }

  $effect(() => {
    if (!distroOpen) return;
    const onDocClick = () => (distroOpen = false);
    window.addEventListener("click", onDocClick);
    return () => window.removeEventListener("click", onDocClick);
  });

  // ---- idle detection ------------------------------------------------------
  const IDLE_THRESHOLD_MS = 5000;
  let lastDataTime = Date.now();
  let notifiedThisIdle = false;

  function onDataReceived() {
    lastDataTime = Date.now();
    notifiedThisIdle = false;
  }

  function checkIdle() {
    if (notifiedThisIdle) return;
    const sinceLast = Date.now() - lastDataTime;
    if (sinceLast >= IDLE_THRESHOLD_MS) {
      notifiedThisIdle = true;
      const name = leaf.label ?? leaf.distro ?? "pane";
      console.log("[tiletopia] notifying idle:", leaf.id, "quietForMs:", sinceLast);
      orch.notify(`${name} is idle`);
    }
  }

  const idleTimer = window.setInterval(checkIdle, 1000);
  onDestroy(() => clearInterval(idleTimer));

  // ---- broadcast -----------------------------------------------------------
  function onTerminalInput(b64: string) {
    if (leaf.broadcast) orch.broadcastFrom(leaf.id, b64);
  }

  // ---- focus / active ------------------------------------------------------
  let focusTrigger = $state(0);

  $effect(() => {
    if (active) focusTrigger += 1;
  });

  // Backup setActive for toolbar clicks (which can't reach the document
  // capture listener if a bubble-phase handler stops propagation). Cheap;
  // idempotent if the document listener also fired.
  function onPaneClick() {
    orch.setActive(leaf.id);
  }

  // ---- pane id registration ------------------------------------------------
  function onPaneSpawned(paneId: number) {
    orch.registerPaneId(leaf.id, paneId);
  }
  onDestroy(() => orch.registerPaneId(leaf.id, null));
</script>

<div
  class="leaf"
  class:active={active}
  class:broadcasting={leaf.broadcast}
  role="group"
  aria-label={"Terminal pane: " + (leaf.label ?? leaf.distro ?? "unnamed")}
  data-leaf-id={leaf.id}
  onpointerdown={onPaneClick}
>
  <div class="pane-toolbar">
    {#if editingLabel}
      <input
        class="label-input"
        bind:this={labelInputEl}
        bind:value={labelDraft}
        onkeydown={onLabelKey}
        onblur={commitLabel}
        placeholder="(label)"
      />
    {:else}
      <button
        class="pane-label"
        onclick={startEditLabel}
        title="Click to rename pane"
      >
        {leaf.label ?? "(unnamed)"}
      </button>
    {/if}

    <span class="distro-wrap">
      <button
        class="distro-chip"
        onclick={toggleDistroMenu}
        title="Change distro (respawns the pane)"
      >
        {leaf.distro ?? "(default)"} ▾
      </button>
      {#if distroOpen}
        <div
          class="distro-menu"
          onclick={(e) => e.stopPropagation()}
          role="menu"
          tabindex="-1"
          onkeydown={() => {}}
        >
          {#each orch.distros as d}
            <button
              class="distro-menu-item"
              class:active={d === leaf.distro}
              onclick={() => pickDistro(d)}
            >{d}</button>
          {/each}
        </div>
      {/if}
    </span>

    <button
      class="bcast-chip"
      class:on={leaf.broadcast}
      onclick={(e) => { e.stopPropagation(); orch.toggleBroadcast(leaf.id); }}
      title={leaf.broadcast ? "Broadcasting (click to leave group)" : "Click to broadcast input to other broadcast panes"}
      aria-pressed={leaf.broadcast ? "true" : "false"}
    >📡</button>

    <span class="pane-status {statusOk ? 'ok' : 'err'}">{status}</span>

    <span class="pane-actions">
      <button
        class="pane-btn"
        title="Split right"
        onclick={(e) => { e.stopPropagation(); orch.split(leaf.id, "h"); }}
        aria-label="Split right"
      >⇥</button>
      <button
        class="pane-btn"
        title="Split down"
        onclick={(e) => { e.stopPropagation(); orch.split(leaf.id, "v"); }}
        aria-label="Split down"
      >⇣</button>
      <button
        class="pane-btn close"
        title="Close pane"
        onclick={(e) => { e.stopPropagation(); orch.close(leaf.id); }}
        aria-label="Close pane"
      >×</button>
    </span>
  </div>
  <div class="xterm-wrap">
    <XtermPane
      distro={leaf.distro}
      cwd={leaf.cwd}
      onStatus={(msg, ok) => {
        status = msg;
        statusOk = ok;
      }}
      onSpawn={onPaneSpawned}
      onInput={onTerminalInput}
      onFocus={() => orch.setActive(leaf.id)}
      {onDataReceived}
      {focusTrigger}
    />
  </div>
</div>

<style>
  .leaf {
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
    min-width: 0;
    min-height: 0;
    border: 2px solid transparent;
    box-sizing: border-box;
  }
  .leaf.active {
    border-color: #5a8cd8;
  }
  .leaf.broadcasting {
    border-color: #e09838;
  }
  .leaf.active.broadcasting {
    border-color: #ffb840;
  }

  .pane-toolbar {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 2px 8px;
    background: #181818;
    border-bottom: 1px solid #2a2a2a;
    font-size: 11px;
    color: #aaa;
    user-select: none;
    min-height: 24px;
  }
  .pane-label {
    font: inherit;
    font-family: "Cascadia Mono", "JetBrains Mono", "Consolas", monospace;
    font-weight: 600;
    color: #ccc;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 3px;
    padding: 1px 6px;
    cursor: text;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 200px;
  }
  .pane-label:hover {
    background: #222;
    border-color: #2a2a2a;
  }
  .label-input {
    font: inherit;
    font-family: "Cascadia Mono", "JetBrains Mono", "Consolas", monospace;
    font-weight: 600;
    color: #fff;
    background: #0c0c0c;
    border: 1px solid #3a5a8c;
    border-radius: 3px;
    padding: 1px 6px;
    outline: none;
    max-width: 240px;
  }

  .distro-wrap {
    position: relative;
  }
  .distro-chip,
  .bcast-chip {
    font: inherit;
    font-family: "Cascadia Mono", "JetBrains Mono", "Consolas", monospace;
    font-size: 10px;
    background: #222;
    color: #88c;
    border: 1px solid #2a2a3a;
    border-radius: 3px;
    padding: 1px 6px;
    cursor: pointer;
  }
  .distro-chip:hover,
  .bcast-chip:hover {
    background: #2a2a3a;
    color: #aac;
  }
  .bcast-chip {
    color: #777;
    background: #1c1c1c;
    border-color: #2a2a2a;
    padding: 1px 5px;
  }
  .bcast-chip.on {
    background: #4a3010;
    color: #f0c060;
    border-color: #c98a1f;
  }

  .distro-menu {
    position: absolute;
    top: 100%;
    left: 0;
    margin-top: 2px;
    background: #1a1a1a;
    border: 1px solid #2a2a2a;
    border-radius: 4px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
    z-index: 10;
    min-width: 140px;
    display: flex;
    flex-direction: column;
    padding: 2px;
  }
  .distro-menu-item {
    font: inherit;
    font-family: "Cascadia Mono", "JetBrains Mono", "Consolas", monospace;
    font-size: 11px;
    text-align: left;
    background: transparent;
    color: #ccc;
    border: none;
    border-radius: 2px;
    padding: 3px 8px;
    cursor: pointer;
  }
  .distro-menu-item:hover {
    background: #2a2a2a;
  }
  .distro-menu-item.active {
    background: #1a3a5c;
    color: #cce6ff;
  }

  .pane-status {
    margin-left: auto;
    font-family: "Cascadia Mono", "JetBrains Mono", "Consolas", monospace;
    color: #777;
    font-size: 10px;
    white-space: nowrap;
  }
  .pane-status.ok { color: #6c6; }
  .pane-status.err { color: #d66; }

  .pane-actions {
    display: flex;
    gap: 2px;
  }
  .pane-btn {
    background: transparent;
    border: none;
    color: #888;
    font: inherit;
    font-size: 14px;
    line-height: 1;
    padding: 2px 6px;
    border-radius: 3px;
    cursor: pointer;
  }
  .pane-btn:hover {
    background: #2a2a2a;
    color: #ddd;
  }
  .pane-btn.close:hover {
    background: #5a1a1a;
    color: #fcc;
  }
  .xterm-wrap {
    flex: 1 1 auto;
    min-height: 0;
    position: relative;
  }
</style>
