/* ============================================================
   斗地主 · 音效引擎（Web Audio 合成，无需音频文件）
   window.SFX.play(name) / SFX.setEnabled({sfx,music}) / SFX.toggleMusic()
   ============================================================ */
(function () {
  const AC = window.AudioContext || window.webkitAudioContext;
  let ctx = null, master = null, musicGain = null;
  let enabled = { sfx: true, music: true };
  let musicTimer = null;

  function ensure() {
    if (!ctx) {
      ctx = new AC();
      master = ctx.createGain(); master.gain.value = 0.9; master.connect(ctx.destination);
      musicGain = ctx.createGain(); musicGain.gain.value = 0.0; musicGain.connect(master);
    }
    if (ctx.state === 'suspended') ctx.resume();
    return ctx;
  }

  function blip({ freq = 440, to = null, dur = 0.12, type = 'sine', vol = 0.22, attack = 0.004, when = 0 }) {
    ensure();
    const t0 = ctx.currentTime + when;
    const osc = ctx.createOscillator();
    const g = ctx.createGain();
    osc.type = type; osc.frequency.setValueAtTime(freq, t0);
    if (to) osc.frequency.exponentialRampToValueAtTime(Math.max(1, to), t0 + dur);
    g.gain.setValueAtTime(0.0001, t0);
    g.gain.exponentialRampToValueAtTime(vol, t0 + attack);
    g.gain.exponentialRampToValueAtTime(0.0001, t0 + dur);
    osc.connect(g); g.connect(master);
    osc.start(t0); osc.stop(t0 + dur + 0.02);
  }
  function noise({ dur = 0.18, vol = 0.3, when = 0, hp = 800 }) {
    ensure();
    const t0 = ctx.currentTime + when;
    const n = Math.floor(ctx.sampleRate * dur);
    const buf = ctx.createBuffer(1, n, ctx.sampleRate);
    const d = buf.getChannelData(0);
    for (let i = 0; i < n; i++) d[i] = (Math.random() * 2 - 1) * (1 - i / n);
    const src = ctx.createBufferSource(); src.buffer = buf;
    const f = ctx.createBiquadFilter(); f.type = 'highpass'; f.frequency.value = hp;
    const g = ctx.createGain(); g.gain.setValueAtTime(vol, t0); g.gain.exponentialRampToValueAtTime(0.001, t0 + dur);
    src.connect(f); f.connect(g); g.connect(master);
    src.start(t0); src.stop(t0 + dur);
  }
  function chord(freqs, opts = {}) { freqs.forEach((f, i) => blip({ freq: f, when: (opts.stagger || 0) * i, ...opts, freq: f })); }

  const SOUNDS = {
    click:  () => blip({ freq: 520, to: 360, dur: 0.07, type: 'triangle', vol: 0.14 }),
    select: () => blip({ freq: 680, dur: 0.05, type: 'sine', vol: 0.12 }),
    deal:   () => { for (let i = 0; i < 5; i++) noise({ dur: 0.05, vol: 0.12, when: i * 0.05, hp: 1800 }); },
    play:   () => { blip({ freq: 430, to: 600, dur: 0.1, type: 'triangle', vol: 0.2 }); noise({ dur: 0.06, vol: 0.1, hp: 1500 }); },
    pass:   () => blip({ freq: 300, to: 220, dur: 0.14, type: 'sine', vol: 0.16 }),
    invalid:() => { blip({ freq: 200, to: 140, dur: 0.16, type: 'sawtooth', vol: 0.16 }); },
    bid:    () => chord([523, 659], { dur: 0.16, type: 'triangle', vol: 0.18, stagger: 0.05 }),
    landlord:() => chord([523, 659, 784, 1047], { dur: 0.5, type: 'triangle', vol: 0.16, stagger: 0.07 }),
    bomb:   () => { noise({ dur: 0.4, vol: 0.45, hp: 200 }); blip({ freq: 160, to: 50, dur: 0.4, type: 'sawtooth', vol: 0.3 }); },
    rocket: () => { blip({ freq: 300, to: 2200, dur: 0.5, type: 'sawtooth', vol: 0.25 }); noise({ dur: 0.5, vol: 0.3, when: 0.1, hp: 600 }); },
    win:    () => chord([523, 659, 784, 1047, 1319], { dur: 0.6, type: 'triangle', vol: 0.18, stagger: 0.09 }),
    lose:   () => chord([440, 370, 294, 220], { dur: 0.6, type: 'sine', vol: 0.16, stagger: 0.1 }),
    coin:   () => { blip({ freq: 1200, to: 1600, dur: 0.08, type: 'square', vol: 0.12 }); blip({ freq: 1600, to: 2000, dur: 0.08, type: 'square', vol: 0.1, when: 0.08 }); },
    tick:   () => blip({ freq: 880, dur: 0.04, type: 'square', vol: 0.08 }),
  };

  /* 轻量背景音乐：缓慢琶音 */
  const SCALE = [261.6, 329.6, 392.0, 523.3, 392.0, 329.6];
  let mi = 0;
  function musicStep() {
    if (!enabled.music) return;
    ensure();
    const f = SCALE[mi % SCALE.length]; mi++;
    const t0 = ctx.currentTime;
    const osc = ctx.createOscillator(); const g = ctx.createGain();
    osc.type = 'sine'; osc.frequency.value = f;
    g.gain.setValueAtTime(0.0001, t0);
    g.gain.exponentialRampToValueAtTime(0.05, t0 + 0.3);
    g.gain.exponentialRampToValueAtTime(0.0001, t0 + 1.6);
    osc.connect(g); g.connect(musicGain);
    osc.start(t0); osc.stop(t0 + 1.7);
  }
  function startMusic() { if (musicTimer) return; ensure(); musicGain.gain.linearRampToValueAtTime(0.6, ctx.currentTime + 1); musicTimer = setInterval(musicStep, 760); }
  function stopMusic() { if (musicTimer) { clearInterval(musicTimer); musicTimer = null; } if (musicGain && ctx) musicGain.gain.linearRampToValueAtTime(0, ctx.currentTime + 0.4); }

  window.SFX = {
    play(name) { if (!enabled.sfx) return; try { (SOUNDS[name] || SOUNDS.click)(); } catch (e) {} },
    setEnabled(s) {
      enabled = { ...enabled, ...s };
      if (enabled.music) startMusic(); else stopMusic();
    },
    unlock() { ensure(); },
    get enabled() { return { ...enabled }; },
  };
})();
