<script lang="ts">
  import { appsById } from '$lib/data/apps';
  import ContentWindow from '$lib/components/content/ContentWindow.svelte';
  import ControlPanel from '$lib/components/os/ControlPanel.svelte';
  import Terminal from '$lib/components/os/Terminal.svelte';
  import { windowStore, type WindowState } from '$lib/stores/windowStore';

  export let item: WindowState;
  export let runCommand: (command: string, source?: 'terminal' | 'palette') => string | void;
  export let replayBoot: () => void;

  $: app = appsById.get(item.id);

  let dragStart:
    | { pointerId: number; startX: number; startY: number; originalX: number; originalY: number }
    | undefined;
  let resizeStart:
    | { pointerId: number; startX: number; startY: number; originalWidth: number; originalHeight: number }
    | undefined;

  function focus() {
    windowStore.focusWindow(item.id);
  }

  function startDrag(event: PointerEvent) {
    if (item.maximised) return;
    const target = event.target as HTMLElement;
    if (target.closest('button')) return;

    dragStart = {
      pointerId: event.pointerId,
      startX: event.clientX,
      startY: event.clientY,
      originalX: item.x,
      originalY: item.y
    };
    (event.currentTarget as HTMLElement).setPointerCapture(event.pointerId);
    focus();
  }

  function drag(event: PointerEvent) {
    if (!dragStart || dragStart.pointerId !== event.pointerId) return;
    const nextX = Math.max(8, dragStart.originalX + event.clientX - dragStart.startX);
    const nextY = Math.max(42, dragStart.originalY + event.clientY - dragStart.startY);
    windowStore.moveWindow(item.id, nextX, nextY);
  }

  function stopDrag(event: PointerEvent) {
    if (!dragStart || dragStart.pointerId !== event.pointerId) return;
    dragStart = undefined;
  }

  function startResize(event: PointerEvent) {
    if (item.maximised) return;
    resizeStart = {
      pointerId: event.pointerId,
      startX: event.clientX,
      startY: event.clientY,
      originalWidth: item.width,
      originalHeight: item.height
    };
    (event.currentTarget as HTMLElement).setPointerCapture(event.pointerId);
    focus();
  }

  function resize(event: PointerEvent) {
    if (!resizeStart || resizeStart.pointerId !== event.pointerId) return;
    const nextWidth = Math.max(360, resizeStart.originalWidth + event.clientX - resizeStart.startX);
    const nextHeight = Math.max(320, resizeStart.originalHeight + event.clientY - resizeStart.startY);
    windowStore.resizeWindow(item.id, nextWidth, nextHeight);
  }

  function stopResize(event: PointerEvent) {
    if (!resizeStart || resizeStart.pointerId !== event.pointerId) return;
    resizeStart = undefined;
  }
</script>

{#if app && !item.minimised}
  <section
    class="os-window"
    class:maximised={item.maximised}
    style={`--window-x: ${item.x}px; --window-y: ${item.y}px; --window-width: ${item.width}px; --window-height: ${item.height}px; z-index: ${item.z};`}
    aria-label={app.title}
    on:pointerdown={focus}
  >
    <header
      class="os-window__titlebar"
      role="toolbar"
      aria-label={`${app.shortTitle} window controls`}
      tabindex="0"
      on:pointerdown={startDrag}
      on:pointermove={drag}
      on:pointerup={stopDrag}
      on:pointercancel={stopDrag}
      on:dblclick={() => windowStore.toggleMaximise(item.id)}
    >
      <span class="os-window__icon" aria-hidden="true">{app.icon}</span>
      <h2>{app.title}</h2>
      <div class="os-window__actions">
        <button type="button" aria-label={`Minimise ${app.shortTitle}`} on:click={() => windowStore.minimiseWindow(item.id)}>-</button>
        <button type="button" aria-label={`Maximise ${app.shortTitle}`} on:click={() => windowStore.toggleMaximise(item.id)}>{item.maximised ? '<>' : '[]'}</button>
        <button type="button" aria-label={`Close ${app.shortTitle}`} on:click={() => windowStore.closeWindow(item.id)}>x</button>
      </div>
    </header>
    <div class="os-window__body">
      {#if app.id === 'terminal'}
        <Terminal {runCommand} />
      {:else if app.id === 'control'}
        <ControlPanel {replayBoot} />
      {:else}
        <ContentWindow {app} />
      {/if}
    </div>
    <button
      type="button"
      class="os-window__resize"
      aria-label={`Resize ${app.shortTitle}`}
      on:pointerdown={startResize}
      on:pointermove={resize}
      on:pointerup={stopResize}
      on:pointercancel={stopResize}
    ></button>
  </section>
{/if}
