// flippy-hud.jsx — shared HUD primitives
// All components attached to window for cross-script access.

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

// =====================================================================
// useReveal — IntersectionObserver-driven reveal on scroll
// =====================================================================
function useReveal(opts = {}) {
  const ref = useRef(null);
  const [shown, setShown] = useState(false);
  useEffect(() => {
    if (!ref.current) return;
    if (shown) return;
    const obs = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) { setShown(true); obs.disconnect(); }
        });
      },
      { threshold: opts.threshold ?? 0.18, rootMargin: opts.rootMargin ?? "0px 0px -10% 0px" }
    );
    obs.observe(ref.current);
    return () => obs.disconnect();
  }, []);
  return [ref, shown];
}

// =====================================================================
// Reveal — wraps children with a tactical slam-in reveal
// =====================================================================
function Reveal({ children, delay = 0, dir = "up", as: Tag = "div", className = "", ...rest }) {
  const [ref, shown] = useReveal();
  const tx = {
    up:    "translate3d(0, 24px, 0)",
    down:  "translate3d(0, -16px, 0)",
    left:  "translate3d(24px, 0, 0)",
    right: "translate3d(-24px, 0, 0)",
    none:  "translate3d(0, 0, 0)",
  }[dir] || "translate3d(0, 24px, 0)";
  const style = {
    transform: shown ? "translate3d(0,0,0)" : tx,
    opacity: shown ? 1 : 0,
    transition: `transform 720ms cubic-bezier(0.2,0.9,0.2,1) ${delay}ms, opacity 540ms cubic-bezier(0.2,0.9,0.2,1) ${delay}ms`,
    willChange: "transform, opacity",
  };
  return <Tag ref={ref} style={style} className={className} {...rest}>{children}</Tag>;
}

// =====================================================================
// Glitch — wraps a string, occasionally fires a glitch effect on the text
// =====================================================================
function GlitchText({ children, className = "", style }) {
  return (
    <span className={`gx ${className}`} data-text={typeof children === "string" ? children : ""} style={style}>
      {children}
    </span>
  );
}

// =====================================================================
// TypeOut — typewriter
// =====================================================================
function TypeOut({ text, speed = 24, onDone, className = "" }) {
  const [i, setI] = useState(0);
  useEffect(() => {
    if (i >= text.length) { onDone && onDone(); return; }
    const t = setTimeout(() => setI(i + 1), speed);
    return () => clearTimeout(t);
  }, [i, text, speed]);
  return (
    <span className={className}>
      {text.slice(0, i)}
      <span className="blink" style={{ color: "var(--acid)" }}>▌</span>
    </span>
  );
}

// =====================================================================
// CountUp — animates a number from 0 to value when in view
// =====================================================================
function CountUp({ to, suffix = "", prefix = "", duration = 1600, fmt }) {
  const [ref, shown] = useReveal();
  const [v, setV] = useState(0);
  useEffect(() => {
    if (!shown) return;
    let start;
    let raf;
    const step = (ts) => {
      if (!start) start = ts;
      const t = Math.min(1, (ts - start) / duration);
      const eased = 1 - Math.pow(1 - t, 3);
      setV(Math.round(to * eased));
      if (t < 1) raf = requestAnimationFrame(step);
    };
    raf = requestAnimationFrame(step);
    return () => cancelAnimationFrame(raf);
  }, [shown, to, duration]);
  const out = fmt ? fmt(v) : v.toLocaleString();
  return <span ref={ref}>{prefix}{out}{suffix}</span>;
}

// =====================================================================
// HudReadout — small terminal-style readout panel
// =====================================================================
function HudReadout({ label, rows, className = "" }) {
  return (
    <div className={`hud-readout ${className}`}>
      <div className="row" style={{ marginBottom: 6 }}>
        <span style={{ color: "var(--acid)", fontWeight: 700 }}>{label}</span>
        <span className="blink">●</span>
      </div>
      {rows.map((r, i) => (
        <div className="row" key={i}>
          <span className="k">{r[0]}</span>
          <span>{r[1]}</span>
        </div>
      ))}
    </div>
  );
}

// =====================================================================
// CopyButton — copies CA / text
// =====================================================================
function CopyButton({ value, children = "COPY", className = "copy" }) {
  const [done, setDone] = useState(false);
  return (
    <button
      className={className}
      onClick={() => {
        try { navigator.clipboard.writeText(value); } catch (e) {}
        setDone(true);
        setTimeout(() => setDone(false), 1200);
      }}
    >
      {done ? "✓ LOCKED" : children}
    </button>
  );
}

// Make available globally
Object.assign(window, {
  useReveal, Reveal, GlitchText, TypeOut, CountUp, HudReadout, CopyButton,
});
