import AMR from 'benz-amr-recorder';

type AMREvent = 'play' | 'stop';

class AMRPlayer {
  private amrInstances: Map<string, AMR> = new Map();
  private currentAudioUrl: string | null = null;
  private eventListeners: Map<string, () => void> = new Map();
  private isProcessing: boolean = false;

  public on(event: AMREvent, url: string, callback: () => void) {
    const key = `${event}:${url}`;
    this.eventListeners.set(key, callback);
  }

  public off(event: AMREvent, url: string) {
    const key = `${event}:${url}`;
    this.eventListeners.delete(key);
  }

  private emit(event: AMREvent, url: string) {
    const key = `${event}:${url}`;
    this.eventListeners.get(key)?.();
  }

  public async play(url: string) {
    if (this.isProcessing) return;
    this.isProcessing = true;

    try {
      if (this.currentAudioUrl === url) {
        await this.stop(url);
        return;
      }

      if (this.currentAudioUrl) {
        await this.stop(this.currentAudioUrl);
      }

      let amr = this.amrInstances.get(url);
      if (!amr) {
        amr = new AMR();
        amr.onEnded(async () => {
          await this.stop(url);
        });
        await amr.initWithUrl(url);
        this.amrInstances.set(url, amr);
      }

      await amr.play();
      this.currentAudioUrl = url;
      this.emit('play', url);
    } catch (error) {
      await this.stop(url);
      throw error;
    } finally {
      this.isProcessing = false;
    }
  }

  public async stop(url?: string) {
    const targetUrl = url || this.currentAudioUrl;
    if (!targetUrl) return;

    const amr = this.amrInstances.get(targetUrl);
    if (amr) {
      try {
        amr.stop();
      } catch (e) {
        console.error(e);
      }
      this.amrInstances.delete(targetUrl);
      if (this.currentAudioUrl === targetUrl) {
        this.currentAudioUrl = null;
      }
      this.emit('stop', targetUrl);
    }
  }

  public isPlaying(url: string): boolean {
    return this.currentAudioUrl === url && this.amrInstances.has(url);
  }
}

export const amrPlayer = new AMRPlayer();
