/**
 * The envelope of a sample, drawn from the 128 numbers `kitindex.py` precomputed.
 *
 * Deliberately not wavesurfer. A kit page shows a hundred-odd rows; a hundred
 * wavesurfer instances means a hundred fetches and a hundred decodes to draw
 * something 200 px wide, so the list would take a minute to appear and the audio
 * thread would be fighting the render. The index already carries the envelope, so a
 * row costs one <svg> and no network at all — audio is fetched only when a sample is
 * actually played. (Same instinct as the tide-table's ship-the-index rule.)
 *
 * The playhead is a CSS transform driven by the deck's own clock, so it cannot drift
 * away from what you are hearing even when React is busy.
 */
import { memo } from 'react'

type Props = {
  env: number[]
  color: string
  /** 0..1, or null when this sample is not sounding */
  head?: number | null
  /** bar boundaries to rule, as fractions of the width */
  bars?: number
  height?: number
  className?: string
}

export const Waveform = memo(function Waveform(
  { env, color, head = null, bars = 0, height = 34, className }: Props,
) {
  const n = env.length || 1
  const mid = height / 2
  // one polygon, mirrored: cheaper than 128 rects and it reads as a waveform rather
  // than as a bar chart, which matters when you are scanning for where the hit is
  const top = env.map((v, i) => `${(i / n) * 100},${mid - (v / 100) * (mid - 1)}`)
  const bot = env.map((v, i) => `${(i / n) * 100},${mid + (v / 100) * (mid - 1)}`).reverse()
  return (
    <svg className={className} viewBox={`0 0 100 ${height}`} height={height}
         preserveAspectRatio="none" style={{ width: '100%', display: 'block' }}>
      <polygon points={[...top, ...bot].join(' ')} fill={color} fillOpacity={0.75} />
      {bars > 1 && Array.from({ length: bars - 1 }, (_, i) => (
        <line key={i} x1={((i + 1) / bars) * 100} x2={((i + 1) / bars) * 100}
              y1={0} y2={height} stroke="var(--hairline)" strokeWidth={0.3} />
      ))}
      {head != null && (
        <line x1={head * 100} x2={head * 100} y1={0} y2={height}
              stroke="var(--ink)" strokeWidth={0.5} />
      )}
    </svg>
  )
})
