/* visuals8.jsx — AC: the wave.
   A sloshing reservoir that pushes water back and forth, and an oscilloscope
   trace. `freq` = how fast it sloshes; `amp` = how hard. A phase clock drives
   both the water motion and the scope. DC shown as a flat line for contrast.  */

/* live animation hook: returns a phase 0..1 advancing at `freq` Hz (scaled). */
function useAcPhase(freq, running = true) {
  const [phase, setPhase] = React.useState(0);
  const ref = React.useRef(0);
  React.useEffect(() => {
    if (!running) return;
    let raf, last = performance.now();
    const tick = (now) => {
      const dt = (now - last) / 1000; last = now;
      ref.current = (ref.current + dt * freq) % 1;
      setPhase(ref.current);
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [freq, running]);
  return phase;
}

/* ─── AcWaterScene ───────────────────────────────────────────────────────
   A U-shaped tube. The water surface tilts back and forth (AC) or sits
   steady tilted (DC). A paddle/piston at the left drives it.
   ───────────────────────────────────────────────────────────────────────── */
function AcWaterScene({ mode = "ac", amp = 1, phase = 0, height = 360, showLabels = true }) {
  const W = 820, H = 460;
  const cx = W / 2, baseY = 250, tubeW = 520, tubeH = 150;
  const left = cx - tubeW / 2, right = cx + tubeW / 2;

  // surface offset: AC oscillates, DC is a fixed tilt
  const swing = 54 * amp;
  const s = mode === "ac" ? Math.sin(phase * Math.PI * 2) : 1;
  const leftLevel = baseY - s * swing;
  const rightLevel = baseY + s * swing;

  // piston position (drives the left column)
  const pistonY = leftLevel - 36;

  // arrows show instantaneous flow direction
  const flowing = mode === "dc" || Math.abs(s) > 0.08;
  const dir = mode === "dc" ? 1 : (Math.cos(phase * Math.PI * 2) >= 0 ? 1 : -1);

  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" height={height}
         preserveAspectRatio="xMidYMid meet" style={{ display: "block", maxHeight: height }}>
      <defs>
        <linearGradient id="ac-water" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="var(--water-soft)" />
          <stop offset="100%" stopColor="var(--water)" />
        </linearGradient>
        <clipPath id="ac-tube">
          <path d={`M ${left} 90 L ${left} ${baseY + tubeH} Q ${left} ${baseY + tubeH + 30} ${left + 30} ${baseY + tubeH + 30}
                    L ${right - 30} ${baseY + tubeH + 30} Q ${right} ${baseY + tubeH + 30} ${right} ${baseY + tubeH}
                    L ${right} 90 L ${right - 44} 90 L ${right - 44} ${baseY + tubeH - 8}
                    Q ${right - 44} ${baseY + tubeH - 2} ${right - 52} ${baseY + tubeH - 2}
                    L ${left + 52} ${baseY + tubeH - 2} Q ${left + 44} ${baseY + tubeH - 2} ${left + 44} ${baseY + tubeH - 8}
                    L ${left + 44} 90 Z`} />
        </clipPath>
      </defs>

      {/* water fills both columns up to their (tilting) surfaces */}
      <g clipPath="url(#ac-tube)">
        <rect x={left} y={leftLevel} width={tubeW / 2} height={H} fill="url(#ac-water)" />
        <rect x={cx} y={rightLevel} width={tubeW / 2} height={H} fill="url(#ac-water)" />
        {/* surface highlights */}
        <rect x={left} y={leftLevel} width={tubeW / 2} height={4} fill="var(--water-deep)" opacity="0.5" />
        <rect x={cx} y={rightLevel} width={tubeW / 2} height={4} fill="var(--water-deep)" opacity="0.5" />
      </g>

      {/* tube outline */}
      <path d={`M ${left} 90 L ${left} ${baseY + tubeH} Q ${left} ${baseY + tubeH + 30} ${left + 30} ${baseY + tubeH + 30}
                L ${right - 30} ${baseY + tubeH + 30} Q ${right} ${baseY + tubeH + 30} ${right} ${baseY + tubeH}
                L ${right} 90 M ${left + 44} 90 L ${left + 44} ${baseY + tubeH - 8}
                Q ${left + 44} ${baseY + tubeH - 2} ${left + 52} ${baseY + tubeH - 2}
                L ${right - 52} ${baseY + tubeH - 2} Q ${right - 44} ${baseY + tubeH - 2} ${right - 44} ${baseY + tubeH - 8}
                L ${right - 44} 90`}
            fill="none" stroke="var(--ink)" strokeWidth="2.5" strokeLinejoin="round" />

      {/* driving piston on the left column */}
      <g style={{ transition: "none" }}>
        <rect x={left + 2} y={pistonY} width={42} height={16} rx={3}
              fill="var(--current)" stroke="var(--ink)" strokeWidth="2" />
        <line x1={left + 23} y1={pistonY} x2={left + 23} y2={pistonY - 26}
              stroke="var(--ink)" strokeWidth="3" />
        <circle cx={left + 23} cy={pistonY - 30} r="6" fill="var(--current)" stroke="var(--ink)" strokeWidth="2" />
      </g>

      {/* flow direction arrow in the bottom channel */}
      {flowing && (
        <g transform={`translate(${cx} ${baseY + tubeH + 14})`} opacity="0.9">
          <path d={dir > 0 ? "M -14 -6 L 4 0 L -14 6 L -9 0 Z" : "M 14 -6 L -4 0 L 14 6 L 9 0 Z"}
                fill="var(--current)" />
        </g>
      )}

      {showLabels && (
        <g fontFamily="IBM Plex Mono, monospace" letterSpacing="0.1em">
          <text x={left + 23} y={78} textAnchor="middle" fontSize="19" fill="var(--current)">DRIVER</text>
          <text x={cx} y={baseY + tubeH + 52} textAnchor="middle" fontSize="21.5"
                fill={mode === "ac" ? "var(--current)" : "var(--water)"}>
            {mode === "ac" ? "AC · sloshes back & forth" : "DC · steady one-way push"}
          </text>
        </g>
      )}
    </svg>
  );
}

/* ─── ScopeScene ─────────────────────────────────────────────────────────
   An oscilloscope trace: sine for AC (amp & freq), flat line for DC.
   ───────────────────────────────────────────────────────────────────────── */
function ScopeScene({ mode = "ac", amp = 1, freq = 1, phase = 0, height = 360, showLabels = true }) {
  const W = 820, H = 460;
  const x0 = 70, x1 = W - 50, midY = H / 2, span = 150 * amp;
  const cycles = mode === "ac" ? Math.max(1, Math.round(freq * 2)) : 0;

  // build the trace path
  const pts = [];
  const N = 240;
  for (let i = 0; i <= N; i++) {
    const x = x0 + (i / N) * (x1 - x0);
    let y = midY;
    if (mode === "ac") {
      const t = i / N;
      y = midY - Math.sin((t * cycles + phase) * Math.PI * 2) * span;
    } else {
      y = midY - span * 0.7;  // steady DC level
    }
    pts.push(`${x.toFixed(1)},${y.toFixed(1)}`);
  }
  const d = "M " + pts.join(" L ");

  // moving dot at the left edge (the "now" sample)
  const dotY = mode === "ac" ? midY - Math.sin(phase * Math.PI * 2) * span : midY - span * 0.7;

  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" height={height}
         preserveAspectRatio="xMidYMid meet" style={{ display: "block", maxHeight: height }}>
      {/* scope screen */}
      <rect x={40} y={40} width={W - 80} height={H - 80} rx="10"
            fill="var(--bg-deeper)" stroke="var(--rule-strong)" strokeWidth="1.5" />
      {/* grid */}
      {Array.from({ length: 9 }, (_, i) => (
        <line key={"v" + i} x1={x0 + (i / 8) * (x1 - x0)} y1={50} x2={x0 + (i / 8) * (x1 - x0)} y2={H - 50}
              stroke="var(--rule)" strokeWidth="0.7" />
      ))}
      {[-2, -1, 0, 1, 2].map(k => (
        <line key={"h" + k} x1={x0} y1={midY + k * (span / 2 || 40)} x2={x1} y2={midY + k * (span / 2 || 40)}
              stroke={k === 0 ? "var(--rule-strong)" : "var(--rule)"} strokeWidth={k === 0 ? 1.2 : 0.7} />
      ))}
      {/* zero line label */}
      <text x={x0 - 8} y={midY + 4} textAnchor="end" fontFamily="IBM Plex Mono, monospace"
            fontSize="15" fill="var(--ink-faint)">0V</text>

      {/* the trace */}
      <path d={d} fill="none" stroke="var(--current)" strokeWidth="2.5" strokeLinejoin="round" />
      {/* now-dot */}
      <circle cx={x0} cy={dotY} r="5" fill="var(--current)" />

      {showLabels && (
        <g fontFamily="IBM Plex Mono, monospace" letterSpacing="0.1em">
          <text x={W / 2} y={H - 22} textAnchor="middle" fontSize="20.5"
                fill={mode === "ac" ? "var(--current)" : "var(--water)"}>
            {mode === "ac" ? "voltage swings + and − over time" : "voltage holds steady"}
          </text>
          <text x={x1} y={64} textAnchor="end" fontSize="16" fill="var(--ink-faint)">
            {mode === "ac" ? `${freq.toFixed(1)}× speed` : "DC"}
          </text>
        </g>
      )}
    </svg>
  );
}

Object.assign(window, { useAcPhase, AcWaterScene, ScopeScene });
