// visuals.jsx - reusable visual elements: thumbnails, waveforms, sparklines, filmstrips

const { thumbGrad } = window.ZAMPP_DATA;

// AssetThumb — renders a placeholder thumbnail for an asset.
// For video: gradient background + scan lines + framed window + tiny "preview" content
// For audio: waveform
function AssetThumb({ asset, size = "md" }) {
  const aspect = size === "tall" ? "9 / 16" : "16 / 9";
  const seed = asset.seed || 1;

  if (asset.type === "audio") {
    return (
      <div className="asset-thumb audio" style={{ aspectRatio: aspect }}>
        <Waveform seed={seed} />
        <div className="thumb-overlay">
          <Icon name="audio" size={20} style={{ opacity: 0.9 }} />
        </div>
      </div>
    );
  }

  return (
    <div className="asset-thumb" style={{ background: thumbGrad(seed), aspectRatio: aspect }}>
      <FauxFrame seed={seed} />
      <div className="scanlines" />
    </div>
  );
}

// FauxFrame - draws a stylized video frame using shapes/SVG
function FauxFrame({ seed }) {
  // pick a "shot" type by seed
  const shots = ["stage", "track", "interview", "aerial", "crowd", "trophy"];
  const shot = shots[seed % shots.length];

  return (
    <svg viewBox="0 0 160 90" preserveAspectRatio="xMidYMid slice" className="thumb-svg">
      <defs>
        <linearGradient id={`sky-${seed}`} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stopColor="hsl(220 30% 18%)" />
          <stop offset="1" stopColor="hsl(280 25% 8%)" />
        </linearGradient>
        <linearGradient id={`ground-${seed}`} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stopColor="hsl(220 15% 12%)" />
          <stop offset="1" stopColor="hsl(220 15% 6%)" />
        </linearGradient>
      </defs>
      {shot === "stage" && (
        <>
          <rect width="160" height="55" fill={`url(#sky-${seed})`} />
          <rect y="55" width="160" height="35" fill={`url(#ground-${seed})`} />
          <circle cx="50" cy="30" r="14" fill="hsl(40 60% 50% / 0.6)" />
          <rect x="20" y="45" width="120" height="20" fill="hsl(220 30% 8% / 0.6)" />
          <rect x="40" y="55" width="6" height="20" fill="hsl(220 20% 40%)" />
          <rect x="55" y="50" width="6" height="25" fill="hsl(220 20% 40%)" />
          <rect x="100" y="52" width="6" height="23" fill="hsl(220 20% 40%)" />
          <rect x="115" y="58" width="6" height="17" fill="hsl(220 20% 40%)" />
        </>
      )}
      {shot === "track" && (
        <>
          <rect width="160" height="50" fill={`url(#sky-${seed})`} />
          <rect y="50" width="160" height="40" fill="hsl(20 15% 12%)" />
          <path d="M0 60 L160 50 L160 90 L0 80 Z" fill="hsl(20 25% 18%)" />
          <path d="M0 70 L160 60" stroke="hsl(40 80% 60% / 0.5)" strokeWidth="0.5" strokeDasharray="4 2" />
          <rect x="60" y="48" width="16" height="10" rx="2" fill="hsl(0 70% 45%)" />
          <rect x="62" y="50" width="12" height="3" fill="hsl(0 0% 80%)" />
          <circle cx="63" cy="59" r="2" fill="hsl(0 0% 8%)" />
          <circle cx="73" cy="59" r="2" fill="hsl(0 0% 8%)" />
        </>
      )}
      {shot === "interview" && (
        <>
          <rect width="160" height="90" fill="hsl(220 20% 14%)" />
          <rect x="0" y="55" width="160" height="35" fill="hsl(220 20% 8%)" />
          <ellipse cx="80" cy="40" rx="14" ry="16" fill="hsl(30 30% 35%)" />
          <ellipse cx="80" cy="32" rx="8" ry="9" fill="hsl(30 40% 55%)" />
          <rect x="68" y="55" width="24" height="35" fill="hsl(220 25% 22%)" />
          <circle cx="80" cy="70" r="2" fill="hsl(0 80% 50%)" />
        </>
      )}
      {shot === "aerial" && (
        <>
          <rect width="160" height="90" fill="hsl(200 30% 20%)" />
          <path d="M0 50 Q40 40 80 55 T160 50 L160 90 L0 90 Z" fill="hsl(140 20% 25%)" />
          <path d="M0 65 Q40 55 80 70 T160 65 L160 90 L0 90 Z" fill="hsl(140 15% 18%)" />
          <circle cx="120" cy="20" r="8" fill="hsl(60 30% 60% / 0.4)" />
          <rect x="40" y="60" width="3" height="2" fill="white" />
          <rect x="80" y="55" width="3" height="2" fill="white" />
          <rect x="110" y="62" width="3" height="2" fill="white" />
        </>
      )}
      {shot === "crowd" && (
        <>
          <rect width="160" height="60" fill={`url(#sky-${seed})`} />
          <rect y="60" width="160" height="30" fill="hsl(220 15% 10%)" />
          {Array.from({ length: 40 }).map((_, i) => {
            const x = (i * 4.5) % 160;
            const y = 50 + Math.sin(i * 1.7) * 4;
            return <circle key={i} cx={x} cy={y} r="2.5" fill={`hsl(${30 + (i * 13) % 60} 30% ${30 + (i % 3) * 8}%)`} />;
          })}
        </>
      )}
      {shot === "trophy" && (
        <>
          <rect width="160" height="90" fill={`url(#sky-${seed})`} />
          <path d="M70 25 L90 25 L88 50 L72 50 Z" fill="hsl(45 80% 55%)" />
          <rect x="74" y="50" width="12" height="6" fill="hsl(45 70% 45%)" />
          <rect x="70" y="56" width="20" height="4" fill="hsl(45 60% 35%)" />
          <path d="M65 35 Q60 30 65 25" fill="none" stroke="hsl(45 80% 55%)" strokeWidth="2" />
          <path d="M95 35 Q100 30 95 25" fill="none" stroke="hsl(45 80% 55%)" strokeWidth="2" />
        </>
      )}
    </svg>
  );
}

