<script lang="ts">
    import { random_string } from "$lib/helpers";
    import { createEventDispatcher } from "svelte";
    import { onMount } from "svelte";
    import { Temporal } from "temporal-polyfill";
    import {
        ExclamationTriangle,
        CheckCircle,
        InformationCircle,
        XCircle,
        XMark,
    } from "./icons";

    const noCooldownSetting = "no-cooldown";
    // if no unique id is supplied, cooldown will not work between page loads.
    // Therefore we are disabling it with noCooldownSetting in the fallback id.
    export let id = "alert--" + noCooldownSetting + "--" + random_string(4);
    export let title = "";
    export let message = "";
    export let type: "info" | "success" | "warning" | "error" = "info";
    export let closeable = false;
    export let closeableCooldown = "-1";
    export let rightLinkText = "";
    export let listItems: Array<string> = [];
    export let actions: Array<{ id: string; text: string; color?: string }> =
        [];
    // This value is set on a plain anchor tag without any svelte routing,
    // listen to the right-link-click if you want to intercept the click without navigating
    export let rightLinkHref = "javascript:void(0)";
    export let visible = true;

    const dispatch = createEventDispatcher();

    const cooldownStorageKey = "lastseen--" + id;

    let iconComponent: any;
    let colorClassPart = "";

    $: switch (type) {
        case "info": {
            colorClassPart = "blue";
            iconComponent = InformationCircle;
            break;
        }
        case "warning": {
            colorClassPart = "yellow";
            iconComponent = ExclamationTriangle;
            break;
        }
        case "error": {
            colorClassPart = "red";
            iconComponent = XCircle;
            break;
        }
        case "success": {
            colorClassPart = "green";
            iconComponent = CheckCircle;
            break;
        }
    }

    $: cooldownEnabled =
        id.indexOf(noCooldownSetting) === -1 &&
        closeable &&
        (closeableCooldown === "~" || parseInt(closeableCooldown) > 0);

    function close() {
        visible = false;
        if (cooldownEnabled) {
            console.log(
                "Cooldown enabled for " + id + ", " + closeableCooldown === "~"
                    ? "with an endless cooldown"
                    : ""
            );
            localStorage.setItem(
                cooldownStorageKey,
                String(Temporal.Now.instant().epochSeconds)
            );
        }
    }

    // Manages the state of the alert if cooldown is enabled
    function run_cooldown() {
        if (!cooldownEnabled) {
            console.log("Alert cooldown is not enabled for " + id);
            return;
        }
        if (!localStorage.getItem(cooldownStorageKey)) {
            console.log("Alert " + id + " has not been seen yet, displaying");
            visible = true;
            return;
        }
        if (!visible) {
            console.log(
                "Alert " + id + " is not visible, stopping cooldown change"
            );
            return;
        }
        if (closeableCooldown === "~") {
            console.log("Alert " + id + " has an infinite cooldown, hiding");
            visible = false;
            return;
        }

        const lastSeen = Temporal.Instant.fromEpochSeconds(
            parseInt(localStorage.getItem(cooldownStorageKey) ?? "-1")
        );
        if (
            Temporal.Instant.compare(
                Temporal.Now.instant(),
                lastSeen.add({ seconds: parseInt(closeableCooldown) })
            ) === 1
        ) {
            console.log(
                "Alert " +
                    id +
                    " has a cooldown of " +
                    closeableCooldown +
                    " and was last seen " +
                    lastSeen.toLocaleString() +
                    " making it due for a showing"
            );
            visible = true;
        } else {
            visible = false;
        }
    }

    onMount(() => {
        if (cooldownEnabled) {
            run_cooldown();
        }
    });
</script>

{#if visible}
    <div class="rounded-md bg-{colorClassPart}-50 p-4 ">
        <div class="flex">
            <div class="flex-shrink-0">
                <svelte:component
                    this={iconComponent}
                    class="text-{colorClassPart}-400"
                />
            </div>
            <div class="ml-3">
                {#if title}
                    <h3 class="text-sm font-medium text-{colorClassPart}-800">
                        {title}
                    </h3>
                {/if}
                {#if message}
                    <div
                        class="{title
                            ? 'mt-2 text-sm'
                            : ''} text-{colorClassPart}-700"
                    >
                        <p>
                            {@html message}
                            {#if rightLinkText}
                                <p class="mt-3 text-sm md:mt-0 md:ml-6">
                                    <a
                                        href={rightLinkHref}
                                        on:click={() =>
                                            dispatch("right-link-click")}
                                        class="whitespace-nowrap font-medium text-{colorClassPart}-700 hover:text-{colorClassPart}-600"
                                    >
                                        {rightLinkText}
                                        <span aria-hidden="true"> &rarr;</span>
                                    </a>
                                </p>
                            {/if}
                        </p>
                        {#if listItems?.length ?? 0}
                            <ul class="list-disc space-y-1 pl-5">
                                {#each listItems as listItem}
                                    <li>{listItem}</li>
                                {/each}
                            </ul>
                        {/if}
                    </div>
                {/if}
            </div>
            {#if actions?.length ?? 0}
                <div class="mt-4">
                    <div class="-mx-2 -my-1.5 flex">
                        {#each actions as action}
                            {@const color = action?.color ?? colorClassPart}
                            <button
                                type="button"
                                on:click={() => dispatch("act-" + action.id)}
                                class="rounded-md
                            bg-{color}-50
                            px-2 py-1.5 text-sm font-medium
                            text-{color}-800
                            hover:bg-{color}-100
                            focus:outline-none focus:ring-2
                            focus:ring-{color}-600
                            focus:ring-offset-2
                            focus:ring-offset-{color}-50"
                            >
                                {action.text}
                            </button>
                        {/each}
                    </div>
                </div>
            {/if}
            {#if closeable}
                <div class="ml-auto pl-3">
                    <div class="-mx-1.5 -my-1.5">
                        <button
                            type="button"
                            on:click={() => close()}
                            class="inline-flex rounded-md bg-{colorClassPart}-50 p-1.5 text-{colorClassPart}-500 hover:bg-{colorClassPart}-100 focus:outline-none focus:ring-2 focus:ring-{colorClassPart}-600 focus:ring-offset-2 focus:ring-offset-{colorClassPart}-50"
                        >
                            <span class="sr-only">Dismiss</span>
                            <XMark />
                        </button>
                    </div>
                </div>
            {/if}
        </div>
    </div>
{/if}
