// Technical visualisations — spectrum analyzer, waveform, SPL meter, polar response

// Frequency response curve (smooth animated)
function SpectrumAnalyzer({ height = 280, bars = 64, animated = true }) {
  const [frame, setFrame] = React.useState(0);
  React.useEffect(() => {
    if (!animated) return;
    let id; const tick = () => { setFrame(f => f + 1); id = requestAnimationFrame(tick); };
    id = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(id);
  }, [animated]);

  // Generate a frequency-response-like curve
  const width = 1000, h = 280;
  const t = frame * 0.008;
  const pts = [];
  for (let i = 0; i <= bars; i++) {
    const x = (i / bars) * width;
    // Log-ish frequency emphasis + rolling peaks
    const freqN = i / bars;
    const base = 0.55
      + 0.12 * Math.sin(freqN * 8 + t * 1.1)
      + 0.08 * Math.sin(freqN * 14 - t * 0.7)
      + 0.04 * Math.sin(freqN * 30 + t * 2);
    // roll-off at extremes
    const rolloff = 1 - Math.pow(Math.abs(freqN - 0.5) * 1.8, 3);
    const v = Math.max(0.05, Math.min(0.95, base * rolloff + 0.15));
    pts.push([x, h - v * h]);
  }
  // smooth path
  let d = `M 0 ${h} L ${pts[0][0]} ${pts[0][1]}`;
  for (let i = 1; i < pts.length; i++) {
    const [x1, y1] = pts[i - 1], [x2, y2] = pts[i];
    const cx = (x1 + x2) / 2;
    d += ` Q ${x1} ${y1} ${cx} ${(y1 + y2) / 2}`;
  }
  d += ` L ${width} ${h} Z`;

  // peak dots
  const peaks = pts.filter((_, i) => i % 8 === 0);

  return (
    <div className="analyzer" style={{ height }}>
      <svg className="analyzer-svg" viewBox={`0 0 ${width} ${h}`} preserveAspectRatio="none">
        <defs>
          <linearGradient id="spec-fill" x1="0" x2="0" y1="0" y2="1">
            <stop offset="0%" stopColor="var(--accent)" stopOpacity="0.45" />
            <stop offset="100%" stopColor="var(--accent)" stopOpacity="0" />
          </linearGradient>
        </defs>
        {/* target curve */}
        <path d={`M 0 ${h*0.5} L ${width} ${h*0.5}`} stroke="var(--accent-faint)" strokeDasharray="4 6" strokeWidth="1" fill="none" />
        <path d={d} fill="url(#spec-fill)" stroke="var(--accent)" strokeWidth="1.4" vectorEffect="non-scaling-stroke" />
        {peaks.map(([x, y], i) => (
          <circle key={i} cx={x} cy={y} r="2" fill="var(--accent)" />
        ))}
      </svg>
      <div className="analyzer-labels">
        <div className="analyzer-y">
          <span>+12</span><span>+6</span><span>0 dB</span><span>-6</span><span>-12</span>
        </div>
        <div className="analyzer-x">
          <span>20</span><span>100</span><span>500</span><span>1k</span><span>2k</span><span>5k</span><span>10k</span><span>20kHz</span>
        </div>
      </div>
    </div>
  );
}

// Waveform (horizontal, stereo)
function Waveform({ height = 120, seed = 1 }) {
  const bars = 120;
  const arr = React.useMemo(() => {
    const out = [];
    let s = seed * 1.7;
    for (let i = 0; i < bars; i++) {
      const env = Math.sin((i / bars) * Math.PI);
      const v = (Math.sin(s * 1.3) * 0.5 + 0.5) * (0.25 + 0.75 * env);
      out.push(Math.max(0.05, v));
      s += 0.37;
    }
    return out;
  }, [seed]);
  return (
    <svg width="100%" height={height} viewBox={`0 0 ${bars*3} 100`} preserveAspectRatio="none" style={{ display: 'block' }}>
      {arr.map((v, i) => (
        <rect key={i} x={i*3} y={50 - v*48} width="2" height={v*96} fill="var(--text-2)" opacity={0.7 - (v < 0.2 ? 0.3 : 0)} />
      ))}
    </svg>
  );
}

