// Easter eggs, audio, animation helpers for Rövhattens Åkeri.
// Loaded before sections + app.

// ---- Web Audio honk ---------------------------------------------------------
let _audioCtx = null;
function audioCtx() {
  if (!_audioCtx) {
    const AC = window.AudioContext || window.webkitAudioContext;
    if (AC) _audioCtx = new AC();
  }
  return _audioCtx;
}

function playTut(pattern) {
  const ac = audioCtx();
  if (!ac) return;
  if (ac.state === 'suspended') ac.resume();
  // Two-tone diesel air-horn: 311 Hz (Eb) → 415 Hz (Ab) major-third blast,
  // with detuned saws + sub + 2nd harmonic + lowpass to add body and warmth.
  const seq = pattern || [[311, .28], [415, .55]];
  let t = ac.currentTime + 0.01;

  // Master chain: lowpass → soft compressor → out
  const filter = ac.createBiquadFilter();
  filter.type = 'lowpass';
  filter.frequency.value = 1500;
  filter.Q.value = 0.6;
  const comp = ac.createDynamicsCompressor();
  comp.threshold.value = -18;
  comp.knee.value = 8;
  comp.ratio.value = 4;
  comp.attack.value = 0.003;
  comp.release.value = 0.15;
  const master = ac.createGain();
  master.gain.value = 0.55;
  filter.connect(comp).connect(master).connect(ac.destination);

  seq.forEach(([f, dur]) => {
    const start = t;
    const end = start + dur;

    // Per-tone envelope: quick attack, full sustain, exponential tail
    const env = ac.createGain();
    env.gain.setValueAtTime(0.0001, start);
    env.gain.exponentialRampToValueAtTime(0.55, start + 0.025);   // bright attack
    env.gain.setValueAtTime(0.55, end - 0.10);
    env.gain.exponentialRampToValueAtTime(0.0001, end);            // smooth release
    env.connect(filter);

    // 3 detuned sawtooth voices = chorus-y "horn body" (the meat)
    [-9, 0, 9].forEach((detune) => {
      const o = ac.createOscillator();
      o.type = 'sawtooth';
      o.detune.value = detune;
      o.frequency.setValueAtTime(f, start);
      o.frequency.exponentialRampToValueAtTime(f * 0.92, end);     // diesel droop
      const g = ac.createGain();
      g.gain.value = 0.32;
      o.connect(g).connect(env);
      o.start(start); o.stop(end + 0.02);
    });

    // Sub-octave triangle for low-end weight
    const sub = ac.createOscillator();
    sub.type = 'triangle';
    sub.frequency.setValueAtTime(f / 2, start);
    sub.frequency.exponentialRampToValueAtTime(f * 0.46, end);
    const subG = ac.createGain();
    subG.gain.value = 0.45;
    sub.connect(subG).connect(env);
    sub.start(start); sub.stop(end + 0.02);

    // 2nd harmonic square for "brassy" top edge
    const har = ac.createOscillator();
    har.type = 'square';
    har.frequency.setValueAtTime(f * 2, start);
    har.frequency.exponentialRampToValueAtTime(f * 1.84, end);
    const harG = ac.createGain();
    harG.gain.value = 0.08;
    har.connect(harG).connect(env);
    har.start(start); har.stop(end + 0.02);

    t = end + 0.025;
  });
}

function playStrike() {
  const ac = audioCtx();
  if (!ac) return;
  if (ac.state === 'suspended') ac.resume();
  // crash via noise burst
  const buf = ac.createBuffer(1, ac.sampleRate * 0.6, ac.sampleRate);
  const d = buf.getChannelData(0);
  for (let i = 0; i < d.length; i++) {
    d[i] = (Math.random() * 2 - 1) * Math.pow(1 - i / d.length, 2);
  }
  const src = ac.createBufferSource();
  src.buffer = buf;
  const g = ac.createGain();
  g.gain.value = 0.3;
  const f = ac.createBiquadFilter();
  f.type = 'bandpass';
  f.frequency.value = 2200;
  src.connect(f).connect(g).connect(ac.destination);
  src.start();
}

// ---- Visual effects --------------------------------------------------------
function spawnHonk(text, x, y) {
  const el = document.createElement('div');
  el.className = 'honk-bubble';
  el.textContent = text;
  el.style.left = (x || (window.innerWidth / 2)) + 'px';
  el.style.top = (y || (window.innerHeight * 0.4)) + 'px';
  document.body.appendChild(el);
  setTimeout(() => el.remove(), 1000);
}

