import { useEventListener } from '@vueuse/core'

export default function useAudioContext(audioTrack: Ref<MediaStreamTrack | undefined>) {
  const ctx = new (window.AudioContext || window.webkitAudioContext)()

  const stream = new MediaStream()
  const audioEl = new Audio()

  const sourceNode = shallowRef<MediaStreamAudioSourceNode>()
  const gainNode = ctx.createGain()

  watch(audioTrack, async (track, prevTrack) => {
    if (prevTrack)
      stream.removeTrack(prevTrack)

    if (!track)
      return

    stream.addTrack(track)

    if (!audioEl.srcObject) {
      audioEl.srcObject = stream
      audioEl.muted = true
    }

    sourceNode.value = ctx.createMediaStreamSource(stream)

    await connect()
  }, { immediate: true })

  useEventListener(document, 'click', async () => {
    if (ctx.state === 'suspended') {
      await ctx.resume()
    }

    await connect()
  }, { once: true })

  onScopeDispose(() => {
    audioEl.pause()
    audioEl.srcObject = null
    ctx.close()
  })

  async function connect() {
    if (!sourceNode.value || ctx.state === 'suspended')
      return

    sourceNode.value.connect(gainNode)
    gainNode.connect(ctx.destination)

    ctx.resume()
  }

  function setGain(value: number) {
    gainNode.gain.value = value
  }

  return {
    setGain,
  }
}
