<template>
    <Teleport to="#teleports" v-if="display">
        <div class="absolute border-2 border-light-35 dark:border-dark-35 max-w-[550px] max-h-[450px] bg-light-0 dark:bg-dark-0 text-light-100 dark:text-dark-100 overflow-hidden" :style="pos"
            @mouseenter="debounce(show, 250)" @mouseleave="debounce(() => { emit('beforeHide'); display = false }, 250)">
            <slot name="content"></slot>
        </div>
    </Teleport>
    <span ref="el" :class="$attrs.class" @mouseenter="debounce(show, 250)" @mouseleave="debounce(() => { emit('beforeHide'); display = false }, 250)">
        <slot name="default"></slot>
    </span>
</template>

<script setup lang="ts">
import { useTemplateRef } from 'vue';

const display = ref(false), fetched = ref(false);
const el = useTemplateRef('el'), pos = ref<Record<string, string>>();
const emit = defineEmits(['beforeShow', 'beforeHide']);

async function show()
{
    if(display.value)
        return;

    emit('beforeShow');

    const rect = (el.value as HTMLDivElement)?.getBoundingClientRect();

    if(!rect)
        return;

    const r: Record<string, string> = {};
    if (rect.bottom + 450 < window.innerHeight)
        r.top = (rect.bottom + 4) + "px";
    else
        r.bottom = (window.innerHeight - rect.top + 4) + "px";
    if (rect.right + 550 < window.innerWidth)
        r.left = rect.left + "px";
    else
        r.right = (window.innerWidth - rect.right + 4) + "px";

    pos.value = r;
    display.value = true;
}
let debounceFn: () => void, timeout: NodeJS.Timeout;
function debounce(fn: () => void, ms: number)
{
    debounceFn = fn;
    clearTimeout(timeout);
    timeout = setTimeout(debounceFn, ms);
}
</script>