<script setup lang="ts">
import type { ParsedContent } from '@nuxt/content/dist/runtime/types';

const props = defineProps({
    href: {
        type: String,
        default: ''
    },
    target: {
        type: String,
        default: undefined,
        required: false
    }
})

function sluggify(s: string): string {
    return s
        .split("/")
        .map((segment) => segment.normalize('NFD').replace(/[\u0300-\u036f]/g, '').replace(/^\d\. */g, '').replace(/\s/g, "-").replace(/%/g, "-percent").replace(/\?/g, "-q").toLowerCase()) // slugify all segments
        .filter(e => !!e)
        .join("/") // always use / as sep
        .replace(/\/$/, "")
}
function flatten(val: TocLink[]): TocLink[] {
    return val.flatMap ? val?.flatMap((e: TocLink) => e.children ? [e, ...flatten(e.children)] : e) : val;
}

const link = (props.href.includes('#') ? props.href.substring(0, props.href.indexOf('#')) : props.href).replace(/\..*$/, '');
const anchor = props.href.includes('#') ? props.href.substring(props.href.indexOf('#'), props.href.length) : '';
let content: ParsedContent;
try {
    content = await queryContent().where({ _path: new RegExp(sluggify(link) + '$', 'i') }).findOne();
    if(anchor && !!content && content._type == 'markdown' && content.body && content.body.children)
    {
        const id = flatten(content.body.toc?.links).find(e => "#" + sluggify(e.id) === anchor);
        const tag = `h${id?.depth ?? 0}`;

        const startIdx = content.body.children.findIndex(e => e.tag === tag && e?.props?.id === id?.id) ?? 0;
        const nbr = content.body.children.findIndex((e, i) => i > startIdx && e.tag?.match(new RegExp(`h[1-${id?.depth ?? 1}]`))) ?? content.body.children.length;

        content.body.children = content.body.children.splice(startIdx, nbr - startIdx);
    }
} catch (e) {}

const hovered = ref(false), pos = ref<DOMRect>();
let timeout: NodeJS.Timeout;
function showPreview(e: Event, bbox: boolean) {
    clearTimeout(timeout);
    !!bbox && (pos.value = (e.currentTarget as HTMLElement)?.getBoundingClientRect());
    hovered.value = true;
}
function hidePreview(e: Event) {
    timeout = setTimeout(() => hovered.value = false, 300);
}
</script>

<template >
    <NuxtLink custom no-prefetch v-slot="{ href: hrefSlot, navigate }" :to="(content?._path ?? href + anchor) ?? href" :target="target">
        <a :href="hrefSlot" @click="navigate" @mouseenter="(e) => showPreview(e, true)" @mouseleave="hidePreview" v-bind="$attrs"><slot ></slot></a>
    </NuxtLink>
    <Teleport to="body" v-if="hovered && !!content">
        <div class="popover hover-popover is-loaded" :style="{ top: (pos.bottom + 4) + 'px', left: pos.left + 'px' }" @mouseenter="(e) => showPreview(e, false)" @mouseleave="hidePreview">
            <div class="markdown-embed" v-if="content._type == 'markdown'">
                <div class="markdown-embed-content">
                    <div class="markdown-preview-view markdown-rendered node-insert-event hide-title">
                        <div class="markdown-preview-sizer markdown-preview-section" style="padding-bottom: 0px;">
                            <h1 v-if="content?.title">{{ content?.title }}</h1>
                            <ContentRenderer :key="content._id" :value="content"/>
                        </div>
                    </div>
                </div>
            </div>
            <CanvasRenderer v-else-if="content._type == 'canvas'" :key="content._id" :canvas="content" />
            <div v-else>
                <div class="not-found-container">
                    <div class="not-found-image"></div>
                    <div class="not-found-title">Impossible d'afficher</div>
                    <div class="not-found-description">Cette page est actuellement vide et impossible à traiter</div>
                </div>
            </div>
        </div>
    </Teleport>
</template>