<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
import { playCountdownMusic, stopCountdownMusic } from '@/commons/music'

const props = withDefaults(defineProps<{
    width?: number
    height?: number
    mode?: 'contain' | 'cover'
    background?: string
}>(), {
    width: 1920,
    height: 1080,
    mode: 'contain',
    // background: '#FA6047',
})

const scale = ref(1)
const countdown = ref(3)
const countdownVisible = ref(false)
const countdownKey = ref(0)
const gameCountdown = ref(60)
const gameCountdownVisible = ref(false)
let countdownTimer: ReturnType<typeof setTimeout> | undefined
let countdownResolve: (() => void) | undefined

const updateScale = () => {
    const scaleX = window.innerWidth / props.width
    const scaleY = window.innerHeight / props.height
    scale.value = props.mode === 'cover'
        ? Math.max(scaleX, scaleY)
        : Math.min(scaleX, scaleY)
}

const stageStyle = computed(() => ({
    width: `${props.width}px`,
    height: `${props.height}px`,
    transform: `translate(-50%, -50%) scale(${scale.value})`,
}))

const clearCountdown = () => {
    if (countdownTimer) {
        clearTimeout(countdownTimer)
        countdownTimer = undefined
    }
}

const stopCountdown = () => {
    clearCountdown()
    stopCountdownMusic()
    countdownVisible.value = false
    gameCountdownVisible.value = false
    countdownResolve?.()
    countdownResolve = undefined
}

const startCountdown = (startSeconds = 3, gameSeconds = 60) => {
    stopCountdown()
    void playCountdownMusic()

    return new Promise<void>((resolve) => {
        countdownResolve = resolve
        countdown.value = startSeconds
        countdownVisible.value = true
        countdownKey.value += 1

        const startGameCountdown = () => {
            countdownVisible.value = false
            gameCountdown.value = gameSeconds
            gameCountdownVisible.value = true

            const tick = () => {
                gameCountdown.value -= 1

                if (gameCountdown.value <= 0) {
                    gameCountdown.value = 0
                    countdownTimer = undefined
                    gameCountdownVisible.value = false
                    countdownResolve?.()
                    countdownResolve = undefined
                    return
                }

                countdownTimer = setTimeout(tick, 1000)
            }

            countdownTimer = setTimeout(tick, 1000)
        }

        const tick = () => {
            if (countdown.value <= 1) {
                startGameCountdown()
                return
            }

            countdown.value -= 1
            countdownKey.value += 1
            countdownTimer = setTimeout(tick, 1000)
        }

        countdownTimer = setTimeout(tick, 1000)
    })
}

defineExpose({
    startCountdown,
    stopCountdown,
})

onMounted(() => {
    updateScale()
    window.addEventListener('resize', updateScale)
})

onBeforeUnmount(() => {
    window.removeEventListener('resize', updateScale)
    stopCountdown()
})
</script>

<template>
    <div class="design-stage-viewport" :style="{ background }">
        <div class="design-stage" :style="stageStyle">
            <div v-if="gameCountdownVisible" class="game-countdown">
                倒计时: &nbsp;{{ gameCountdown }}</div>
            <div v-if="countdownVisible" class="countdown-modal">
                <div :key="countdownKey" class="countdown-number">{{ countdown }}</div>
            </div>
            <slot />
        </div>
    </div>
</template>

<style scoped>
.design-stage-viewport {
    width: 100%;
    height: 100%;
    overflow: hidden;
    position: relative;
}

.countdown-modal {
    position: absolute;
    inset: 0;
    z-index: 10;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: rgba(0, 0, 0, 0.2);
    pointer-events: none;
}

.countdown-number {
    color: white;
    font-size: 300pt;
    font-weight: 800;
    line-height: 1;
    text-shadow: 0 18px 38px rgba(0, 0, 0, 0.25);
    animation: countdown-pop 1s ease both;
}

.game-countdown {
    position: absolute;
    top: 64px;
    right: 80px;
    z-index: 10;
    width: 300px;
    height: 84px;
    padding: 0 40px;
    background: rgba(0, 0, 0, 0.42);
    /* border: 1px solid #ccc; */
    color: #fff;
    font-size: 42px;
    line-height: 84px;
    text-align: center;
    box-shadow: 0 18px 42px rgba(0, 0, 0, 0.25);
    text-shadow: 0 8px 18px rgba(0, 0, 0, 0.4);
    pointer-events: none;
}

.design-stage {
    position: absolute;
    left: 50%;
    top: 50%;
    transform-origin: center center;
    overflow: hidden;
    z-index: 1;
}

@keyframes countdown-pop {
    0% {
        opacity: 0;
        transform: scale(0.45);
    }

    18% {
        opacity: 1;
        transform: scale(1.14);
    }

    58% {
        opacity: 1;
        transform: scale(1);
    }

    100% {
        opacity: 0;
        transform: scale(0.84);
    }
}
</style>