// Waveform — pseudorandom but deterministic
function Waveform({ seed = 1, color = "var(--accent)", className = "" }) {
  const bars = 60;
  const pts = React.useMemo(() => {
    return Array.from({ length: bars }).map((_, i) => {
      const x = i / bars;
      const n = Math.sin(i * 0.7 + seed) * 0.5 + Math.sin(i * 2.1 + seed * 1.3) * 0.3 + Math.sin(i * 4.3 + seed * 0.7) * 0.2;
      return Math.max(0.1, Math.min(1, 0.5 + n * 0.5));
    });
  }, [seed]);

  return (
    <svg viewBox="0 0 60 20" preserveAspectRatio="none" className={`waveform ${className}`}>
      {pts.map((p, i) => (
        <rect key={i} x={i} y={10 - p * 9} width="0.6" height={p * 18} fill={color} rx="0.3" />
      ))}
    </svg>
  );
}

// Live scrolling thumbnail strip - shows recent frames coming in
function LiveStrip({ seed = 1, count = 8 }) {
  const [tick, setTick] = React.useState(0);
  React.useEffect(() => {
    const i = setInterval(() => setTick(t => t + 1), 2000);
    return () => clearInterval(i);
  }, []);
  return (
    <div className="live-strip">
      {Array.from({ length: count }).map((_, i) => (
        <div
          key={`${tick}-${i}`}
          className="live-strip-cell"
          style={{ background: thumbGrad((seed + i + tick) % 11) }}
        >
          <FauxFrame seed={(seed + i + tick) % 6} />
        </div>
      ))}
      <div className="live-strip-now">
        <span className="live-pulse" />
        NOW
      </div>
    </div>
  );
}

// Sparkline
function Sparkline({ data, color = "var(--accent)", height = 28, fill = true }) {
  const max = Math.max(...data, 1);
  const min = Math.min(...data, 0);
  const range = max - min || 1;
  const w = 100;
  const pts = data.map((d, i) => {
    const x = (i / (data.length - 1)) * w;
    const y = height - ((d - min) / range) * height;
    return `${x},${y}`;
  }).join(" ");
  const area = `0,${height} ${pts} ${w},${height}`;
  return (
    <svg viewBox={`0 0 ${w} ${height}`} preserveAspectRatio="none" style={{ width: "100%", height, display: "block" }}>
      {fill && <polygon points={area} fill={color} opacity="0.15" />}
      <polyline points={pts} fill="none" stroke={color} strokeWidth="1.5" />
    </svg>
  );
}

// Animated audio meter
function AudioMeter({ level = 0.7, peak = 0.85, vertical = false }) {
  const segs = 20;
  return (
    <div className={`audio-meter ${vertical ? "v" : "h"}`}>
      {Array.from({ length: segs }).map((_, i) => {
        const v = i / segs;
        const on = v < level;
        const color = v < 0.6 ? "var(--success)" : v < 0.85 ? "var(--warning)" : "var(--danger)";
        return <div key={i} className="audio-seg" style={{ background: on ? color : "var(--bg-3)", opacity: on ? 1 : 0.4 }} />;
      })}
    </div>
  );
}

// Status dot with pulse
function StatusDot({ status }) {
  const map = {
    online: { color: "var(--success)", pulse: false },
    recording: { color: "var(--live)", pulse: true },
    armed: { color: "var(--accent)", pulse: false },
    idle: { color: "var(--text-4)", pulse: false },
    error: { color: "var(--danger)", pulse: true },
    offline: { color: "var(--text-4)", pulse: false },
    processing: { color: "var(--warning)", pulse: true },
    ready: { color: "var(--success)", pulse: false },
    live: { color: "var(--live)", pulse: true },
    queued: { color: "var(--text-3)", pulse: false },
    running: { color: "var(--accent)", pulse: true },
    done: { color: "var(--success)", pulse: false },
    failed: { color: "var(--danger)", pulse: false },
  };
  const s = map[status] || { color: "var(--text-3)" };
  return (
    <span className={`status-dot ${s.pulse ? "pulse" : ""}`} style={{ background: s.color, boxShadow: `0 0 0 3px ${s.color}30` }} />
  );
}

// Live-style ticking clock for elapsed times
function Elapsed({ seconds, live = false }) {
  const [t, setT] = React.useState(seconds);
  React.useEffect(() => {
    if (!live) return;
    const i = setInterval(() => setT(x => x + 1), 1000);
    return () => clearInterval(i);
  }, [live]);
  const h = Math.floor(t / 3600);
  const m = Math.floor((t % 3600) / 60);
  const s = t % 60;
  return <span className="mono">{String(h).padStart(2, "0")}:{String(m).padStart(2, "0")}:{String(s).padStart(2, "0")}</span>;
}

Object.assign(window, { AssetThumb, FauxFrame, Waveform, LiveStrip, Sparkline, AudioMeter, StatusDot, Elapsed });
