// Simple WebAudio helper — synthesizes drum hits and a short loop.
// No external samples needed.

const AudioKit = (() => {
  let ctx = null;
  const getCtx = () => {
    if (!ctx) ctx = new (window.AudioContext || window.webkitAudioContext)();
    if (ctx.state === 'suspended') ctx.resume();
    return ctx;
  };

  const kick = (t = 0) => {
    const c = getCtx(); const n = c.currentTime + t;
    const o = c.createOscillator(); const g = c.createGain();
    o.frequency.setValueAtTime(150, n);
    o.frequency.exponentialRampToValueAtTime(40, n + 0.18);
    g.gain.setValueAtTime(0.9, n);
    g.gain.exponentialRampToValueAtTime(0.001, n + 0.4);
    o.connect(g).connect(c.destination);
    o.start(n); o.stop(n + 0.4);
  };

  const snare = (t = 0) => {
    const c = getCtx(); const n = c.currentTime + t;
    const buf = c.createBuffer(1, c.sampleRate * 0.2, c.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 s = c.createBufferSource(); s.buffer = buf;
    const f = c.createBiquadFilter(); f.type = 'highpass'; f.frequency.value = 1500;
    const g = c.createGain(); g.gain.value = 0.5;
    s.connect(f).connect(g).connect(c.destination);
    s.start(n);
  };

  const hat = (t = 0, open = false) => {
    const c = getCtx(); const n = c.currentTime + t;
    const buf = c.createBuffer(1, c.sampleRate * (open ? 0.3 : 0.08), c.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, open ? 1 : 3);
    const s = c.createBufferSource(); s.buffer = buf;
    const f = c.createBiquadFilter(); f.type = 'highpass'; f.frequency.value = 6000;
    const g = c.createGain(); g.gain.value = 0.35;
    s.connect(f).connect(g).connect(c.destination);
    s.start(n);
  };

  const clap = (t = 0) => {
    const c = getCtx(); const n = c.currentTime + t;
    [0, 0.01, 0.025].forEach(offset => {
      const buf = c.createBuffer(1, c.sampleRate * 0.08, c.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, 3);
      const s = c.createBufferSource(); s.buffer = buf;
      const f = c.createBiquadFilter(); f.type = 'bandpass'; f.frequency.value = 1500;
      const g = c.createGain(); g.gain.value = 0.3;
      s.connect(f).connect(g).connect(c.destination);
      s.start(n + offset);
    });
  };

  const tone = (freq, t = 0, dur = 0.3, type = 'triangle', gain = 0.3) => {
    const c = getCtx(); const n = c.currentTime + t;
    const o = c.createOscillator(); const g = c.createGain();
    o.type = type;
    o.frequency.setValueAtTime(freq, n);
    g.gain.setValueAtTime(0, n);
    g.gain.linearRampToValueAtTime(gain, n + 0.01);
    g.gain.exponentialRampToValueAtTime(0.001, n + dur);
    o.connect(g).connect(c.destination);
    o.start(n); o.stop(n + dur + 0.02);
  };

  const PADS = {
    KICK:  { label: 'KICK',  fn: kick,  color: '#F23827' },
    SNR:   { label: 'SNARE', fn: snare, color: '#F5C518' },
    HH:    { label: 'HAT',   fn: (t) => hat(t, false), color: '#00B8D4' },
    OH:    { label: 'OPEN',  fn: (t) => hat(t, true), color: '#E5429C' },
    CLAP:  { label: 'CLAP',  fn: clap, color: '#2B6BF3' },
    C:     { label: 'C3',    fn: (t) => tone(130.81, t, 0.5, 'sawtooth'), color: '#3BA55C' },
    E:     { label: 'E3',    fn: (t) => tone(164.81, t, 0.5, 'sawtooth'), color: '#E8FF3A' },
    G:     { label: 'G3',    fn: (t) => tone(196.00, t, 0.5, 'sawtooth'), color: '#B14DFF' },
  };

  // --- Loop player ---
  let loopTimer = null; let loopStep = 0; let onStep = null;
  const LOOP = [
    // kick snare hat clap c e g
    // step 0..15
    { kick: 1, hat: 1 },                 // 0
    {},
    { hat: 1, c: 1 },                    // 2
    {},
    { snare: 1, hat: 1, e: 1 },          // 4
    {},
    { hat: 1 },                          // 6
    { g: 1 },
    { kick: 1, hat: 1 },                 // 8
    { kick: 1 },
    { hat: 1, c: 1 },                    // 10
    {},
    { snare: 1, clap: 1, hat: 1, e: 1 }, // 12
    {},
    { oh: 1 },                           // 14
    { g: 1 },
  ];

  const playLoop = (onStepCb) => {
    stopLoop();
    onStep = onStepCb || null;
    loopStep = 0;
    const bpm = 92;
    const stepDur = 60 / bpm / 4; // 16ths
    const tick = () => {
      const s = LOOP[loopStep % 16];
      if (s.kick) kick();
      if (s.snare) snare();
      if (s.hat) hat(0, false);
      if (s.oh) hat(0, true);
      if (s.clap) clap();
      if (s.c) tone(130.81, 0, 0.4, 'sawtooth', 0.15);
      if (s.e) tone(164.81, 0, 0.4, 'sawtooth', 0.15);
      if (s.g) tone(196.00, 0, 0.4, 'sawtooth', 0.15);
      if (onStep) onStep(loopStep % 16);
      loopStep++;
    };
    tick();
    loopTimer = setInterval(tick, stepDur * 1000);
  };

  const stopLoop = () => {
    if (loopTimer) { clearInterval(loopTimer); loopTimer = null; }
    if (onStep) onStep(-1);
  };

  return { PADS, playLoop, stopLoop, getCtx };
})();

window.AudioKit = AudioKit;
