<script lang="ts">
    import { isLoggedIn, parseTaskId } from "./ksp-task-grabber";
    import type { TaskStatus } from "./ksp-task-grabber";
    import type { TaskSubmitStatus, SubtaskSubmitStatus } from './ksp-submit-api'
    import * as api from './ksp-submit-api'
    import { taskStatuses, refresh as refreshTaskStatus } from './task-status-cache'
    import * as s from 'svelte'

    export let id: string;
    const taskFromCache: TaskStatus | undefined = $taskStatuses.get(id)
    let task: TaskSubmitStatus
    let subtaskId: string = "1"
    let uploadSubtaskId: string | null | undefined = null
    let expiresInSec: number = 0
    let tick = 1
    let validSubmitSubtasks: SubtaskSubmitStatus[] = []
    let downloading = false
    let generating = false
    let downloadedSubtasks = new Set<string>()

    $: {
        if (task && task.id == "cviciste/" + id) {
            break $
        }

        task = {
            // fill with guesses to prevent flashing
            id,
            name: "",
            points: taskFromCache?.points ?? 0,
            max_points: taskFromCache?.maxPoints ?? 1,
            subtasks: [
                { id: "1", input_generated: false, max_points: 1, points: 0 }
            ]
        }
        subtaskId = "1"

        updateTaskStatus()

        downloadedSubtasks.clear()
    }

    $: {
        tick
        task
        expiresInSec = uploadSubtaskId ? calcExpires(uploadSubtaskId) : 0
    }
    window.setInterval(() => { tick++ }, 1000)

    $: {
        tick
        validSubmitSubtasks = task.subtasks.filter(t => calcExpires(t.id) > 0)
    }
    $: {
        if (!validSubmitSubtasks.map(t => t.id).includes(uploadSubtaskId!)) {
            uploadSubtaskId = validSubmitSubtasks.find(t => !isDone(t))?.id ?? validSubmitSubtasks[0]?.id
        }
    }

    function updateTaskStatus() {
        api.taskStatus(id)
           .then(t => {
               task = t
               updateCurrentDownloadTask()
           })
    }

    function updateCurrentDownloadTask() {
        // update the default task for download
        // prefer not-downloaded not-done.
        const newSubtaskId =
            task.subtasks.find(t => !isDone(t) && !downloadedSubtasks.has(t.id))?.id
        if (newSubtaskId) {
            subtaskId = newSubtaskId
        }
    }

    function updateCurrentUploadTask() {
        // update the default task for upload
        const newSubtaskId =
            validSubmitSubtasks.find(t => !isDone(t))?.id
        if (newSubtaskId) {
            uploadSubtaskId = newSubtaskId
        }
    }

    function calcExpires(subtask: string): number {
        const st = task.subtasks.find(t => t.id == subtask)
        if (!st || !st.input_generated) {
            return 0
        }
        const validUntil = new Date(st.input_valid_until!).valueOf()
        const now = Date.now()
        if (validUntil < now) {
            return 0
        } else {
            return (validUntil - now) / 1000
        }
    }

    function isDone(subtask: SubtaskSubmitStatus) {
        return subtask.points > subtask.max_points - 0.0001
    }

    function nameSubtask(subtask: SubtaskSubmitStatus) {
        const map: any = {
            "1": "první",
            "2": "druhý",
            "3": "třetí",
            "4": "čtvrtý",
            "5": "pátý",
            "6": "šestý",
            "7": "sedmý",
            "8": "osmý",
            "9": "devátý",
            "10": "desátý"
        }
        const check = isDone(subtask) ? " ✔️" : ""
        return (map[subtask.id] ?? subtask.id) + check
    }

    function magicTrickSaveBlob(blob: Blob, fileName: string) {
        const url = URL.createObjectURL(blob)
        magicTrickSaveFile(url, fileName)
        window.URL.revokeObjectURL(url);
    }
    function magicTrickSaveFile(url: string, fileName: string) {
        var a = document.createElement("a");
        document.body.appendChild(a);
        a.style.display = "none";
        a.href = url;
        a.download = fileName;
        a.click();
        a.remove()
    }

    async function download() {
        // copy to prevent races
        const [id_, subtaskId_] = [id, subtaskId]
        if (!subtaskId_) { return }
        if (calcExpires(subtaskId_) < 20) {
            const x = await api.generateInput(id_, subtaskId_)
            if (id_ != id) { return }
            const subtasks = [...task.subtasks]
            subtasks[subtasks.findIndex(s => s.id == x.id)] = x
            task = { ...task, subtasks }
        }
        // It's probably better to download the input using the "old" method
        // TODO: specify that as an API

        const parsedId = parseTaskId(id_)
        magicTrickSaveFile(`/cviciste/?in=1:sub=${subtaskId}:task=${id_}:year=${parsedId!.rocnik}`, subtaskId_ + ".in.txt")
        downloadedSubtasks.add(subtaskId_)
        updateCurrentDownloadTask()

        // if we have a solved task selected, select the downloaded task for upload
        if (!uploadSubtaskId || isDone(task.subtasks.find(t => t.id == uploadSubtaskId)!)) {
            uploadSubtaskId = subtaskId_
        }

        // const blob = await api.getInput(id_, subtaskId_)
        // magicTrickSaveBlob(blob, subtaskId_ + ".in.txt")
    }

    async function upload(file: File) {
        const x = await api.submit(id, uploadSubtaskId!, file)
        refreshTaskStatus([id])
        const subtasks = [...task.subtasks]
        subtasks[subtasks.findIndex(s => s.id == x.id)] = x
        task = { ...task, subtasks }
        alert(x.verdict)
        await s.tick() // wait for update of validSubmitSubtasks
        updateCurrentUploadTask()
    }

    function fileChange(ev: Event) {
        const file = (ev.target as HTMLInputElement).files![0]
        upload(file)
    }

    function drop(ev: DragEvent) {
        ev.preventDefault()
        const files = ev.dataTransfer?.files ?? []
        if (files.length > 1) {
            alert("Drag & Drop funguje, ale musíš jenom jeden soubor")
        }
        if (files.length > 0) {
            upload(files[0])
        }
    }
    function dragOver(ev: DragEvent) {
        ev.preventDefault()
    }
