import { assetUrl } from '@/commons/assets'

const game1MusicUrl = assetUrl('game1.mp3')
const game2MusicUrl = assetUrl('game2.mp3')
const game4MusicUrl = assetUrl('cmyf-bgm.mp3')
const game5MusicUrl = assetUrl('qcnf-bgm.mp3')
const game6MusicUrl = assetUrl('game6.mp3')
const go321 = assetUrl('321go.mp3')
const applause = assetUrl('applause.mp3')

let backgroundMusic: HTMLAudioElement | null = null
let countdownTemplate: HTMLAudioElement | null = null
let pendingCountdownRetry: (() => void) | null = null
const countdownAudios = new Set<HTMLAudioElement>()



export function stopAllMusic() {
    stopApplauseMusic();
    stopGame1Music();
    stopGame2Music();
    // stopGame3Music();
    stopGame4Music();
    stopGame5Music();
    stopGame6Music();
    backgroundMusic = null;
}

function getBackgroundMusic(music: string, force: boolean = true) {
    if (force) { //
        if (backgroundMusic) {
            stopAllMusic();
        }
    }
    if (!backgroundMusic) {
        backgroundMusic = new Audio(music)
        backgroundMusic.loop = true
        backgroundMusic.preload = 'auto'
        backgroundMusic.volume = 0.6
        backgroundMusic.load()
    }

    return backgroundMusic
}

//播放庆祝音乐
export async function playApplauseMusic() {
    const audio = getBackgroundMusic(applause)

    try {
        await audio.play()
        window.removeEventListener('pointerdown', playApplauseMusic)
        window.removeEventListener('keydown', playApplauseMusic)
    } catch {
        window.addEventListener('pointerdown', playApplauseMusic, { once: true })
        window.addEventListener('keydown', playApplauseMusic, { once: true })
    }
}

export function stopApplauseMusic() {
    window.removeEventListener('pointerdown', playApplauseMusic)
    window.removeEventListener('keydown', playApplauseMusic)
    backgroundMusic?.pause()
}


export async function playGame1Music() {
    const audio = getBackgroundMusic(game1MusicUrl)

    try {
        await audio.play()
        window.removeEventListener('pointerdown', playGame1Music)
        window.removeEventListener('keydown', playGame1Music)
    } catch {
        window.addEventListener('pointerdown', playGame1Music, { once: true })
        window.addEventListener('keydown', playGame1Music, { once: true })
    }
}

export function stopGame1Music() {
    window.removeEventListener('pointerdown', playGame1Music)
    window.removeEventListener('keydown', playGame1Music)
    backgroundMusic?.pause()
}

export async function playGame2Music() {
    const audio = getBackgroundMusic(game2MusicUrl)

    try {
        await audio.play()
        window.removeEventListener('pointerdown', playGame2Music)
        window.removeEventListener('keydown', playGame2Music)
    } catch {
        window.addEventListener('pointerdown', playGame2Music, { once: true })
        window.addEventListener('keydown', playGame2Music, { once: true })
    }
}

export function stopGame2Music() {
    window.removeEventListener('pointerdown', playGame2Music)
    window.removeEventListener('keydown', playGame2Music)
    backgroundMusic?.pause()
}

export async function playGame4Music() {
    const audio = getBackgroundMusic(game4MusicUrl)

    try {
        await audio.play()
        window.removeEventListener('pointerdown', playGame4Music)
        window.removeEventListener('keydown', playGame4Music)
    } catch {
        window.addEventListener('pointerdown', playGame4Music, { once: true })
        window.addEventListener('keydown', playGame4Music, { once: true })
    }
}

export function stopGame4Music() {
    window.removeEventListener('pointerdown', playGame4Music)
    window.removeEventListener('keydown', playGame4Music)
    backgroundMusic?.pause()
}

export async function playGame5Music() {
    const audio = getBackgroundMusic(game5MusicUrl)

    try {
        await audio.play()
        window.removeEventListener('pointerdown', playGame5Music)
        window.removeEventListener('keydown', playGame5Music)
    } catch {
        window.addEventListener('pointerdown', playGame5Music, { once: true })
        window.addEventListener('keydown', playGame5Music, { once: true })
    }
}

export function stopGame5Music() {
    window.removeEventListener('pointerdown', playGame5Music)
    window.removeEventListener('keydown', playGame5Music)
    backgroundMusic?.pause()
}

export async function playGame6Music() {
    const audio = getBackgroundMusic(game6MusicUrl)

    try {
        await audio.play()
        window.removeEventListener('pointerdown', playGame6Music)
        window.removeEventListener('keydown', playGame6Music)
    } catch {
        window.addEventListener('pointerdown', playGame6Music, { once: true })
        window.addEventListener('keydown', playGame6Music, { once: true })
    }
}

export function stopGame6Music() {
    window.removeEventListener('pointerdown', playGame6Music)
    window.removeEventListener('keydown', playGame6Music)
    backgroundMusic?.pause()
}

function getCountdownTemplate() {
    if (!countdownTemplate) {
        countdownTemplate = new Audio(go321)
        countdownTemplate.loop = false
        countdownTemplate.preload = 'auto'
        countdownTemplate.volume = 0.8
        countdownTemplate.load()
    }

    return countdownTemplate
}

function releaseCountdownAudio(audio: HTMLAudioElement) {
    audio.pause()
    audio.removeAttribute('src')
    audio.load()
    countdownAudios.delete(audio)
}

function clearCountdownRetry() {
    if (!pendingCountdownRetry) return

    window.removeEventListener('pointerdown', pendingCountdownRetry)
    window.removeEventListener('keydown', pendingCountdownRetry)
    pendingCountdownRetry = null
}

export async function playCountdownMusic() {
    const audio = getCountdownTemplate().cloneNode(true) as HTMLAudioElement
    audio.loop = false
    audio.volume = 1
    countdownAudios.add(audio)

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

    try {
        await audio.play()
        clearCountdownRetry()
    } catch {
        releaseCountdownAudio(audio)

        if (pendingCountdownRetry) return
        pendingCountdownRetry = () => {
            pendingCountdownRetry = null
            void playCountdownMusic()
        }
        window.addEventListener('pointerdown', pendingCountdownRetry, { once: true })
        window.addEventListener('keydown', pendingCountdownRetry, { once: true })
    }
}

export function stopCountdownMusic() {
    clearCountdownRetry()
    countdownAudios.forEach(releaseCountdownAudio)
}