// Vertical level meter (stereo)
function LevelMeter({ label = "L", target = 0.7 }) {
  const [level, setLevel] = React.useState(0.5);
  const [peak, setPeak] = React.useState(0.6);
  React.useEffect(() => {
    let peakTimer;
    const id = setInterval(() => {
      setLevel(l => {
        const next = Math.max(0.1, Math.min(0.95, target + (Math.random() - 0.5) * 0.4));
        setPeak(p => Math.max(p * 0.985, next));
        return next;
      });
    }, 120);
    return () => { clearInterval(id); clearTimeout(peakTimer); };
  }, [target]);

  const segs = 20;
  return (
    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4, fontFamily: 'var(--mono)', fontSize: 10, color: 'var(--muted)' }}>
      <div style={{ width: 16, height: 160, background: '#0a0b0d', border: '1px solid var(--line)', display: 'flex', flexDirection: 'column-reverse', padding: 1, gap: 1 }}>
        {Array.from({ length: segs }).map((_, i) => {
          const on = (i / segs) < level;
          const color = i > segs * 0.85 ? 'var(--red)' : i > segs * 0.65 ? 'var(--accent)' : 'var(--green)';
          return <div key={i} style={{ flex: 1, background: on ? color : 'transparent', opacity: on ? 0.9 : 0.15 }} />;
        })}
      </div>
      <span>{label}</span>
    </div>
  );
}

// Polar dispersion diagram
function PolarPattern({ size = 200 }) {
  const pts = [];
  const N = 72;
  for (let i = 0; i < N; i++) {
    const a = (i / N) * Math.PI * 2;
    // cardioid-ish
    const r = 0.55 + 0.4 * Math.max(0, Math.cos(a - Math.PI/2));
    const x = size/2 + Math.cos(a) * r * size/2;
    const y = size/2 + Math.sin(a) * r * size/2;
    pts.push(`${x},${y}`);
  }
  return (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
      {[0.25, 0.5, 0.75, 1].map((s, i) => (
        <circle key={i} cx={size/2} cy={size/2} r={(size/2)*s} fill="none" stroke="var(--line)" strokeDasharray="2 3" />
      ))}
      <line x1={size/2} y1="0" x2={size/2} y2={size} stroke="var(--line)" />
      <line x1="0" y1={size/2} x2={size} y2={size/2} stroke="var(--line)" />
      <polygon points={pts.join(' ')} fill="var(--accent)" opacity="0.12" stroke="var(--accent)" strokeWidth="1.2" />
    </svg>
  );
}

// Animated "signal flow" diagram
function SignalChain() {
  const items = [
    { label: 'SRC', sub: '信源' },
    { label: 'PRE', sub: '前級' },
    { label: 'EQ',  sub: '等化' },
    { label: 'DSP', sub: '處理' },
    { label: 'AMP', sub: '功放' },
    { label: 'SPK', sub: '揚聲' },
  ];
  const [active, setActive] = React.useState(0);
  React.useEffect(() => {
    const id = setInterval(() => setActive(a => (a + 1) % items.length), 700);
    return () => clearInterval(id);
  }, []);
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontFamily: 'var(--mono)', fontSize: 11 }}>
      {items.map((it, i) => (
        <React.Fragment key={i}>
          <div style={{
            padding: '10px 12px',
            border: `1px solid ${i === active ? 'var(--accent)' : 'var(--line)'}`,
            color: i === active ? 'var(--accent)' : 'var(--text-2)',
            background: i === active ? 'rgba(218, 165, 32, 0.08)' : 'transparent',
            transition: 'all .2s',
            minWidth: 58, textAlign: 'center',
          }}>
            <div style={{ fontWeight: 600, letterSpacing: '0.1em' }}>{it.label}</div>
            <div style={{ fontSize: 9, color: 'var(--muted)', marginTop: 2 }}>{it.sub}</div>
          </div>
          {i < items.length - 1 && (
            <div style={{ width: 16, height: 1, background: i < active ? 'var(--accent)' : 'var(--line)' }} />
          )}
        </React.Fragment>
      ))}
    </div>
  );
}

Object.assign(window, { SpectrumAnalyzer, Waveform, LevelMeter, PolarPattern, SignalChain });
