/* ============================================================
   audio.js - Tiny WebAudio beep engine reproducing the
   Game & Watch piezo buzzer feel. No external assets.
   ============================================================ */
(function (ST) {
  "use strict";

  var ctx = null;
  var masterGain = null;
  var muted = false;

  function ensureCtx() {
    if (ctx) return ctx;
    try {
      var AC = window.AudioContext || window.webkitAudioContext;
      if (!AC) { console.warn("[audio] WebAudio not supported; running silent."); return null; }
      ctx = new AC();
      masterGain = ctx.createGain();
      masterGain.gain.value = 0.25;
      masterGain.connect(ctx.destination);
    } catch (e) {
      console.error("[audio] Failed to create AudioContext:", e);
      ctx = null;
    }
    return ctx;
  }

  /* A short square-wave blip — the characteristic G&W tone. */
  function blip(freq, dur, type, vol) {
    if (muted) return;
    var c = ensureCtx();
    if (!c) return;
    try {
      if (c.state === "suspended") c.resume();
      var t = c.currentTime;
      var osc = c.createOscillator();
      var g = c.createGain();
      osc.type = type || "square";
      osc.frequency.setValueAtTime(freq, t);
      g.gain.setValueAtTime(0.0001, t);
      g.gain.exponentialRampToValueAtTime(vol || 0.9, t + 0.004);
      g.gain.exponentialRampToValueAtTime(0.0001, t + dur);
      osc.connect(g);
      g.connect(masterGain);
      osc.start(t);
      osc.stop(t + dur + 0.02);
    } catch (e) {
      console.warn("[audio] blip failed:", e);
    }
  }

  var Sound = {
    /* Unlock audio on first user gesture (mobile autoplay policy). */
    unlock: function () {
      var c = ensureCtx();
      if (c && c.state === "suspended") {
        c.resume().catch(function (e) { console.warn("[audio] resume failed", e); });
      }
    },
    setMuted: function (m) { muted = !!m; },
    isMuted: function () { return muted; },

    hit:    function () { blip(880, 0.05, "square", 0.9); },        // Snoopy returns a ball
    serve:  function () { blip(440, 0.045, "square", 0.6); },       // Charlie serves
    lucy:   function () { blip(1180, 0.05, "square", 0.8); setTimeout(function(){ blip(1480,0.05,"square",0.7);}, 55); },
    miss:   function () { blip(200, 0.16, "sawtooth", 0.8); },      // missed ball
    point:  function () { blip(1320, 0.04, "square", 0.5); },
    gameover: function () {
      var seq = [523, 415, 349, 262];
      seq.forEach(function (f, i) { setTimeout(function () { blip(f, 0.22, "square", 0.8); }, i * 200); });
    },
    start:  function () { blip(660, 0.08, "square", 0.6); setTimeout(function(){ blip(990,0.1,"square",0.6);}, 90); },
    ui:     function () { blip(1000, 0.03, "square", 0.35); },
    bonus:  function () { // chance-time chime
      [784, 988, 1319].forEach(function (f, i) { setTimeout(function () { blip(f, 0.09, "square", 0.6); }, i * 90); });
    }
  };

  ST.Sound = Sound;
})(window.ST = window.ST || {});
