// Alligator Signal — Tweaks panel + headline typewriter
const { useEffect, useRef } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "dark": true,
  "headline": "auto"
}/*EDITMODE-END*/;

const HEADLINES = {
  "five-seconds": {
    label: "Five seconds.",
    lines: ["Five seconds.", "One signal.", "Zero hesitation."],
    italicLast: true,
    sub: "Alligator Signal reads Pocket Option's live tape through a WebSocket side-channel and prints a confidence-scored BUY or SELL before the next candle closes. Built for traders who already know the Jaws, Teeth & Lips by heart."
  },
  "math-bites": {
    label: "The math bites first.",
    lines: ["The math", "bites first.", "You just follow."],
    italicLast: true,
    sub: "Jaws, Teeth and Lips — recomputed every tick, scored 1 to 10, and slammed onto your chart before the next candle even thinks about closing."
  },
  "stop-guessing": {
    label: "Stop calculating.",
    lines: ["Stop", "calculating.", "Start biting."],
    italicLast: true,
    sub: "Williams' Alligator, executed by a 56-kilobyte Chrome extension that hooks Pocket Option's WebSocket and prints a 1-to-10 confidence call every five seconds."
  }
};

const VARIANT_ORDER = ["five-seconds", "math-bites", "stop-guessing"];

/* ---------------- typewriter primitives ---------------- */

const sleep = (ms, signal) => new Promise((res, rej) => {
  if (signal?.aborted) return rej(new DOMException('Aborted', 'AbortError'));
  const t = setTimeout(res, ms);
  signal?.addEventListener('abort', () => { clearTimeout(t); rej(new DOMException('Aborted', 'AbortError')); }, { once: true });
});

// Type a string char-by-char into target (Text node target.firstChild).
async function typeInto(target, text, perChar, signal) {
  const textNode = target.firstChild; // pre-seeded empty text node
  for (let i = 0; i < text.length; i++) {
    if (signal?.aborted) throw new DOMException('Aborted', 'AbortError');
    textNode.data = text.slice(0, i + 1);
    // small jitter for human feel; near-zero on spaces
    const jitter = text[i] === ' ' ? 0 : (Math.random() * 22) - 6;
    await sleep(perChar + jitter, signal);
  }
}

async function eraseFrom(target, perChar, signal) {
  const textNode = target.firstChild;
  let s = textNode.data;
  while (s.length > 0) {
    if (signal?.aborted) throw new DOMException('Aborted', 'AbortError');
    s = s.slice(0, -1);
    textNode.data = s;
    await sleep(perChar, signal);
  }
}

/* ---------------- headline renderer ---------------- */
// Builds 3 empty line-containers + a blinking caret element.
// Returns refs the typewriter loop can drive.
function buildHeadlineSkeleton(display) {
  display.innerHTML = '';
  const lineEls = [];
  for (let i = 0; i < 3; i++) {
    const span = document.createElement('span');
    span.setAttribute('data-headline-line', String(i));
    // inner element that holds the text (so we can wrap with <em> for last line)
    const inner = document.createElement('span');
    inner.className = 'tw-inner';
    inner.appendChild(document.createTextNode(''));
    span.appendChild(inner);
    display.appendChild(span);
    lineEls.push({ span, inner });
  }
  // caret — appended to whichever line is currently being typed
  const caret = document.createElement('span');
  caret.className = 'tw-caret';
  caret.textContent = '\u258F'; // left one-eighth block — sharp terminal caret
  return { lineEls, caret };
}

function applyVariantStyling(lineEls, variant) {
  // Wrap the LAST line's inner in <em> if italicLast, else plain
  const last = lineEls[lineEls.length - 1].inner;
  // reset class
  last.classList.toggle('tw-italic', !!variant.italicLast);
}

/* ---------------- main typewriter loop ---------------- */

async function runTypewriter({ display, subhead, mode, signal }) {
  const variants = mode === 'auto'
    ? VARIANT_ORDER.map(k => HEADLINES[k])
    : [HEADLINES[mode] || HEADLINES['five-seconds']];

  const { lineEls, caret } = buildHeadlineSkeleton(display);

  // typing speeds
  const TYPE_MS  = 38;
  const ERASE_MS = 18;
  const HOLD_MS  = 2200;     // after all 3 lines typed
  const INTERLINE_MS = 220;  // pause between typing each line
  const AFTER_ERASE_MS = 280;

  let variantIdx = 0;

  while (!signal.aborted) {
    const variant = variants[variantIdx % variants.length];
    applyVariantStyling(lineEls, variant);

    // sub-headline crossfade
    if (subhead) {
      subhead.style.transition = 'opacity .35s ease';
      subhead.style.opacity = '0';
      await sleep(180, signal);
      subhead.textContent = variant.sub;
      subhead.style.opacity = '1';
    }

    // type each line
    for (let i = 0; i < variant.lines.length; i++) {
      lineEls[i].inner.appendChild(caret);
      await sleep(INTERLINE_MS, signal);
      await typeInto(lineEls[i].inner, variant.lines[i], TYPE_MS, signal);
    }

    // hold (caret keeps blinking on last line)
    await sleep(HOLD_MS, signal);

    // if only one variant (manual pick), stop here — keep caret blinking forever
    if (variants.length === 1) return;

    // erase in reverse
    for (let i = variant.lines.length - 1; i >= 0; i--) {
      // move caret to this line first
      lineEls[i].inner.appendChild(caret);
      await sleep(120, signal);
      await eraseFrom(lineEls[i].inner, ERASE_MS, signal);
    }

    await sleep(AFTER_ERASE_MS, signal);
    variantIdx++;
  }
}

/* ---------------- App ---------------- */

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const abortRef = useRef(null);

  // theme
  useEffect(() => {
    document.documentElement.setAttribute("data-theme", t.dark ? "dark" : "light");
  }, [t.dark]);

  // headline typewriter
  useEffect(() => {
    // cancel any previous loop
    if (abortRef.current) abortRef.current.abort();
    const ctrl = new AbortController();
    abortRef.current = ctrl;

    const display = document.querySelector('[data-headline]');
    const subhead = document.querySelector('[data-subhead]');
    if (!display) return;

    runTypewriter({ display, subhead, mode: t.headline, signal: ctrl.signal })
      .catch(err => { if (err?.name !== 'AbortError') console.error(err); });

    return () => ctrl.abort();
  }, [t.headline]);

  const variantOptions = [
    { value: 'auto', label: 'Auto-cycle (all 3)' },
    ...VARIANT_ORDER.map(k => ({ value: k, label: HEADLINES[k].label })),
  ];

  return (
    <TweaksPanel>
      <TweakSection label="Theme" />
      <TweakToggle
        label="Dark mode"
        value={t.dark}
        onChange={(v) => setTweak('dark', v)}
      />
      <TweakSection label="Headline copy" />
      <TweakSelect
        label="Variant"
        value={t.headline}
        options={variantOptions}
        onChange={(v) => setTweak('headline', v)}
      />
    </TweaksPanel>
  );
}

const root = ReactDOM.createRoot(document.getElementById('tweaks-root'));
root.render(<App />);
