<template>
    <div class="absolute overflow-visible group" :class="{ 'z-[1]': focusing }">
        <input v-autofocus v-if="editing" @click="e => e.stopImmediatePropagation()" :style="{ transform: `${labelPos} translate(-50%, -50%)` }" class="relative bg-light-20 dark:bg-dark-20 border border-light-35 dark:border-dark-35 px-4 py-2 z-20" v-model="edge.label" />
        <div v-else-if="edge.label" :style="{ transform: `${labelPos} translate(-50%, -50%)` }" class="relative bg-light-20 dark:bg-dark-20 border border-light-35 dark:border-dark-35 px-4 py-2 z-20" @click.left="select" @dblclick.left="edit">{{ edge.label }}</div>
        <svg ref="dom" class="absolute top-0 overflow-visible h-px w-px">
            <g :style="{'--canvas-color': edge.color?.hex}" class="z-0">
                <g :style="`transform: translate(${path.to.x}px, ${path.to.y}px) scale(var(--zoom-multiplier)) rotate(${rotation[path.side]}deg);`">
                    <polygon :class="style.fill" points="0,0 6.5,10.4 -6.5,10.4"></polygon>
                </g>
                <path :style="`stroke-width: calc(${focusing ? 6 : 3}px * var(--zoom-multiplier));`" style="stroke-linecap: butt;" :class="style.stroke" class="transition-[stroke-width] fill-none stroke-[4px]" :d="path.path"></path>
                <path style="stroke-width: calc(22px * var(--zoom-multiplier));" class="fill-none transition-opacity z-30 opacity-0 hover:opacity-25" :class="[style.stroke, { 'opacity-25': focusing }]" :d="path.path" @click="select" @dblclick="edit"></path>
            </g>
        </svg>
        <span v-if="focusing && !editing" :style="`transform: translate(${path.from.x}px, ${path.from.y}px) translate(-50%, -50%) scale(var(--zoom-multiplier))`" @mousedown.left="(e) => dragEdge(e, 'from')" :class="style.fill" class="hidden group-hover:block z-[31] absolute rounded-full border-2 border-light-70 dark:border-dark-70 bg-light-30 dark:bg-dark-30 w-6 h-6"></span>
        <span v-if="focusing && !editing" :style="`transform: translate(${path.to.x}px, ${path.to.y}px) translate(-50%, -50%) scale(var(--zoom-multiplier))`" @mousedown.left="(e) => dragEdge(e, 'to')" :class="style.fill" class="hidden group-hover:block z-[31] absolute rounded-full border-2 border-light-70 dark:border-dark-70 bg-light-30 dark:bg-dark-30 w-6 h-6"></span>
    </div>
</template>

<style>
.fill-colored
{
    --tw-bg-opacity: 1;
    fill: rgba(from var(--canvas-color) r g b / var(--tw-bg-opacity));
}
</style>
<script setup lang="ts">
import { getPath, labelCenter, rotation } from '#shared/canvas.util';
import type { Element } from '../CanvasEditor.vue';
import type { CanvasEdge, CanvasNode } from '~/types/canvas';

const { edge, nodes } = defineProps<{
    edge: CanvasEdge
    nodes: CanvasNode[]
}>();

const emit = defineEmits<{
    (e: 'select', id: Element): void,
    (e: 'edit', id: Element): void,
    (e: 'drag', id: string, _e: MouseEvent, origin: 'from' | 'to'): void,
    (e: 'input', id: string, text?: string): void,
}>();

const dom = useTemplateRef('dom');
const focusing = ref(false), editing = ref(false);

const from = computed(() => nodes!.find(f => f.id === edge.fromNode));
const to = computed(() => nodes!.find(f => f.id === edge.toNode));
const path = computed(() => getPath(from.value!, edge.fromSide, to.value!, edge.toSide)!);
const labelPos = computed(() => labelCenter(from.value!, edge.fromSide, to.value!, edge.toSide));

let oldText = edge.label;

function select(e: Event) {
    if(editing.value)
        return;

    focusing.value = true;
    emit('select', { type: 'edge', id: edge.id });
}
function edit(e: Event) {
    oldText = edge.label;

    focusing.value = true;
    editing.value = true;

    e.stopImmediatePropagation();
    emit('edit', { type: 'edge', id: edge.id });
}
function dragEdge(e: MouseEvent, origin: 'from' | 'to') {
    e.stopImmediatePropagation();

    emit('drag', edge.id, e, origin);
}
function unselect() {
    if(editing.value)
    {
        const text = edge.label;
        
        if(text !== oldText)
        {
            edge.label = oldText;

            emit('input', edge.id, text);
        }
    }
    focusing.value = false;
    editing.value = false;
}

defineExpose({ unselect, dom, id: edge.id, path });

const style = computed(() => {
    return edge.color ? edge.color?.class ? 
        { fill: `fill-light-${edge.color?.class} dark:fill-dark-${edge.color?.class}`, stroke: `stroke-light-${edge.color?.class} dark:stroke-dark-${edge.color?.class}`, outline: `outline-light-${edge.color?.class} dark:outline-dark-${edge.color?.class}` } : 
        { fill: `fill-colored`, stroke: `stroke-[color:var(--canvas-color)]`, outline: `outline-[color:var(--canvas-color)]` } : 
        { stroke: `stroke-light-40 dark:stroke-dark-40`, fill: `fill-light-40 dark:fill-dark-40`, outline: `outline-light-40 dark:outline-dark-40` }
});
</script>