/* SpeakMind — the floating overlay live-dictation demo (the centerpiece).
   A looping state machine: idle → listening → processing → result, cycling demos. */

const { useState, useEffect, useRef, useCallback } = React;

/* ---- dictionary-highlight rich text (⟦term⟧ → vermilion chip) ---- */
function RichText({ text }) {
  const parts = [];
  let buf = "", inDict = false, key = 0;
  for (const ch of text) {
    if (ch === "⟦") { if (buf) parts.push(<span key={key++}>{buf}</span>); buf = ""; inDict = true; }
    else if (ch === "⟧") { if (buf) parts.push(<span key={key++} className="dict-hl">{buf}</span>); buf = ""; inDict = false; }
    else buf += ch;
  }
  if (buf) parts.push(inDict ? <span key={key++} className="dict-hl">{buf}</span> : <span key={key++}>{buf}</span>);
  return <>{parts}</>;
}

/* ---- tiny Swift highlighter ---- */
function highlightSwift(code) {
  const kw = /\b(func|let|var|try|await|async|return|throws|struct|enum|guard|if|else|self|import)\b/g;
  const ty = /\b(UserProfile|URL|URLSession|JSONDecoder|String|Int|Data|Bool)\b/g;
  // escape
  let h = code.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
  h = h.replace(/("(?:[^"\\]|\\.)*")/g, '<span class="str">$1</span>');
  h = h.replace(kw, '<span class="kw">$1</span>');
  h = h.replace(ty, '<span class="ty">$1</span>');
  h = h.replace(/\b([a-zA-Z_]\w*)(?=\()/g, '<span class="fn">$1</span>');
  return h;
}

/* ---- waveform ---- */
function Waveform({ live }) {
  const bars = 22;
  return (
    <div className={"wave" + (live ? " live" : "")}>
      {Array.from({ length: bars }).map((_, i) => (
        <i key={i} style={{
          height: live ? undefined : "8px",
          animationDuration: live ? `${0.5 + (i % 5) * 0.13}s` : undefined,
          animationDelay: live ? `${(i % 7) * 0.07}s` : undefined,
        }} />
      ))}
    </div>
  );
}

/* ---- result renderers ---- */
function ResultBody({ result }) {
  if (result.kind === "doc") {
    let liN = 0;
    return (
      <div className="doc">
        {result.blocks.map((b, i) => {
          if (b.t === "p") return <p key={i}><RichText text={b.v} /></p>;
          if (b.t === "h") return <h4 key={i}>{b.v}</h4>;
          if (b.t === "li") { liN++; const n = liN; return (
            <ul key={i} style={{ marginBottom: result.blocks[i+1]?.t === "li" ? 0 : 0 }}>
              <li><span className="n">{n}</span><span><RichText text={b.v} /></span></li>
            </ul>
          ); }
          return null;
        })}
      </div>
    );
  }
  if (result.kind === "prompt") return (
    <div>{result.rows.map((r, i) => (
      <div className="prompt-row" key={i}><div className="k">{r.k}</div><div className="v">{r.v}</div></div>
    ))}</div>
  );
  if (result.kind === "email") return (
    <div className="email"><div className="subj">{result.subject}</div><div className="body">{result.body}</div></div>
  );
  if (result.kind === "code") return (
    <pre className="code-block"><code dangerouslySetInnerHTML={{ __html: highlightSwift(result.code) }} /></pre>
  );
  return null;
}

const RESULT_LABEL = { doc: "Cleaned & structured", prompt: "Structured prompt", email: "Drafted email", code: "Generated code" };

/* ---- the overlay panel ---- */
function OverlayPanel({ demo, phase, shownWords, compact }) {
  const c = window.SM.ctx[demo.ctx];
  const isResult = phase === "result";
  return (
    <div className={"overlay" + (isResult && (demo.result.kind === "prompt" || demo.result.kind === "code") ? " wide" : "")}>
      <div className="ov-top">
        <span className="ctx-chip">
          <span className="g" style={{ background: c.color }}>{c.glyph}</span>
          {c.name}
          <span className="aware">Aware</span>
        </span>
        <span className={"ov-status" + (phase === "listening" ? " live" : isResult ? " ready" : "")}>
          <span className="led" />
          {phase === "idle" && "Ready"}
          {phase === "listening" && "Listening"}
          {phase === "processing" && "Working"}
          {isResult && "Ready to insert"}
        </span>
      </div>

      {!isResult && (
        <div className="ov-modes">
          {window.SM.modes.slice(0, 5).map((m) => (
            <span key={m.id} className={"m" + (m.name === demo.mode.name ? " on" : "")}>
              <span className="mi">{m.icon}</span>{m.name}
            </span>
          ))}
        </div>
      )}

      {phase === "idle" && (
        <div className="ov-mic">
          <button className="mic-btn"><MicGlyph /></button>
          <div className="ov-hint">Hold <kbd>⌥ Space</kbd> and speak</div>
        </div>
      )}

      {phase === "listening" && (
        <div className="ov-mic">
          <Waveform live />
          <div className="transcript">
            {shownWords.map((w, i) => <span key={i} className="w">{w}{" "}</span>)}
            <span className="caret" />
          </div>
        </div>
      )}

      {phase === "processing" && (
        <div className="ov-mic">
          <Waveform live={false} />
          <div className="proc"><span className="spin" /><span className="pm">{demo.processing}</span></div>
        </div>
      )}

      {isResult && (
        <>
          <div className="ov-result">
            <div className="res-label">{RESULT_LABEL[demo.result.kind]} · {demo.mode.name}</div>
            <ResultBody result={demo.result} />
          </div>
          <div className="ov-foot">
            <span className="tag"><span className="d" />Context-Aware · {c.name}</span>
            <span className="tag"><span className="d" />Memory Dictionary</span>
          </div>
          <div className="ov-actions">
            <button className="a primary">⏎ Insert</button>
            <button className="a ghost">⧉ Copy</button>
            <button className="a ghost">↺ Redo</button>
          </div>
        </>
      )}
    </div>
  );
}

function MicGlyph() {
  return (
    <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
      <rect x="9" y="2" width="6" height="12" rx="3" fill="currentColor" stroke="none" />
      <path d="M5 11a7 7 0 0 0 14 0" />
      <line x1="12" y1="18" x2="12" y2="22" />
    </svg>
  );
}

/* ---- the looping demo controller ---- */
function OverlayDemo({ onDemoChange }) {
  const [demoIdx, setDemoIdx] = useState(0);
  const [phase, setPhase] = useState("idle");
  const [wordCount, setWordCount] = useState(0);
  const timers = useRef([]);

  const demo = window.SM.demos[demoIdx];
  const words = demo.raw.split(" ");

  useEffect(() => {
    if (onDemoChange) onDemoChange(demo, phase);
  }, [demoIdx, phase]);

  useEffect(() => {
    const clear = () => { timers.current.forEach(clearTimeout); timers.current = []; };
    const add = (fn, ms) => timers.current.push(setTimeout(fn, ms));

    // run one full cycle for the current demo
    setPhase("idle"); setWordCount(0);
    add(() => {
      setPhase("listening");
      const per = Math.max(95, Math.min(150, 2400 / words.length));
      words.forEach((_, i) => add(() => setWordCount(i + 1), per * (i + 1)));
      const listenEnd = per * words.length + 650;
      add(() => setPhase("processing"), listenEnd);
      add(() => setPhase("result"), listenEnd + 1150);
      add(() => setDemoIdx((d) => (d + 1) % window.SM.demos.length), listenEnd + 1150 + 4400);
    }, 850);

    return clear;
  }, [demoIdx]);

  return <OverlayPanel demo={demo} phase={phase} shownWords={words.slice(0, wordCount)} />;
}

window.SMOverlay = { OverlayDemo, OverlayPanel, RichText, Waveform, MicGlyph, highlightSwift };
