// ── Morse code engine ──────────────────────────────────────────────────────
// SOS: · · · — — — · · ·
const MORSE_SEQ = [
  [1,true],[1,false],[1,true],[1,false],[1,true],   // S: ...
  [3,false],
  [3,true],[1,false],[3,true],[1,false],[3,true],   // O: ---
  [3,false],
  [1,true],[1,false],[1,true],[1,false],[1,true],   // S: ...
  [8,false],                                        // word gap
];
const UNIT = 180; // ms per unit

function useMorse(active) {
  const [lit, setLit] = React.useState(false);
  const timer = React.useRef(null);
  const idx   = React.useRef(0);

  React.useEffect(() => {
    if (!active) { setLit(false); return; }
    function tick() {
      const [dur, on] = MORSE_SEQ[idx.current % MORSE_SEQ.length];
      setLit(on);
      idx.current++;
      timer.current = setTimeout(tick, dur * UNIT);
    }
    tick();
    return () => clearTimeout(timer.current);
  }, [active]);

  return lit;
}

// ── Meter ──────────────────────────────────────────────────────────────────
const MAX_ALT   = 2000;
const TICK_ALTS = [0, 400, 800, 1200, 1600, 2000];
const METER_H   = 500;
const AXIS_X    = 48;

function AltitudeMeter({ coffee, visible, animSpeed }) {
  const [progress, setProgress]     = React.useState(0);
  const [displayAlt, setDisplayAlt] = React.useState(0);
  const raf = React.useRef(null);

  const duration = animSpeed === 'slow' ? 3200 : animSpeed === 'fast' ? 900 : 2000;
  const targetPct = coffee.altitude / MAX_ALT;
  const fillPx    = progress * targetPct * METER_H; // current height in px from bottom
  const dotY      = METER_H - fillPx;               // SVG y-coordinate of the dot

  const morseActive = visible && progress > 0.97;
  const dotLit = useMorse(morseActive);

  React.useEffect(() => {
    setProgress(0);
    setDisplayAlt(0);
    if (raf.current) cancelAnimationFrame(raf.current);
    if (!visible) return;

    const t = setTimeout(() => {
      let start = null;
      function tick(ts) {
        if (!start) start = ts;
        const p     = Math.min((ts - start) / duration, 1);
        const eased = 1 - Math.pow(1 - p, 4);
        setProgress(eased);
        setDisplayAlt(Math.round(eased * coffee.altitude));
        if (p < 1) raf.current = requestAnimationFrame(tick);
      }
      raf.current = requestAnimationFrame(tick);
    }, 280);

    return () => { clearTimeout(t); if (raf.current) cancelAnimationFrame(raf.current); };
  }, [coffee.id, visible, animSpeed]);

  // ── Generate contour lines ──────────────────────────────────────────────
  // ~36 horizontal lines, each with a seed-based length variation
  const LINE_SPACING = 14;
  const lines = [];
  for (let i = 1; i * LINE_SPACING <= METER_H + LINE_SPACING; i++) {
    const bottomPx = i * LINE_SPACING;
    const y        = METER_H - bottomPx;
    if (y < -10) break;
    // Pseudo-random length using index as seed
    const seed = ((i * 97 + 31) % 100) / 100;
    const len  = 70 + seed * 55; // 70–125 px
    const isLit = bottomPx <= fillPx + 1;
    lines.push({ y, len, isLit, seed, idx: i });
  }

  // Is the topmost lit line (the "surface")
  const topLitLine = lines.filter(l => l.isLit).slice(-1)[0];

  return (
    <div style={{
      width: '100%', height: '100%',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      position: 'relative', overflow: 'hidden',
    }}>

      {/* Ghost altitude numeral */}
      <div aria-hidden="true" style={{
        position: 'absolute', bottom: '5%', left: '50%',
        transform: 'translateX(-50%)',
        fontFamily: "'Montserrat', sans-serif",
        fontSize: 'clamp(68px, 8.5vw, 128px)',
        fontWeight: 900,
        color: 'rgba(255,255,255,0.04)',
        lineHeight: 1, whiteSpace: 'nowrap',
        userSelect: 'none', pointerEvents: 'none',
        letterSpacing: '-0.02em',
      }}>
        {coffee.altitude.toLocaleString()}
      </div>

      {/* SVG canvas */}
      <div style={{ position: 'relative', flexShrink: 0 }}>
        <svg
          width="260" height={METER_H}
          style={{ overflow: 'visible', display: 'block' }}
        >
          {/* ── Vertical axis ── */}
          <line
            x1={AXIS_X} y1={0}
            x2={AXIS_X} y2={METER_H}
            stroke="rgba(255,255,255,0.12)"
            strokeWidth="1"
          />

          {/* ── Tick marks + altitude labels ── */}
          {TICK_ALTS.map(alt => {
            const ty    = METER_H - (alt / MAX_ALT) * METER_H;
            const isLit = (alt / MAX_ALT) * METER_H <= fillPx + 2;
            return (
              <g key={alt}>
                <line
                  x1={AXIS_X - 8} y1={ty}
                  x2={AXIS_X}     y2={ty}
                  stroke={isLit ? 'rgba(255,255,255,0.55)' : 'rgba(255,255,255,0.15)'}
                  strokeWidth="1"
                />
                {/* Extended tick across the panel */}
                <line
                  x1={AXIS_X} y1={ty}
                  x2={200}    y2={ty}
                  stroke={isLit ? 'rgba(255,255,255,0.06)' : 'rgba(255,255,255,0.03)'}
                  strokeWidth="0.5"
                  strokeDasharray="2 4"
                />
                <text
                  x={AXIS_X - 12} y={ty + 4}
                  textAnchor="end"
                  fontFamily="'Montserrat', sans-serif"
                  fontSize="8"
                  letterSpacing="0.08em"
                  fill={isLit ? 'rgba(255,255,255,0.5)' : 'rgba(255,255,255,0.15)'}
                >
                  {alt === 0 ? 'S.L.' : alt}
                </text>
              </g>
            );
          })}

          {/* ── Contour lines ── */}
          {lines.map(({ y, len, isLit, seed, idx: li }) => {
            const opacity = isLit
              ? 0.5 + seed * 0.45   // lit: 0.5–0.95
              : 0.04 + seed * 0.04; // dim: 0.04–0.08
            const sw = isLit ? (seed > 0.7 ? 1.2 : 0.7) : 0.5;
            return (
              <line
                key={li}
                x1={AXIS_X} y1={y}
                x2={AXIS_X + len} y2={y}
                stroke="#ffffff"
                strokeWidth={sw}
                opacity={opacity}
              />
            );
          })}

          {/* ── Surface line + dot ── */}
          {fillPx > 8 && (
            <g>
              {/* Horizontal dashed reach line to dot */}
              <line
                x1={AXIS_X} y1={dotY}
                x2={175}    y2={dotY}
                stroke="rgba(255,255,255,0.35)"
                strokeWidth="0.8"
                strokeDasharray="4 3"
              />

              {/* Outer halo (when lit) */}
              {dotLit && (
                <circle
                  cx={180} cy={dotY} r={11}
                  fill="none"
                  stroke="rgba(255,255,255,0.15)"
                  strokeWidth="0.8"
                />
              )}

              {/* Mid ring */}
              <circle
                cx={180} cy={dotY}
                r={dotLit ? 6.5 : 4}
                fill="none"
                stroke={dotLit ? 'rgba(255,255,255,0.5)' : 'rgba(255,255,255,0.2)'}
                strokeWidth="0.8"
              />

              {/* Core dot */}
              <circle
                cx={180} cy={dotY}
                r={dotLit ? 4 : 2.5}
                fill={dotLit ? '#ffffff' : 'rgba(255,255,255,0.4)'}
              />
            </g>
          )}
        </svg>

        {/* Altitude counter — tracks dot Y position */}
        <div style={{
          position: 'absolute',
          left: 200,
          top: Math.max(4, dotY - 22),
          pointerEvents: 'none',
          paddingLeft: 16,
          borderLeft: `1px solid ${fillPx > 8 ? 'rgba(255,255,255,0.2)' : 'transparent'}`,
          minWidth: 90,
        }}>
          <div style={{
            fontFamily: "'Montserrat', sans-serif",
            fontSize: 32, fontWeight: 900,
            color: '#ffffff', lineHeight: 1,
            opacity: fillPx > 8 ? 1 : 0,
          }}>
            {displayAlt.toLocaleString()}
          </div>
          <div style={{
            fontFamily: "'Montserrat', sans-serif",
            fontSize: 12, letterSpacing: '0.2em',
            color: 'rgba(255,255,255,0.38)',
            marginTop: 5,
            opacity: fillPx > 8 ? 1 : 0,
          }}>
            M.A.S.L.
          </div>
          {/* Morse signal indicator */}
          {morseActive && (
            <div style={{
              marginTop: 10,
              display: 'flex', gap: 3, alignItems: 'center',
            }}>
              {[0,1,2].map(i => (
                <div key={i} style={{
                  width: i === 1 ? 10 : 4,
                  height: 2,
                  background: dotLit ? 'rgba(255,255,255,0.7)' : 'rgba(255,255,255,0.15)',
                  transition: 'background 0.06s',
                }} />
              ))}
            </div>
          )}
        </div>
      </div>

      {/* Label */}
      <div style={{
        position: 'absolute', bottom: '4%', left: '50%',
        transform: 'translateX(-50%)',
        fontFamily: "'Montserrat', sans-serif",
        fontSize: 12, letterSpacing: '0.35em',
        color: 'rgba(255,255,255,0.2)', whiteSpace: 'nowrap',
      }}>
        GROWING ALTITUDE
      </div>
    </div>
  );
}

Object.assign(window, { AltitudeMeter });
