<script lang="ts">
    import { page } from '$app/stores';
    import getAudioIDMetadata from '@core/audio/getAudioIDMetadata';
    import Background from '@core/components/background.svelte';
    import Cover from '@core/components/cover.svelte';
    import InteractiveBox from '@core/components/interactiveBox.svelte';
    import extractFileName from '@core/utils/extractFileName';
    import localforage from 'localforage';
    import { writable } from 'svelte/store';
    import { type LyricData } from "@alikia/aqualyrics";
    import userAdjustingProgress from '@core/state/userAdjustingProgress';
    import type { IAudioMetadata } from 'music-metadata-browser';
    import { onMount } from 'svelte';
    import progressBarRaw from '@core/state/progressBarRaw';
    import { parseTTML, parseLRC } from '@alikia/aqualyrics';
    import NewLyrics from '@core/components/lyrics/newLyrics.svelte';

    const audioId = $page.params.id;
    let audioPlayer: HTMLAudioElement | null = null;
    let volume = 1;
    let name = '';
    let singer = '';
    let duration = 0;
    let currentProgress = 0;
    let audioFile: File;
    let paused: boolean = true;
    let launched = false;
    let prepared: string[] = [];
    let originalLyrics: LyricData;
    let lyricsText: string[] = [];
    let hasLyrics: boolean;
    const coverPath = writable('');
    let mainInterval: ReturnType<typeof setInterval>;

    function setMediaSession() {
        if ('mediaSession' in navigator === false) return;
        const ms = navigator.mediaSession;
        ms.metadata = new MediaMetadata({
            title: name,
            artist: singer,
            artwork: [
                {
                    src: $coverPath
                }
            ]
        });
        ms.setActionHandler('play', function () {
            if (audioPlayer === null) return;
            audioPlayer.play();
            paused = false;
        });

        ms.setActionHandler('pause', function () {
            if (audioPlayer === null) return;
            audioPlayer.pause();
            paused = true;
        });

        ms.setActionHandler('seekbackward', function () {
            if (audioPlayer === null) return;
            if (audioPlayer.currentTime > 4) {
                audioPlayer.currentTime = 0;
            }
        });

        ms.setActionHandler('previoustrack', function () {
            if (audioPlayer === null) return;
            if (audioPlayer.currentTime > 4) {
                audioPlayer.currentTime = 0;
            }
        });
    }

    function readDB() {
        getAudioIDMetadata(audioId, (metadata: IAudioMetadata | null) => {
            if (!metadata) return;
            duration = metadata.format.duration ? metadata.format.duration : 0;
            singer = metadata.common.artist ? metadata.common.artist : '未知歌手';
            prepared.push('duration');
        });
        localforage.getItem(`${audioId}-cover`, function (err, file) {
            if (file) {
                const img = new Image();
                img.src = URL.createObjectURL(file as File);

                img.onload = function () {
                    const canvas = document.createElement('canvas');
                    const ctx = canvas.getContext('2d');

                    let newWidth = img.width;
                    let newHeight = img.height;

                    if (newWidth < 1200) {
                        newWidth = 1200;
                        newHeight = (img.height * 1200) / img.width;
                    }

                    canvas.width = newWidth;
                    canvas.height = newHeight;

                    ctx!.drawImage(img, 0, 0, newWidth, newHeight);

                    canvas.toBlob(function (blob) {
                        const path = URL.createObjectURL(blob!);
                        coverPath.set(path);
                    }, 'image/jpeg');

                    prepared.push('cover');
                };

                img.onerror = function () {
                    console.error('Failed to load image');
                    prepared.push('cover');
                };
            } else {
                prepared.push('cover');
            }
        });
        localforage.getItem(`${audioId}-file`, function (err, file) {
            if (audioPlayer === null) return;
            if (file) {
                const f = file as File;
                audioFile = f;
                audioPlayer.src = URL.createObjectURL(audioFile);
                name = extractFileName(f.name);
                prepared.push('name');
                prepared.push('file');
            }
        });
        localforage.getItem(`${audioId}-lyric`, function (err, file) {
            if (file) {
                const f = file as File;
                f.text().then((lr) => {
                    if (f.name.endsWith('.ttml')) {
                        originalLyrics = parseTTML(lr);
                        console.log(originalLyrics);
                        for (const line of originalLyrics.scripts!) {
                            lyricsText.push(line.text);
                        }
                        hasLyrics = true;
                    } else if (f.name.endsWith('.lrc')) {
                        originalLyrics = parseLRC(lr);
                        if (!originalLyrics.scripts) return;
                        for (const line of originalLyrics.scripts) {
                            lyricsText.push(line.text);
                        }
                    }
                });
            }
        });
    }

    function playAudio() {
        if (audioPlayer === null) return;
        if (audioPlayer.duration) {
            duration = audioPlayer.duration;
        }
        audioPlayer.paused ? audioPlayer.play() : audioPlayer.pause();
        paused = audioPlayer.paused;
        setMediaSession();
    }

    $: {
        if (!launched && audioPlayer) {
            const requirements = ['name', 'file', 'cover'];
            let flag = true;
            for (const r of requirements) {
                if (!prepared.includes(r)) {
                    flag = false;
                }
            }
            if (flag) {
                launched = true;
                setMediaSession();
                audioPlayer.play();
            }
        }
    }

    function adjustProgress(progress: number) {
        if (audioPlayer) {
            audioPlayer.currentTime = duration * progress;
            currentProgress = duration * progress;
        }
    }

    function adjustDisplayProgress(progress: number) {
        if (audioPlayer) {
            currentProgress = duration * progress;
        }
    }

    function adjustVolume(targetVolume: number) {
        if (audioPlayer) {
            audioPlayer.volume = targetVolume;
        }
    }

    $: {
        clearInterval(mainInterval);
        mainInterval = setInterval(() => {
            if (audioPlayer === null) return;
            if ($userAdjustingProgress === false) currentProgress = audioPlayer.currentTime;
            progressBarRaw.set(audioPlayer.currentTime);
        }, 50);
    }

    onMount(() => {
        if (audioPlayer === null) return;
        audioPlayer.volume = localStorage.getItem('volume') ? Number(localStorage.getItem('volume')) : 1;
    });

    $: {
        if (audioPlayer) {
            paused = audioPlayer.paused;
            volume = audioPlayer.volume;
        }
    }

    $: hasLyrics = !!originalLyrics;

    readDB();
</script>

<svelte:head>
    <title>{name} - AquaVox</title>
</svelte:head>

<Background coverId={audioId} />
<Cover {coverPath} {hasLyrics} />
<InteractiveBox
    {name}
    {singer}
    {duration}
    {volume}
    progress={currentProgress}
    clickPlay={playAudio}
    {paused}
    {adjustProgress}
    {adjustVolume}
    {adjustDisplayProgress}
    {hasLyrics}
/>

<NewLyrics {originalLyrics} progress={currentProgress} player={audioPlayer}/>

<audio
    bind:this={audioPlayer}
    controls
    style="display: none"
    on:play={() => {
        if (audioPlayer === null) return;
        paused = audioPlayer.paused;
    }}
    on:pause={() => {
        if (audioPlayer === null) return;
        paused = audioPlayer.paused;
    }}
    on:ended={() => {
        paused = true;
        if (audioPlayer == null) return;
        audioPlayer.pause();
    }}
></audio>
