/* ───────────────────────────────────────────────────────────────────────────
   Wivexx minimized overlay — the same WebGL DOT as the control room, in a tiny
   always-on-top window. Click to reopen the control room, drag to move.
   Python drives state through `window.wivexxOverlay.*`; this page calls back
   through `pywebview.api.*` (restore_main / start_drag).
   ─────────────────────────────────────────────────────────────────────────── */
(function () {
  "use strict";

  const CAPTIONS = { idle: "ready", listening: "listening…", processing: "thinking…", speaking: "speaking" };
  let _pyReady = false;
  const _queue = [];

  function py(method, ...args) {
    const run = () => { try { return window.pywebview.api[method](...args); } catch (e) {} };
    if (_pyReady && window.pywebview && window.pywebview.api) return run();
    _queue.push(run);
  }
  function flushQueue() { _pyReady = true; while (_queue.length) { try { _queue.shift()(); } catch (e) {} } }

  const cap = () => document.getElementById("cap");

  let _minimal = false;
  const menu = () => document.getElementById("ctx");

  // ── surface Python drives ──────────────────────────────────────────────────
  window.wivexxOverlay = {
    setState(s) {
      if (!CAPTIONS[s]) return;
      window.WivexxDot && window.WivexxDot.setState(s);
      const c = cap();
      if (c) { c.textContent = CAPTIONS[s]; c.style.color = (s === "idle") ? "var(--stone)" : "var(--volt)"; }
    },
    setLevel(v) { window.WivexxDot && window.WivexxDot.setLevel(v); },
    applyMinimal(on) {
      _minimal = !!on;
      document.body.classList.toggle("minimal", _minimal);
      window.WivexxDot && window.WivexxDot.setMinimal && window.WivexxDot.setMinimal(_minimal);
      const b = document.getElementById("ctx-min");
      if (b) b.textContent = (_minimal ? "● full overlay" : "○ minimalist mode");
    },
  };

  // ── right-click context menu ────────────────────────────────────────────────
  function hideMenu() { const m = menu(); if (m) m.classList.add("hidden"); }
  function showMenu(x, y) {
    const m = menu(); if (!m) return;
    m.classList.remove("hidden");
    const w = m.offsetWidth, h = m.offsetHeight;
    m.style.left = Math.max(2, Math.min(x, window.innerWidth - w - 2)) + "px";
    m.style.top = Math.max(2, Math.min(y, window.innerHeight - h - 2)) + "px";
  }
  function wireMenu() {
    document.addEventListener("contextmenu", (e) => { e.preventDefault(); showMenu(e.clientX, e.clientY); });
    menu().addEventListener("click", (e) => {
      const b = e.target.closest("button"); if (!b) return;
      const act = b.getAttribute("data-act");
      hideMenu();
      if (act === "open") py("restore_main");
      // the bare orb is a separate transparent tk window — this overlay just
      // hands off (Python hides this card window and shows the tk ball), so we
      // DON'T morph this window first (that briefly flashed a card-less ball)
      else if (act === "minimal") py("set_minimal", true);
      else if (act === "hide") py("hide_overlay");
      else if (act === "quit") py("quit_app");
    });
    document.addEventListener("keydown", (e) => { if (e.key === "Escape") hideMenu(); });
    window.addEventListener("blur", hideMenu);
  }

  // ── click to restore, drag to move (native drag once movement begins) ──────
  function wireInteract() {
    let downX = 0, downY = 0, dragging = false;
    const MOVED = 4;
    document.body.addEventListener("mousedown", (e) => {
      if (e.target.closest("#ctx")) return;     // menu handles its own clicks
      if (e.button !== 0) return;               // left button only
      hideMenu();
      downX = e.screenX; downY = e.screenY; dragging = false;
      e.preventDefault();
    });
    document.addEventListener("mousemove", (e) => {
      if (e.buttons === 0 || dragging) return;
      if (Math.abs(e.screenX - downX) > MOVED || Math.abs(e.screenY - downY) > MOVED) {
        dragging = true;
        py("start_drag");                 // hand off to the native Windows move loop
      }
    });
    document.addEventListener("mouseup", (e) => {
      if (e.button !== 0 || e.target.closest("#ctx")) { dragging = false; return; }
      const moved = Math.abs(e.screenX - downX) > MOVED || Math.abs(e.screenY - downY) > MOVED;
      if (!dragging && !moved) py("restore_main");
      dragging = false;
    });
  }

  function boot() {
    window.WivexxDot && window.WivexxDot.init(document.getElementById("dot"));
    window.wivexxOverlay.setState("idle");
    wireInteract();
    wireMenu();
    py("ready");
  }

  if (window.pywebview && window.pywebview.api) { _pyReady = true; }
  window.addEventListener("pywebviewready", flushQueue);
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", boot);
  else boot();
})();
