import { createSharedComposable } from '@vueuse/core'
import { Howl } from 'howler'

const CONNECTION_SOUNDS = Object.keys(import.meta.glob('@/../public/sfx/connection/*.ogg')).map(path => path.replace('../public', ''))

console.log('CONNECTION_SOUNDS', CONNECTION_SOUNDS)

function hashStringToNumber(str: string, cap: number): number {
  let hash = 0
  for (let i = 0; i < str.length; i++) {
    hash = (hash * 31 + str.charCodeAt(i)) | 0
  }
  return Math.abs(hash) % cap
}

const oneShots: Howl[] = []

type SfxEvent = 'mic-on' | 'mic-off' | 'stream-on' | 'stream-off' | 'connection' | 'message'

const EVENT_VOLUME: Record<SfxEvent, number> = {
  'mic-on': 0.2,
  'mic-off': 0.2,
  'stream-on': 0.03,
  'stream-off': 0.03,
  'connection': 0.1,
}

// TODO: refactor this shit
export const useSfx = createSharedComposable(() => {
  const { outputMuted } = useApp()

  async function play(src: string, volume = 0.2): Promise<void> {
    return new Promise((resolve) => {
      const howl = new Howl({
        src,
        autoplay: true,
        loop: false,
        volume,
      })

      howl.on('end', () => {
        resolve()
      })
    })
  }

  async function playOneShot(src: string, volume = 0.2): Promise<void> {
    for (const oneShot of oneShots) {
      oneShot.stop()
    }

    oneShots.length = 0

    return new Promise((resolve) => {
      const howl = new Howl({
        src,
        autoplay: true,
        loop: false,
        volume,
      })

      oneShots.push(howl)

      howl.on('end', () => {
        resolve()
      })
    })
  }

  async function playEvent(event: SfxEvent) {
    switch (event) {
      default:
        await playOneShot(`/sfx/${event}.ogg`, EVENT_VOLUME[event])
        break
    }
  }

  async function playRandomConnectionSound(seed: string) {
    await playEvent('stream-on')

    if (outputMuted.value)
      return

    await play(CONNECTION_SOUNDS[hashStringToNumber(seed, CONNECTION_SOUNDS.length)]!, 0.1)
  }

  return {
    playOneShot,
    play,
    playRandomConnectionSound,
    playEvent,
  }
})
