<!--
     This file is part of the happyDomain (R) project.
     Copyright (c) 2022-2025 happyDomain
     Authors: Pierre-Olivier Mercier, et al.

     This program is offered under a commercial and under the AGPL license.
     For commercial licensing, contact us at <contact@happydomain.org>.

     For AGPL licensing:
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Affero General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
     (at your option) any later version.

     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU Affero General Public License for more details.

     You should have received a copy of the GNU Affero General Public License
     along with this program.  If not, see <https://www.gnu.org/licenses/>.
-->

<script lang="ts">
    import { Badge, Button, Icon, Popover, Spinner } from "@sveltestrap/sveltestrap";

    import { deleteZoneService } from "$lib/api/zone";
    import { controls as ctrlNewAlias } from "$lib/components/modals/Alias.svelte";
    import { controls as ctrlRecord } from "$lib/components/modals/Record.svelte";
    import { controls as ctrlNewService } from "$lib/components/services/NewServicePath.svelte";
    import { fqdn, unreverseDomain } from "$lib/dns";
    import type { Domain } from "$lib/model/domain";
    import type { HappydnsService } from "$lib/api-base/types.gen";
    import { ZoneViewGrid, ZoneViewRecords } from "$lib/model/usersettings";
    import { navigate } from "$lib/stores/config";
    import { servicesSpecs } from "$lib/stores/services";
    import { thisAliases, thisZone } from "$lib/stores/thiszone";
    import { userSession } from "$lib/stores/usersession";
    import { t } from "$lib/translations";

    interface Props {
        dn: string;
        origin: Domain;
        services: Array<HappydnsService>;
        zoneId: string;
        reverseZone?: boolean;
        showResources?: boolean;
        toggleShowResources?: () => void;
    }

    let {
        dn,
        origin,
        services,
        zoneId,
        reverseZone = false,
        showResources = true,
        toggleShowResources = () => {
            showResources = !showResources;
        },
    }: Props = $props();

    function isCNAME(services: Array<HappydnsService>) {
        return services.length === 1 && services[0]._svctype === "svcs.CNAME";
    }

    function isPTR(services: Array<HappydnsService>) {
        return services.length === 1 && services[0]._svctype === "svcs.PTR";
    }

    let deleteServiceInProgress = $state(false);
    function deleteCNAME() {
        deleteServiceInProgress = true;
        deleteZoneService(origin, zoneId, services[0]).then(
            (z) => {
                thisZone.set(z);
                deleteServiceInProgress = false;
            },
            (err) => {
                deleteServiceInProgress = false;
                throw err;
            },
        );
    }
</script>