</script>

<style>
    
</style>

<svelte:body on:drop={drop} on:dragover={dragOver} />

<div class="odevzdavatko">
    <div class="download">
        <button class="download"
                on:click={download}
                disabled={downloading || generating}>
            {#if generating}
                Generuji...
            {:else if downloading}
                Stahuji...
            {:else if tick && calcExpires(subtaskId) > 20}
                Stáhnout
            {:else}
                Vygenerovat a stáhnout
            {/if}
        </button>
        <select bind:value={subtaskId}>
            <option value={null}></option>
            {#each task.subtasks as subtask}
                <option value={subtask.id}>
                    {nameSubtask(subtask)}
                </option>
            {/each}
        </select>
        vstup.
    </div>

    {#if validSubmitSubtasks.length > 0}
    <div class="upload">
        Odevzdat
        <select bind:value={uploadSubtaskId}>
            {#each validSubmitSubtasks as subtask}
                <option value={subtask.id}>
                    {nameSubtask(subtask)}
                </option>
            {/each}
        </select>
        vstup:

        <input type="file" on:change={fileChange}> (nebo přetáhni soubor na stránku)
    </div>
    <div>
        {#if expiresInSec > 60*60*24*30}
            Vstup neexpiruje.
        {:else}
            Vstup expiruje za {Math.floor(expiresInSec / 60 / 60).toLocaleString('en-US', {minimumIntegerDigits: 2, useGrouping:false})}:{Math.floor(expiresInSec / 60 % 60).toLocaleString('en-US', {minimumIntegerDigits: 2, useGrouping:false})}:{Math.floor(expiresInSec % 60).toLocaleString('en-US', {minimumIntegerDigits: 2, useGrouping:false})}s.
        {/if}
    </div>
    {/if}
</div>