function spawnConfetti(count) {
  const colors = ['#d83a2a', '#f0c419', '#1a1410', '#fbf3df', '#ee6c2c', '#2a5a3a'];
  for (let i = 0; i < (count || 80); i++) {
    const el = document.createElement('div');
    el.className = 'confetti';
    el.style.left = Math.random() * 100 + 'vw';
    el.style.top = '-20px';
    el.style.background = colors[i % colors.length];
    el.style.animationDelay = (Math.random() * 0.6) + 's';
    el.style.animationDuration = (1.8 + Math.random() * 1.2) + 's';
    el.style.transform = 'rotate(' + (Math.random() * 360) + 'deg)';
    document.body.appendChild(el);
    setTimeout(() => el.remove(), 3200);
  }
}

function spawnTumbleweed() {
  const el = document.createElement('div');
  el.className = 'tumbleweed';
  el.innerHTML = `
    <svg viewBox="0 0 100 100">
      <g fill="none" stroke="#8a5a2a" stroke-width="2" stroke-linecap="round">
        <circle cx="50" cy="50" r="34"/>
        <path d="M16 50 Q30 30 50 30 T84 50"/>
        <path d="M16 50 Q30 70 50 70 T84 50"/>
        <path d="M50 16 Q35 35 35 50 T50 84"/>
        <path d="M50 16 Q65 35 65 50 T50 84"/>
        <path d="M24 28 L76 72 M76 28 L24 72"/>
      </g>
    </svg>`;
  document.body.appendChild(el);
  setTimeout(() => el.remove(), 8200);
}

function spawnBowling() {
  const wrap = document.createElement('div');
  wrap.className = 'bowling';
  wrap.innerHTML = `
    <div class="pin">🎳</div>
    <div class="ball">⚫</div>
    <div class="strike-text">STRIKE!</div>
  `;
  document.body.appendChild(wrap);
  setTimeout(playStrike, 850);
  setTimeout(() => wrap.remove(), 1700);
}

// ---- Background song (one-shot, user-gesture-aware) -----------------------
// Drop the mp3 at: assets/on-the-road-again.mp3
let _songAudio = null;
let _songCleanup = null;

function startSong(src, opts = {}) {
  if (_songCleanup) _songCleanup();
  const audio = new Audio(src);
  audio.loop = !!opts.loop;
  audio.volume = opts.volume == null ? 0.55 : opts.volume;
  audio.preload = 'auto';
  _songAudio = audio;

  const startAt = opts.startAt || 0;
  const seekToStart = () => { try { audio.currentTime = startAt; } catch (e) {} };
  if (startAt > 0) {
    seekToStart();
    audio.addEventListener('loadedmetadata', seekToStart, { once: true });
  }

  let btn = null;
  const updateBtnLabel = () => {
    if (!btn) return;
    if (audio.paused || audio.ended) {
      btn.textContent = '🔊 SPELA IGEN';
      btn.title = 'Sätt igång Teds låt igen';
    } else {
      btn.textContent = '🔇 TYST NU TACK';
      btn.title = 'Pausa Teds låt';
    }
  };
  const ensureBtn = () => {
    if (btn) { updateBtnLabel(); return; }
    btn = document.createElement('button');
    btn.className = 'song-mute-btn';
    btn.onclick = () => {
      if (audio.paused || audio.ended) {
        if (audio.ended) seekToStart();
        audio.play().catch(() => {});
      } else {
        audio.pause();
      }
    };
    document.body.appendChild(btn);
    updateBtnLabel();
  };
  const removeBtn = () => { if (btn) { btn.remove(); btn = null; } };

  audio.addEventListener('play', ensureBtn);
  audio.addEventListener('pause', updateBtnLabel);
  audio.addEventListener('ended', removeBtn);

  audio.play().catch(() => {
    const events = ['click', 'touchstart', 'keydown', 'scroll', 'wheel'];
    const onGesture = () => {
      events.forEach(e => window.removeEventListener(e, onGesture));
      audio.play().catch(() => {});
    };
    events.forEach(e =>
      window.addEventListener(e, onGesture, { once: true, passive: true })
    );
  });

  _songCleanup = () => {
    audio.pause();
    removeBtn();
    _songAudio = null;
  };
  return _songCleanup;
}

window.fx = {
  tut: () => { playTut(); spawnHonk('TUUUUT! 🚛💨'); },
  honkSilent: (txt, x, y) => spawnHonk(txt || 'TUT!', x, y),
  confetti: spawnConfetti,
  tumbleweed: spawnTumbleweed,
  bowling: () => { spawnBowling(); },
  playTut,
  startSong,
};
