import { Howl, Howler } from 'howler'

type TimeUpdateCallback = (currentTime: number) => void

declare module 'howler' {
  interface HowlerGlobal {
    _howls: Howl[]
  }
}

export class ExtendedHowl extends Howl {
  private _timeupdateListeners: TimeUpdateCallback[] = []
  private _interval: ReturnType<typeof setInterval> | null = null

  constructor(options: ConstructorParameters<typeof Howl>[0]) {
    super(options)
    this._startTimeUpdate()
  }

  private _startTimeUpdate(): void {
    this._interval = setInterval(() => {
      if (this.playing()) this._emitTimeUpdate(this.seek() as number)
    }, 250)
  }

  private _emitTimeUpdate(currentTime: number): void {
    this._timeupdateListeners.forEach((cb) => cb(currentTime))
  }

  onTimeUpdate(cb: TimeUpdateCallback): void {
    this._timeupdateListeners.push(cb)
  }

  offTimeUpdate(cb: TimeUpdateCallback): void {
    this._timeupdateListeners = this._timeupdateListeners.filter((l) => l !== cb)
  }

  play(id?: number): number {
    const result = super.play(id as number)
    if (!this._interval) this._startTimeUpdate()
    return result
  }

  pause(id?: number): this {
    super.pause(id)
    if (this._interval) {
      clearInterval(this._interval)
      this._interval = null
    }
    return this
  }

  stop(id?: number): this {
    super.stop(id)
    if (this._interval) {
      clearInterval(this._interval)
      this._interval = null
    }
    return this
  }
}

export function createSound(audioUrl?: string): ExtendedHowl | null {
  return audioUrl ? new ExtendedHowl({ src: [audioUrl] }) : null
}

export function stopAllSounds(): void {
  Howler._howls?.forEach((sound: Howl) => sound.stop())
}
