import game1MusicUrl from '@/assets/images/game1.mp3'
import game6Music1Url from '@/assets/images/game6_1.mp3'
import game6Music2Url from '@/assets/images/game6_2.mp3'
import go321 from '@/assets/images/321go.mp3'


const effectTemplates = new Map<string, HTMLAudioElement>()
const playingEffects = new Set<HTMLAudioElement>()
let pendingPlay = false
let pendingRetry: (() => void) | null = null

function getEffectTemplate(music: string) {
    let template = effectTemplates.get(music)

    if (!template) {
        template = new Audio(music)
        template.loop = false
        template.preload = 'auto'
        template.volume = 1
        template.load()
        effectTemplates.set(music, template)
    }

    return template
}

function releaseEffect(audio: HTMLAudioElement) {
    audio.pause()
    audio.removeAttribute('src')
    audio.load()
    playingEffects.delete(audio)
}

function clearPendingRetry() {
    if (pendingRetry) {
        window.removeEventListener('pointerdown', pendingRetry)
        window.removeEventListener('keydown', pendingRetry)
        pendingRetry = null
    }
    pendingPlay = false
}

function setPendingRetry(retry: () => void) {
    clearPendingRetry()
    pendingPlay = true
    pendingRetry = retry
    window.addEventListener('pointerdown', retry, { once: true })
    window.addEventListener('keydown', retry, { once: true })
}

async function playEffect(music: string, retry: () => void) {
    const audio = getEffectTemplate(music).cloneNode(true) as HTMLAudioElement
    audio.loop = false
    audio.volume = 1
    playingEffects.add(audio)

    const release = () => releaseEffect(audio)
    audio.addEventListener('ended', release, { once: true })
    audio.addEventListener('error', release, { once: true })

    try {
        await audio.play()
        if (pendingRetry === retry) {
            clearPendingRetry()
        }
    } catch {
        releaseEffect(audio)

        if (!pendingPlay) {
            setPendingRetry(retry)
        }
    }
}

function stopEffects() {
    clearPendingRetry()
    for (const audio of playingEffects) {
        releaseEffect(audio)
    }
    playingEffects.clear()
}

export async function playGame1Music() {
    await playEffect(game1MusicUrl, playGame1Music)
}

export function stopGame1Music() {
    window.removeEventListener('pointerdown', playGame1Music)
    window.removeEventListener('keydown', playGame1Music)
    stopEffects()
}

export async function playCountdownMusic() {
    await playEffect(go321, playCountdownMusic)
}

export function stopCountdownMusic() {
    window.removeEventListener('pointerdown', playCountdownMusic)
    window.removeEventListener('keydown', playCountdownMusic)
    stopEffects()
}


/*
打地鼠击中爆炸6-1
打小白兔眩晕6-2
*/
export async function playGame6Music(index: number) {
    let arr: [string, string, string] = ['', game6Music1Url, game6Music2Url];
    const music = arr[index]

    if (!music) {
        return
    }

    const retry = () => { playGame6Music(index) }
    await playEffect(music, retry)
}

export function stopGame6Music() {
    stopEffects()
}
