<script lang="ts">
  import { onMount } from "svelte";
  import {
    getGuide,
    getConfig,
    getStatus,
    onStep,
    onStatus,
    onConfig,
    onFocus,
    onOverlayToggle,
    onOverlayLocked,
    onGuideReload,
    getTimer,
    onTimer,
    fmtTime,
    setOverlayHeight,
    restoreOverlayPosition,
    type GuideData,
    type Config,
    type Status,
    type RunTimer,
  } from "$lib/api";
  import StepView from "$lib/StepView.svelte";

  let guide = $state<GuideData | null>(null);
  let config = $state<Config | null>(null);
  let status = $state<Status | null>(null);
  let timer = $state<RunTimer | null>(null);
  let focused = $state(false);
  let userHidden = $state(false);
  let locked = $state(true);
  // Measured height of the rendered overlay box; drives the OS window height so
  // the window is only as tall as its content (else the WM clamps it on-screen
  // and the overlay jumps to the middle when placed/restored near a screen edge).
  let boxHeight = $state(0);

  // Whether the overlay content should be shown. When unlocked (editing the
  // position) it is always shown; otherwise it follows the focus/toggle rules.
  const visible = $derived.by(() => {
    if (!config) return false;
    if (!locked) return true;
    if (userHidden) return false;
    return config.overlay_only_when_focused ? focused : true;
  });

  const current = $derived(config?.current_step ?? 0);
  const currentStep = $derived(guide?.steps[current] ?? null);
  const lookahead = $derived.by(() => {
    if (!guide || !config) return [];
    const n = config.lookahead;
    return guide.steps.slice(current + 1, current + 1 + n);
  });

  // Recommended level for the area this step heads to.
  const recommendation = $derived.by(() => {
    if (!guide || !currentStep?.target_area) return null;
    return guide.areas[currentStep.target_area]?.recommendation ?? null;
  });

  onMount(() => {
    const unlisten: Array<() => void> = [];
    (async () => {
      guide = await getGuide();
      config = await getConfig();
      status = await getStatus();
      timer = await getTimer();
      focused = status.game_focused;
      unlisten.push(
        await onStep((i) => {
          if (config) config = { ...config, current_step: i };
        }),
      );
      unlisten.push(await onStatus((s) => (status = s)));
      unlisten.push(await onConfig((c) => (config = c)));
      unlisten.push(await onFocus((f) => (focused = f)));
      unlisten.push(await onOverlayToggle(() => (userHidden = !userHidden)));
      unlisten.push(await onOverlayLocked((l) => (locked = l)));
      unlisten.push(await onGuideReload(async () => (guide = await getGuide())));
      unlisten.push(await onTimer((t) => (timer = t)));
    })();
    return () => unlisten.forEach((u) => u());
  });

  // Keep the OS window height matched to the rendered content.
  let positionRestored = false;
  $effect(() => {
    if (visible && boxHeight > 0) {
      setOverlayHeight(Math.ceil(boxHeight) + 2);
      // Once the window is shrunk to content, restore its saved position (the WM
      // would clamp a still-tall window on-screen if we did this any earlier).
      if (!positionRestored) {
        positionRestored = true;
        setTimeout(() => restoreOverlayPosition(), 150);
      }
    }
  });
</script>

{#if guide && config && visible}
  <div class="overlay" class:editing={!locked} style="font-size:{config.overlay_font_size}px;" bind:clientHeight={boxHeight}>
    {#if !locked}
      <div class="dragbar" data-tauri-drag-region>⠿ déplacer · reverrouille dans les réglages pour sauver</div>
    {/if}
    <div class="header">
      <span class="act">Act {currentStep ? currentStep.section + 1 : "?"}</span>
      {#if status}
        <span class="lvl">Lv {status.level || "?"}</span>
        {#if status.area_name}<span class="area">{status.area_name}</span>{/if}
      {/if}
      {#if recommendation && config.show_recommendation}
        <span class="rec">rec. {recommendation}</span>
      {/if}
      <span class="prog">{current + 1}/{guide.steps.length}</span>
    </div>

    {#if config.timer_enabled && timer && timer.active}
      <div class="timer" class:paused={timer.manual_pause || timer.auto_paused || timer.afk_paused}>
        <span class="t-total">⏱ {fmtTime(timer.total_seconds + timer.act_seconds)}</span>
        <span class="t-act">acte {timer.current_act} · {fmtTime(timer.act_seconds)}</span>
        {#if timer.finished}
          <span class="t-flag done">terminé</span>
        {:else if timer.manual_pause}
          <span class="t-flag">pause</span>
        {:else if timer.afk_paused}
          <span class="t-flag">{focused ? "AFK" : "fenêtre"}</span>
        {:else if timer.auto_paused}
          <span class="t-flag">ville</span>
        {/if}
      </div>
      {#if timer.splits.some((s) => s > 0)}
        <div class="splits">
          {#each timer.splits as s, i}
            {#if s > 0}<span class="split">A{i} {fmtTime(s)}</span>{/if}
          {/each}
        </div>
      {/if}
    {/if}

    {#if currentStep}
      <StepView step={currentStep} areas={guide.areas} current={true} showOptionals={config.show_optionals} />
    {/if}
    {#each lookahead as step}
      <StepView {step} areas={guide.areas} showOptionals={config.show_optionals} />
    {/each}
  </div>
{/if}

<style>
  .overlay {
    background: rgba(15, 12, 8, 0.82);
    border: 1px solid var(--border);
    border-radius: 6px;
    overflow: hidden;
    width: 100%;
    backdrop-filter: blur(2px);
  }
  .overlay.editing {
    border-color: var(--accent);
    box-shadow: 0 0 0 2px rgba(200, 162, 74, 0.4);
  }
  .dragbar {
    background: var(--accent);
    color: #14110d;
    font-size: 0.8em;
    text-align: center;
    padding: 2px;
    cursor: move;
    user-select: none;
  }
  .header {
    display: flex;
    gap: 8px;
    align-items: center;
    padding: 4px 10px;
    background: rgba(0, 0, 0, 0.35);
    border-bottom: 1px solid var(--border);
    font-size: 0.85em;
  }
  .header .act {
    color: var(--accent);
    font-weight: 700;
  }
  .header .lvl {
    color: #cfa;
  }
  .header .area {
    color: var(--accent2);
    text-transform: capitalize;
  }
  .header .rec {
    color: var(--muted);
  }
  .header .prog {
    margin-left: auto;
    color: var(--muted);
  }
  .timer {
    display: flex;
    gap: 10px;
    align-items: center;
    padding: 2px 10px;
    background: rgba(0, 0, 0, 0.25);
    border-bottom: 1px solid var(--border);
    font-size: 0.85em;
  }
  .timer .t-total {
    color: var(--accent);
    font-weight: 700;
  }
  .timer .t-act {
    color: var(--text);
  }
  .timer.paused .t-total,
  .timer.paused .t-act {
    color: var(--muted);
  }
  .timer .t-flag {
    margin-left: auto;
    color: #e0c84a;
    text-transform: uppercase;
    font-size: 0.85em;
  }
  .timer .t-flag.done {
    color: #7CFC00;
  }
  .splits {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding: 2px 10px 4px;
    background: rgba(0, 0, 0, 0.18);
    border-bottom: 1px solid var(--border);
    font-size: 0.78em;
  }
  .splits .split {
    color: var(--muted);
  }
</style>
