/* ========================================================================
   LUMINA — Auto VJ (hands-free autopilot)
   Automatically morphs parameters, switches visualizers, fires stingers,
   and changes colors in sync with the music. For hands-free operation.
   ======================================================================== */
(function () {
  const { useState, useEffect, useRef } = React;

  function AutoVJ() {
    const [open, setOpen] = useState(false);
    const [active, setActive] = useState(false);
    const [, tick] = useState(0);
    const cfg = useRef({
      switchViz: true, switchBars: 16,
      morphParams: true,
      autoColor: true, colorBars: 8,
      fireStingers: false,
      autoFx: false,
      energy: 1,
    });
    const lastBarRef = useRef(0);
    const lastColorBar = useRef(0);

    useEffect(() => {
      if (!active) return;
      let raf;
      const loop = () => {
        const C = window.LuminaClock;
        const c = cfg.current;
        if (C) {
          const bar = C.bar;
          // Visualizer switching
          if (c.switchViz && bar - lastBarRef.current >= c.switchBars) {
            lastBarRef.current = bar;
            const list = window.VISUALIZERS || [];
            if (list.length && window.__setVizId) {
              const next = list[Math.floor(Math.random() * list.length)];
              window.__setVizId(next.id);
            }
            if (c.fireStingers && window.Stingers) {
              const keys = Object.keys(window.Stingers.list);
              window.Stingers.fire(keys[Math.floor(Math.random() * keys.length)]);
            }
            if (c.autoFx && window.Prog) {
              // occasionally toggle a random FX
              const fxKeys = Object.keys(window.FXTypes);
              if (Math.random() > 0.5 && window.Prog.fxChain.length < 3) {
                window.Prog.addFX(fxKeys[Math.floor(Math.random() * fxKeys.length)]);
              } else if (window.Prog.fxChain.length) {
                window.Prog.removeFX(window.Prog.fxChain[0].id);
              }
            }
          }
          // Color cycling
          if (c.autoColor && bar - lastColorBar.current >= c.colorBars) {
            lastColorBar.current = bar;
            if (window.__paramsApply && window.__paramsSnapshot) {
              const p = window.__paramsSnapshot();
              window.__paramsApply({ ...p, hue: Math.floor(Math.random() * 360) });
            }
          }
        }
        // Parameter morphing on audio
        if (c.morphParams && window.__paramsSnapshot && window.__paramsApply) {
          const A = window.AudioEngine || {};
          const p = window.__paramsSnapshot();
          const tt = performance.now() / 1000;
          window.__paramsApply({
            ...p,
            intensity: (0.8 + Math.sin(tt * 0.3) * 0.4 + (A.bass || 0) * 0.6) * c.energy,
            motion: 0.8 + Math.sin(tt * 0.17) * 0.6 + (A.energy || 0) * 0.8,
            glow: 0.7 + Math.sin(tt * 0.23) * 0.5 + (A.high || 0) * 0.6,
          });
        }
        raf = requestAnimationFrame(loop);
      };
      raf = requestAnimationFrame(loop);
      return () => cancelAnimationFrame(raf);
    }, [active]);

    if (!open) {
      return (
        <button onClick={() => setOpen(true)}
          style={{
            padding: "8px 14px", border: "none", borderRadius: 8,
            background: active
              ? "radial-gradient(circle at 50% 0%, #d4ffd4 0%, #7cff4f 40%, #1f6a2f 100%)"
              : "linear-gradient(180deg, var(--panel-hi), var(--panel))",
            color: active ? "#062a10" : "var(--led-green)",
            fontFamily: "var(--font-display)", fontWeight: 800, fontSize: 11,
            letterSpacing: "0.18em", textTransform: "uppercase",
            cursor: "pointer",
            boxShadow: active
              ? "inset 0 1px 0 rgba(255,255,255,0.4), 0 0 14px rgba(124,255,79,0.5)"
              : "var(--nshadow-out-sm)",
            display: "flex", alignItems: "center", gap: 6,
            textShadow: active ? "none" : "0 0 4px var(--led-green-glow)",
          }}>
          <span style={{
            width: 8, height: 8, borderRadius: "50%",
            background: active ? "#062a10" : "var(--led-green)",
            boxShadow: active ? "0 0 6px #fff" : "0 0 6px var(--led-green-glow)",
            animation: active ? "pulse 1.5s infinite" : "none",
          }} />
          🤖 Auto VJ {active ? "ON" : ""}
        </button>
      );
    }

    const c = cfg.current;
    const upd = () => tick(n => n + 1);

    return (
      <div style={{
        width: 280,
        background: "linear-gradient(180deg, var(--panel-hi), var(--panel-lo))",
        borderRadius: 10, padding: 12,
        boxShadow: "0 20px 50px rgba(0,0,0,0.7), 0 0 0 1px rgba(124,255,79,0.3)",
      }}>
        <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 10 }}>
          <span style={{
            fontFamily: "var(--font-display)", fontWeight: 800, fontSize: 12,
            letterSpacing: "0.16em", textTransform: "uppercase",
            color: "var(--led-green)", flex: 1, textShadow: "0 0 4px var(--led-green-glow)",
          }}>🤖 Auto VJ</span>
          <button data-lum-close="1" className="nbtn compact" onClick={() => setOpen(false)} style={{ padding: "2px 7px" }}>×</button>
        </div>

        <button
          onClick={() => setActive(a => !a)}
          style={{
            width: "100%", padding: "12px", marginBottom: 12, border: "none", borderRadius: 8,
            background: active
              ? "radial-gradient(circle at 50% 0%, #d4ffd4 0%, #7cff4f 40%, #1f6a2f 100%)"
              : "linear-gradient(180deg, #2a2a30, #1a1a1e)",
            color: active ? "#062a10" : "var(--ink)",
            fontFamily: "var(--font-display)", fontWeight: 800, fontSize: 13,
            letterSpacing: "0.16em", textTransform: "uppercase", cursor: "pointer",
            boxShadow: active ? "inset 0 1px 0 rgba(255,255,255,0.4), 0 0 16px rgba(124,255,79,0.5)" : "var(--nshadow-out-sm)",
          }}>
          {active ? "● RUNNING — STOP" : "▶ ENGAGE AUTO VJ"}
        </button>

        {[
          { k: "switchViz", label: "Auto-switch visualizers" },
          { k: "morphParams", label: "Morph parameters to audio" },
          { k: "autoColor", label: "Cycle colors" },
          { k: "fireStingers", label: "Fire stingers on change" },
          { k: "autoFx", label: "Auto add/remove FX" },
        ].map(o => (
          <div key={o.k} style={{
            display: "flex", justifyContent: "space-between", alignItems: "center",
            padding: "6px 0", borderBottom: "1px solid rgba(255,255,255,0.04)",
          }}>
            <span style={{ fontSize: 11, color: "var(--ink-dim)" }}>{o.label}</span>
            <div className={`flip ${c[o.k] ? "on" : ""}`}
              onClick={() => { c[o.k] = !c[o.k]; upd(); }}
              style={{ position: "relative", width: 38, height: 22,
                background: "linear-gradient(180deg, #0a0a0c, #1a1a1e)", borderRadius: 4,
                boxShadow: "var(--nshadow-in-sm)", cursor: "pointer", flexShrink: 0 }}>
              <div className="flip-lever" style={{
                position: "absolute", top: 2, left: c[o.k] ? 20 : 2,
                width: 16, height: 18, borderRadius: 3,
                background: c[o.k] ? "linear-gradient(180deg, var(--led-green), var(--led-green-glow))"
                  : "linear-gradient(180deg, #5a5a64, #2a2a30)",
                boxShadow: c[o.k] ? "0 0 6px var(--led-green-glow)" : "0 2px 3px rgba(0,0,0,0.7)",
                transition: "left 0.15s",
              }} />
            </div>
          </div>
        ))}

        <div style={{ marginTop: 10 }}>
          <div className="cap" style={{ marginBottom: 4 }}>
            Switch every {c.switchBars} bars
          </div>
          <input type="range" min="2" max="64" step="2" value={c.switchBars}
            onChange={(e) => { c.switchBars = Number(e.target.value); upd(); }}
            style={{ width: "100%" }} />
        </div>
        <div style={{ marginTop: 8 }}>
          <div className="cap" style={{ marginBottom: 4 }}>
            Intensity × {c.energy.toFixed(1)}
          </div>
          <input type="range" min="0.3" max="2" step="0.1" value={c.energy}
            onChange={(e) => { c.energy = Number(e.target.value); upd(); }}
            style={{ width: "100%" }} />
        </div>

        <div style={{ fontSize: 9, color: "var(--ink-faint)", lineHeight: 1.5,
          marginTop: 10, textAlign: "center" }}>
          Hands-free mode · syncs to Master Clock BPM ·
          tap TAP in the clock panel to lock tempo first.
        </div>
      </div>
    );
  }

  function mount() {
    if (!window.React || !window.ReactDOM) { setTimeout(mount, 100); return; }
    let host = document.getElementById("__autovj_panel");
    if (!host) {
      host = document.createElement("div");
      host.id = "__autovj_panel";
      host.style.cssText = "position: fixed; z-index: 596;";
      document.body.appendChild(host);
    }
    ReactDOM.createRoot(host).render(<AutoVJ />);
  }
  if (document.readyState === "complete" || document.readyState === "interactive") setTimeout(mount, 1300);
  else document.addEventListener("DOMContentLoaded", () => setTimeout(mount, 1300));
})();
