<script lang="typescript">
    import type {
        PollOptions,
        PollResult,
        LogEvent,
    } from "src/routes/logs/poll";
    import { faSyncAlt } from "@fortawesome/free-solid-svg-icons";
    import Icon from "svelte-awesome/components/Icon.svelte";

    const sync = (faSyncAlt as unknown) as undefined;
    const POLL_INTERVAL = 5000;
    let logEvents: LogEvent[] | undefined = undefined;
    let syncing = false;
    let poller = 0;
    let maxMessages = 50;
    let error = "";

    const LEVEL_COLORS: Record<string, string> = {
        "verbose": "#A0AEC0",
        "info": "#EFF2F7",
        "warn": "#ECC94B",
        "error": "#C53030",
    };

    function getLevelColor(level: string) {
        if (level in LEVEL_COLORS) {
            return LEVEL_COLORS[level];
        }
        return "#FFFFFF";
    }

    function onAutoUpdateChecked(event: Event & { target: HTMLInputElement }) {
        if (event.target.checked) {
            const pollCallback = async () => {
                await pollEvents();
                poller = setTimeout(pollCallback, POLL_INTERVAL);    
            }
            if (poller >= 0) {
                poller = setTimeout(pollCallback, POLL_INTERVAL);
            }
        } else {
            clearTimeout(poller);
            poller = -1;
        }
    }

    async function pollEvents() {
        if (syncing) {
            return;
        }
        syncing = true;
        const params: PollOptions = {
            limit: maxMessages.toString(),
        };
        const query = Object.entries(params).reduce(
            (prev, [key, val]) =>
                `${prev}&${encodeURIComponent(key)}=${encodeURIComponent(val)}`,
            ""
        );
        const response = await fetch(`/logs/poll?${query}`, {
            method: "get",
            credentials: "include",
            headers: {
                Accept: "application/json",
            },
        });

        const result = (await response.json()) as PollResult;
        if (result.ok) {
            logEvents = result.events;
        } else {
            error = result.error;
        }
        syncing = false;
    }
</script>

<style>
    .sync-button {
        @apply bg-blue-600 py-1 px-3 text-white cursor-pointer rounded-sm text-sm;

        &:hover {
            @apply bg-blue-700 text-gray-100;
        }
    }

    .logs-table {
        @apply bg-black m-3 block overflow-y-auto;
        max-height: 70%;

        td,
        th {
            @apply font-mono px-2 text-sm;
        }

        thead th {
            @apply sticky top-0 bg-black py-2;
        }
    }

    .error-box {
        @apply text-gray-100 bg-red-600 py-4 px-3 rounded-sm;
    }

    .query-row {
        @apply flex flex-row justify-end items-center;
    }

    .event-log-options {
        @apply flex flex-col;

        input[type="number"] {
            @apply text-black w-16;
        }
    }
</style>

<div class="viewport text-white">
    <h1 class="text-3xl pb-4">Event logs</h1>
    <form class="py-2" on:submit|preventDefault={pollEvents}>
        <div class="event-log-options">
            <label>Max messages: <input type="number" min="0" bind:value={maxMessages} /></label>
        </div>
        <div class="query-row">
            {#if syncing}
                <Icon class="mx-1" data={sync} spin />
            {/if}
            <input class="sync-button" type="submit" value="Query" disabled={syncing} />
            <label class="mx-1"><input type="checkbox" on:input={onAutoUpdateChecked}/> Auto update</label>
        </div>
    </form>
    {#if error}
        <p class="error-box">
            Failed to query: <span class="font-mono">{error}</span>
        </p>
    {/if}
    {#if logEvents}
        <table class="logs-table">
            <thead>
                <tr>
                    <th>Timestamp</th>
                    <th>Source</th>
                    <th>Level</th>
                    <th>Message</th>
                </tr>
            </thead>
            <tbody>
                {#each logEvents as logEvent (logEvent._id)}
                    <tr style="color: {getLevelColor(logEvent.level)};">
                        <td>{logEvent.timestamp}</td>
                        <td>{logEvent.label}</td>
                        <td>{logEvent.level}</td>
                        <td>{logEvent.message}</td>
                    </tr>
                {/each}
            </tbody>
        </table>
    {/if}
</div>
