// Looping WebAudio ringtones. Two patterns:
//   - outgoing: long calling tone, 3s cycle
//   - incoming: classic "ring ring" double beep, 2s cycle

type Pattern = 'outgoing' | 'incoming';

class Ringtone {
  private ctx: AudioContext | null = null;
  private interval: number | null = null;
  private pattern: Pattern | null = null;

  start(pattern: Pattern): void {
    if (this.pattern === pattern) return; // already playing this pattern
    this.stop();
    const AudioCtx =
      window.AudioContext ??
      (window as unknown as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;
    if (!AudioCtx) return;
    this.ctx = new AudioCtx();
    this.pattern = pattern;

    const play = pattern === 'outgoing' ? this.playOutgoing : this.playIncoming;
    play.call(this);
    this.interval = window.setInterval(
      () => play.call(this),
      pattern === 'outgoing' ? 3000 : 2000,
    );
  }

  stop(): void {
    if (this.interval !== null) {
      window.clearInterval(this.interval);
      this.interval = null;
    }
    if (this.ctx) {
      void this.ctx.close().catch(() => {
        /* ignore */
      });
      this.ctx = null;
    }
    this.pattern = null;
  }

  private beep(freq: number, durationSec: number, delaySec: number, gain = 0.18): void {
    const ctx = this.ctx;
    if (!ctx) return;
    const osc = ctx.createOscillator();
    const g = ctx.createGain();
    osc.type = 'sine';
    osc.frequency.value = freq;
    osc.connect(g);
    g.connect(ctx.destination);
    const t0 = ctx.currentTime + delaySec;
    g.gain.setValueAtTime(0, t0);
    g.gain.linearRampToValueAtTime(gain, t0 + 0.02);
    g.gain.exponentialRampToValueAtTime(0.001, t0 + durationSec);
    osc.start(t0);
    osc.stop(t0 + durationSec + 0.02);
  }

  private playOutgoing(): void {
    // Soft calling tone — single warm note.
    this.beep(440, 0.4, 0, 0.14);
    this.beep(440, 0.4, 0.6, 0.14);
  }

  private playIncoming(): void {
    // Classic double-ring "ring ring".
    this.beep(880, 0.18, 0, 0.22);
    this.beep(660, 0.18, 0.22, 0.22);
    this.beep(880, 0.18, 0.6, 0.22);
    this.beep(660, 0.18, 0.82, 0.22);
  }
}

export const ringtone = new Ringtone();
