/**
 * Star Wars Hearthstone - Web Audio sound effects
 */
(function (global) {
  'use strict';

  let ctx = null;

  function init() {
    if (ctx) {
      if (ctx.state === 'suspended') ctx.resume().catch(function () {});
      return ctx;
    }
    try {
      ctx = new (global.AudioContext || global.webkitAudioContext)();
    } catch (e) {
      return null;
    }
    return ctx;
  }

  function beep(freq, duration, type, vol) {
    const c = init();
    if (!c) return;
    const osc = c.createOscillator();
    const gain = c.createGain();
    osc.connect(gain);
    gain.connect(c.destination);
    osc.frequency.value = freq;
    osc.type = type || 'sine';
    gain.gain.setValueAtTime(vol ?? 0.15, c.currentTime);
    gain.gain.exponentialRampToValueAtTime(0.001, c.currentTime + duration);
    osc.start(c.currentTime);
    osc.stop(c.currentTime + duration);
  }

  function playCard() {
    const c = init();
    if (!c) return;
    const osc = c.createOscillator();
    const gain = c.createGain();
    osc.connect(gain);
    gain.connect(c.destination);
    osc.type = 'sine';
    osc.frequency.setValueAtTime(523, c.currentTime);
    osc.frequency.exponentialRampToValueAtTime(784, c.currentTime + 0.08);
    gain.gain.setValueAtTime(0.12, c.currentTime);
    gain.gain.exponentialRampToValueAtTime(0.001, c.currentTime + 0.15);
    osc.start(c.currentTime);
    osc.stop(c.currentTime + 0.15);
  }

  function attack() {
    const c = init();
    if (!c) return;
    const osc = c.createOscillator();
    const gain = c.createGain();
    osc.connect(gain);
    gain.connect(c.destination);
    osc.type = 'square';
    osc.frequency.value = 180;
    gain.gain.setValueAtTime(0.08, c.currentTime);
    gain.gain.exponentialRampToValueAtTime(0.001, c.currentTime + 0.12);
    osc.start(c.currentTime);
    osc.stop(c.currentTime + 0.12);
  }

  function endTurn() {
    beep(392, 0.06, 'sine', 0.1);
    setTimeout(() => beep(523, 0.08, 'sine', 0.08), 80);
  }

  function victory() {
    const notes = [523, 659, 784, 1047];
    notes.forEach((f, i) => {
      setTimeout(() => beep(f, 0.25, 'sine', 0.12), i * 120);
    });
  }

  function defeat() {
    const notes = [392, 349, 294];
    notes.forEach((f, i) => {
      setTimeout(() => beep(f, 0.2, 'sine', 0.1), i * 150);
    });
  }

  function drawCard() {
    beep(440, 0.06, 'sine', 0.08);
  }

  function hoverCard() {
    beep(600, 0.04, 'sine', 0.05);
  }

  function timerWarning() {
    const c = init();
    if (!c) return;
    const osc = c.createOscillator();
    const gain = c.createGain();
    osc.connect(gain);
    gain.connect(c.destination);
    osc.type = 'sawtooth';
    osc.frequency.setValueAtTime(220, c.currentTime);
    osc.frequency.exponentialRampToValueAtTime(440, c.currentTime + 0.15);
    gain.gain.setValueAtTime(0.08, c.currentTime);
    gain.gain.exponentialRampToValueAtTime(0.001, c.currentTime + 0.2);
    osc.start(c.currentTime);
    osc.stop(c.currentTime + 0.2);
  }

  function timerEnd() {
    const notes = [262, 330, 392];
    notes.forEach((f, i) => {
      setTimeout(() => beep(f, 0.1, 'square', 0.08), i * 80);
    });
  }

  function forge() {
    const c = init();
    if (!c) return;
    const notes = [392, 523, 659, 784];
    notes.forEach((f, i) => {
      setTimeout(() => beep(f, 0.2, 'sine', 0.12), i * 90);
    });
  }

  global.Sounds = {
    init,
    playCard,
    attack,
    endTurn,
    victory,
    defeat,
    drawCard,
    hoverCard,
    timerWarning,
    timerEnd,
    forge,
  };
})(typeof window !== 'undefined' ? window : globalThis);
