<script lang="ts">
    import { onMount, onDestroy } from "svelte";
    import type { IViewer } from "./viewers/IViewer";
    import { createViewer } from "./viewers/ViewerFactory";

    interface Data {
        input: string;
        input_path: string;
        model1: string;
        model1_path: string;
        model2: string;
        model2_path: string;
    }

    let viewerA: IViewer;
    let viewerB: IViewer;
    let canvasA: HTMLCanvasElement;
    let canvasB: HTMLCanvasElement;
    let containerA: HTMLDivElement;
    let containerB: HTMLDivElement;
    let overlayA: HTMLDivElement;
    let overlayB: HTMLDivElement;
    let loadingBarFillA: HTMLDivElement;
    let loadingBarFillB: HTMLDivElement;
    let statusMessage: string = "Loading...";
    let errorMessage: string = "";
    let data: Data;

    async function fetchScenes() {
        statusMessage = "Loading...";
        errorMessage = "";

        try {
            const username = "dylanebert";
            const url = `https://dylanebert-3d-arena-backend.hf.space/pair?username=${username}`;
            const response = await fetch(url, {
                method: "GET",
                headers: {
                    Authorization: "Bearer " + import.meta.env.VITE_HF_TOKEN,
                    "Cache-Control": "no-cache",
                },
            });
            const result = await response.json();
            if (result.input) {
                data = result;
                statusMessage = "";
                return true;
            } else {
                statusMessage = "Voting complete.";
                return false;
            }
        } catch (error) {
            errorMessage = "Failed to fetch pair.";
            statusMessage = "";
            return false;
        }
    }

    async function loadScenes() {
        const success = await fetchScenes();
        if (!success) return;

        overlayA.style.display = "flex";
        overlayB.style.display = "flex";

        const baseUrl = "https://huggingface.co/datasets/dylanebert/3d-arena/resolve/main/";
        const model1_path = `${baseUrl}${data.model1_path}`;
        const model2_path = `${baseUrl}${data.model2_path}`;

        try {
            const promises = [
                createViewer(model1_path, canvasA, (progress) => {
                    loadingBarFillA.style.width = `${progress * 100}%`;
                }),
                createViewer(model2_path, canvasB, (progress) => {
                    loadingBarFillB.style.width = `${progress * 100}%`;
                }),
            ];
            await Promise.all(promises);

            window.addEventListener("resize", handleResize);
            handleResize();
        } catch (error) {
            errorMessage = "Failed to load scenes.";
        }

        overlayA.style.display = "none";
        overlayB.style.display = "none";
    }

    async function vote(option: "A" | "B") {
        statusMessage = "Processing vote...";
        errorMessage = "";

        const payload = {
            username: "dylanebert",
            input: data.input,
            better: option == "A" ? data.model1 : data.model2,
            worse: option == "A" ? data.model2 : data.model1,
        };
        const url = `https://dylanebert-3d-arena-backend.hf.space/vote`;

        try {
            const response = await fetch(url, {
                method: "POST",
                headers: {
                    Authorization: "Bearer " + import.meta.env.VITE_HF_TOKEN,
                    "Cache-Control": "no-cache",
                    "Content-Type": "application/json",
                },
                body: JSON.stringify(payload),
            });

            if (response.ok) {
                const result = await response.json();
                console.log(result);
                loadScenes();
            } else {
                errorMessage = "Failed to process vote.";
            }
        } catch (error) {
            errorMessage = "Failed to process vote.";
            statusMessage = "";
        }
    }

    function handleResize() {
        requestAnimationFrame(() => {
            if (canvasA && containerA) {
                const maxWidth = containerA.clientHeight;
                const maxHeight = containerA.clientWidth;
                canvasA.width = Math.min(containerA.clientWidth, maxWidth);
                canvasA.height = Math.min(containerA.clientHeight, maxHeight);
            }
            if (canvasB && containerB) {
                const maxWidth = containerB.clientHeight;
                const maxHeight = containerB.clientWidth;
                canvasB.width = Math.min(containerB.clientWidth, maxWidth);
                canvasB.height = Math.min(containerB.clientHeight, maxHeight);
            }
        });
    }

    onMount(loadScenes);

    onDestroy(() => {
        viewerA?.dispose();
        viewerB?.dispose();
        if (typeof window !== "undefined") {
            window.removeEventListener("resize", handleResize);
        }
    });
</script>

{#if errorMessage}
    <p class="center-title muted" style="color: red;">{errorMessage}</p>
{:else if statusMessage}
    <p class="center-title muted">{statusMessage}</p>
{:else}
    <h2 class="center-title">Which is better?</h2>
    <div class="voting-container">
        <div bind:this={containerA} class="voting-canvas-wrapper">
            <div bind:this={overlayA} class="loading-overlay">
                <div class="loading-bar">
                    <div bind:this={loadingBarFillA} class="loading-bar-fill" />
                </div>
            </div>
            <canvas bind:this={canvasA} class="voting-canvas" id="canvas1"></canvas>
            <button class="vote-button" on:click={() => vote("A")}>A is Better</button>
        </div>
        <div bind:this={containerB} class="voting-canvas-wrapper">
            <div bind:this={overlayB} class="loading-overlay">
                <div class="loading-bar">
                    <div bind:this={loadingBarFillB} class="loading-bar-fill" />
                </div>
            </div>
            <canvas bind:this={canvasB} class="voting-canvas" id="canvas2"></canvas>
            <button class="vote-button" on:click={() => vote("B")}>B is Better</button>
        </div>
    </div>
{/if}