<div class="sticky-top bg-light d-flex align-items-center mb-3 gap-2" style="z-index: 1">
    <div
        role="button"
        tabindex="0"
        class="h2 text-truncate mb-0"
        class:text-muted={services.length === 0 && dn != ""}
        style:cursor={(services.length || dn == "") && !isPTR(services) && !isCNAME(services)
            ? "pointer"
            : "default"}
        onclick={toggleShowResources}
        onkeypress={toggleShowResources}
    >
        {#if services.length === 0 && dn != ""}
            <Icon name="plus-square-dotted" title="Intermediate domain with no service" />
        {:else if isPTR(services)}
            <Icon name="signpost" title="PTR" />
        {:else if isCNAME(services)}
            <Icon name="sign-turn-right" title="CNAME" />
        {:else if showResources}
            <Icon name="chevron-down" />
        {:else}
            <Icon name="chevron-right" />
        {/if}
        <span class="font-monospace" title={fqdn(dn, origin.domain)}>
            {#if reverseZone}
                {unreverseDomain(fqdn(dn, origin.domain))}
            {:else if dn}
                {dn}<span class="text-muted" style="opacity: 0.6;">.{origin.domain}</span>
            {:else}
                {origin.domain}
            {/if}
        </span>
    </div>
    {#if isCNAME(services) || isPTR(services)}
        {@const svcData = services[0].Service as Record<string, unknown> | undefined}
        {@const dn = (isPTR(services)
            ? (svcData?.Record as Record<string, unknown> | undefined)?.Ptr
            : (svcData?.cname as Record<string, unknown> | undefined)?.Target) as string}
        <span class="text-truncate text-muted lead">
            <Icon name="arrow-right" />
            <span class="font-monospace">
                {#if dn.endsWith(origin.domain)}
                    {dn.substring(0, dn.length - origin.domain.length - 1)}<span
                        style="opacity: 0.5;">.{origin.domain}</span
                    >
                {:else}
                    {dn}
                {/if}
            </span>
        </span>
    {:else if !showResources && services.length}
        <Badge color="primary" id={"popoversvc-" + dn.replace(".", "__")} style="cursor: pointer;">
            {$t("domains.n-services", { count: services.length })}
        </Badge>
        <Popover dismissible placement="bottom" target={"popoversvc-" + dn.replace(".", "__")}>
            {#each services as service}
                {#if $servicesSpecs[service._svctype]}
                    <strong>{$servicesSpecs[service._svctype].name}:</strong>
                {/if}
                <span class="text-muted">{service._comment}</span>
                <br />
            {/each}
        </Popover>
    {/if}
    {#if $thisAliases[dn] && $thisAliases[dn].length != 0}
        <Badge id={"popoverbadge-" + dn.replace(".", "__")} style="cursor: pointer;">
            + {$t("domains.n-aliases", { count: $thisAliases[dn].length })}
        </Badge>
        <Popover
            dismissible
            placement="bottom"
            target={"popoverbadge-" + dn.replace(".", "__")}
            class="font-monospace"
        >
            {#each $thisAliases[dn] as alias}
                <a href={"#" + alias}>
                    {alias}
                </a>
                <br />
            {/each}
        </Popover>
    {/if}
    <div class="flex-fill"></div>
    {#if isCNAME(services) || isPTR(services)}
        <Button
            type="button"
            color="info"
            outline
            size="sm"
            title={$t("domains.edit-target")}
            on:click={() => {
                const subdomainParam = dn === "" ? "@" : dn;
                navigate(
                    `/domains/${encodeURIComponent(origin.domain)}/${encodeURIComponent(zoneId)}/${encodeURIComponent(subdomainParam)}/${encodeURIComponent(services[0]._id!)}`,
                );
            }}
        >
            <Icon name="pencil" />
        </Button>
        <Button
            type="button"
            color="danger"
            disabled={deleteServiceInProgress}
            outline
            size="sm"
            title={isPTR(services) ? $t("domains.drop-pointer") : $t("domains.drop-alias")}
            on:click={deleteCNAME}
        >
            {#if deleteServiceInProgress}
                <Spinner size="sm" />
            {:else}
                <Icon name="x-circle" />
            {/if}
        </Button>
    {:else if showResources && services.length}
        <Button
            type="button"
            color="primary"
            outline
            size="sm"
            title={$t("domains.add-an-alias")}
            on:click={() => ctrlNewAlias.Open(dn)}
        >
            <Icon name="link" />
        </Button>
    {/if}
    {#if !showResources || ($userSession.settings && $userSession.settings.zoneview !== ZoneViewGrid)}
        {#if $userSession.settings && $userSession.settings.zoneview === ZoneViewRecords}
            <Button
                type="button"
                color="primary"
                size="sm"
                title={$t("domains.add-a-record")}
                on:click={() => ctrlRecord.Open(null, dn)}
            >
                <Icon name="plus" />
            </Button>
        {:else}
            <Button
                type="button"
                color="primary"
                size="sm"
                title={$t("domains.add-a-service")}
                on:click={() => ctrlNewService.Open(dn)}
            >
                <Icon name="plus" />
            </Button>
        {/if}
    {/if}
</div>
