<script setup lang="ts">
import { Base64 } from 'js-base64';

import type { VoiceKey } from '#shared/pronunciation/voices.ts';

const props = withDefaults(defineProps<{
    pronunciation?: string | null;
    voice: VoiceKey;
    showVoiceLabel?: boolean;
}>(), {
    pronunciation: null,
});

const pronunciationLink = computed((): string | undefined => {
    if (!props.pronunciation) {
        return undefined;
    }

    return `/api/pronounce/${props.voice}/${Base64.encodeURI(props.pronunciation)}`;
});

const state = ref<'idle' | 'loading' | 'playing'>('idle');
const sound = ref<HTMLAudioElement>();
const pronounce = () => {
    if (!pronunciationLink.value) {
        return;
    }
    if (sound.value && sound.value.src.endsWith(pronunciationLink.value) && !sound.value.error) {
        // reuse the sound object if it has the same source and has been loaded without an error
        sound.value.pause();
        sound.value.currentTime = 0;
        sound.value.play();

        return;
    }

    sound.value = new Audio(pronunciationLink.value);

    sound.value.addEventListener('canplay', () => sound.value!.play());
    sound.value.addEventListener('play', () => state.value = 'playing');
    sound.value.addEventListener('ended', () => state.value = 'idle');
    sound.value.addEventListener('error', () => state.value = 'idle');

    state.value = 'loading';
    sound.value.load();
};

const icon = computed((): string => {
    switch (state.value) {
        case 'loading':
            return 'spinner fa-spin';
        case 'playing':
            return 'volume-up';
        case 'idle':
        default:
            return 'volume';
    }
});

const config = useConfig();
const voiceLabel = computed((): string | null => {
    if (!props.showVoiceLabel) {
        return null;
    }
    if (!config.pronunciation?.enabled) {
        return props.voice.toUpperCase();
    }

    const voices = config.pronunciation.voices;
    if (voices.length === 1 && props.voice === voices[0]) {
        // don’t show voice name if it is considered the main voice for this locale
        return null;
    }

    return props.voice.toUpperCase();
});
</script>

<template>
    <Tooltip
        tag="a"
        :text="$t('pronunciation.play')"
        :class="!pronunciation ? 'disabled' : ''"
        dir="ltr"
        :href="pronunciationLink"
        target="_blank"
        @click.prevent="pronounce"
    >
        <Icon :v="icon" /><sub v-if="voiceLabel">{{ voiceLabel }}</sub>
    </Tooltip>
</template>
