<script lang="ts">
type Direction = 'bottom' | 'top' | 'left' | 'right';
const rotation: Record<Direction, string> = {
    top: "180",
    bottom: "0",
    left: "90",
    right: "270"
};
</script>

<script setup lang="ts">
import { useDrag, useHover, usePinch, useWheel } from '@vueuse/gesture';
import { Icon } from '@iconify/vue/dist/iconify.js';
import { clamp } from '#shared/general.utils';
import type { CanvasContent, CanvasEdge, CanvasNode } from '~/types/canvas';
import { labelCenter, getPath } from '#shared/canvas.util';
import FakeA from './prose/FakeA.vue';

const { canvas } = defineProps<{
    canvas: CanvasContent
}>();

const dispX = ref(0), dispY = ref(0), minZoom = ref(0.1), zoom = ref(0.5);
const focusing = ref<CanvasNode | CanvasEdge>(), editing = ref<CanvasNode | CanvasEdge>();
const canvasRef = useTemplateRef('canvasRef');

const nodes = computed(() => {
    return canvas.nodes.map(e => ({ ...e, class: e.color ? e.color?.class ? 
        { bg: `bg-light-${e.color?.class} dark:bg-dark-${e.color?.class}`, border: `border-light-${e.color?.class} dark:border-dark-${e.color?.class}`, outline: `outline-light-${e.color?.class} dark:outline-dark-${e.color?.class}` } : 
        { bg: `bg-colored`, border: `border-[color:var(--canvas-color)]`, outline: `outline-[color:var(--canvas-color)]` } : 
        { border: `border-light-40 dark:border-dark-40`, bg: `bg-light-40 dark:bg-dark-40`, outline: `outline-light-40 dark:outline-dark-40` } }))
})
const edges = computed(() => {
    return canvas.edges.map(e => { 
        const from = canvas.nodes.find(f => f.id === e.fromNode), to = canvas.nodes.find(f => f.id === e.toNode);
        const path = getPath(from!, e.fromSide, to!, e.toSide)!;
        return { ...e, from, to, path };
    });
})

const reset = (_: MouseEvent) => {
    zoom.value = minZoom.value; 

    dispX.value = 0; 
    dispY.value = 0;
}

const cancelEvent = (e: Event) => e.preventDefault()
useHover(({ hovering }) => {
    if (!hovering) {
        //@ts-ignore
        window.removeEventListener('wheel', cancelEvent, { passive: false });
        document.removeEventListener('gesturestart', cancelEvent)
        document.removeEventListener('gesturechange', cancelEvent)
        return
    }
    
    window.addEventListener('wheel', cancelEvent, { passive: false });
    document.addEventListener('gesturestart', cancelEvent)
    document.addEventListener('gesturechange', cancelEvent)
}, {
    domTarget: canvasRef,
});

const dragHandler = useDrag(({ delta: [x, y] }: { delta: number[] }) => { 
    if(editing.value === undefined)
    {
        dispX.value += x / zoom.value;
        dispY.value += y / zoom.value;
    }
}, {
    useTouch: true,
    domTarget: canvasRef,
});
const wheelHandler = useWheel(({ delta: [x, y] }: { delta: number[] }) => {
    if(editing.value === undefined)
    {
        zoom.value = clamp(zoom.value + y * -0.001, minZoom.value, 3);
    }
}, {
    eventOptions: {
        capture: true,
    },
    domTarget: canvasRef,
});
const pinchHandler = usePinch(({ offset: [z] }: { offset: number[] }) => {
    if(editing.value === undefined)
    {
        zoom.value = clamp(z / 2048, minZoom.value, 3);
    }
}, {
    domTarget: canvasRef,
});
</script>

<template>
    <div ref="canvasRef" class="absolute top-0 left-0 overflow-hidden w-full h-full touch-none" :style="{ '--zoom-multiplier': (1 / Math.pow(zoom, 0.7)) }" @click.self="() => { focusing = undefined; editing = undefined; }">
        <div class="flex flex-col absolute sm:top-2 top-10 left-2 z-[35] overflow-hidden gap-4">
            <div class="border border-light-35 dark:border-dark-35 bg-light-10 dark:bg-dark-10">
                <Tooltip message="Zoom avant" side="right">
                    <div @click="zoom = clamp(zoom * 1.1, minZoom, 3)" class="w-8 h-8 flex justify-center items-center p-2 hover:bg-light-30 dark:hover:bg-dark-30 cursor-pointer">
                        <Icon icon="radix-icons:plus" />
                    </div>
                </Tooltip>
                <Tooltip message="Reset" side="right">
                    <div @click="zoom = 1" class="w-8 h-8 flex justify-center items-center p-2 hover:bg-light-30 dark:hover:bg-dark-30 cursor-pointer">
                        <Icon icon="radix-icons:reload" />
                    </div>
                </Tooltip>
                <Tooltip message="Tout contenir" side="right">
                    <div @click="reset" class="w-8 h-8 flex justify-center items-center p-2 hover:bg-light-30 dark:hover:bg-dark-30 cursor-pointer">
                        <Icon icon="radix-icons:corners" />
                    </div>
                </Tooltip>
                <Tooltip message="Zoom arrière" side="right">
                    <div @click="zoom = clamp(zoom * 0.9, minZoom, 3)" class="w-8 h-8 flex justify-center items-center p-2 hover:bg-light-30 dark:hover:bg-dark-30 cursor-pointer">
                        <Icon icon="radix-icons:minus" />
                    </div>
                </Tooltip>
            </div>
            <div class="border border-light-35 dark:border-dark-35 bg-light-10 dark:bg-dark-10">
                <Tooltip message="Aide" side="right">
                    <Dialog title="Aide" iconClose>
                        <template #trigger>
                            <div class="w-8 h-8 flex justify-center items-center p-2 hover:bg-light-30 dark:hover:bg-dark-30 cursor-pointer">
                                <Icon icon="radix-icons:question-mark-circled" />
                            </div>
                        </template>
                        <template #default>
                            <div class="flex items-center"><Icon icon="ph:mouse-left-click-fill" class="w-6 h-6"/>: Selectionner</div>
                            <div class="flex items-center"><Icon icon="ph:mouse-middle-click-fill" class="w-6 h-6"/>: Déplacer</div>
                            <div class="flex items-center"><Icon icon="ph:mouse-right-click-fill" class="w-6 h-6"/>: Menu</div>
                        </template>
                    </Dialog>
                </Tooltip>
            </div>
        </div>
<!--         <ContextMenuRoot>
            <ContextMenuTrigger asChild> -->
                <div :style="{
                    '--tw-translate-x': `${dispX}px`,
                    '--tw-translate-y': `${dispY}px`,
                    '--tw-scale-x': `${zoom}`,
                    '--tw-scale-y': `${zoom}`,
                    transform: 'scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)) translate3d(var(--tw-translate-x), var(--tw-translate-y), 0)'
                }">
                    <div class="absolute top-0 left-0 w-full h-full origin-center pointer-events-none *:pointer-events-auto *:select-none touch-none">
                        <div>
                            <div v-for="node of nodes" :key="node.id" class="absolute" :style="{transform: `translate(${node.x}px, ${node.y}px)`, width: `${node.width}px`, height: `${node.height}px`, '--canvas-color': node.color?.hex}" :class="{'-z-10': node.type === 'group', 'z-10': node.type !== 'group'}">
                                <div v-if="editing?.id !== node.id" style="outline-style: solid;" :class="[node.class.border, node.class.outline, { '!outline-4': focusing?.id === node.id }]" class="outline-0 transition-[outline-width] border-2 bg-light-20 dark:bg-dark-20 overflow-hidden contain-strict w-full h-full flex" @click.left="() => { focusing = node; editing = undefined; }" @dblclick="() => { if(node.type === 'text') editing = node; }">
                                    <div class="w-full h-full py-2 px-4 flex !bg-opacity-[0.07]" :class="node.class.bg">
                                        <div v-if="node.text?.length > 0" class="flex items-center">
                                            <MarkdownRenderer :content="node.text" :proses="{ a: FakeA }" />
                                        </div>
                                    </div>
                                </div>
                                <div v-else style="outline-style: solid;" :class="[node.class.border, node.class.outline, { '!outline-4': focusing?.id === node.id }]" class="outline-0 transition-[outline-width] border-2 bg-light-20 dark:bg-dark-20 overflow-hidden contain-strict w-full h-full flex" >
                                    <Editor v-model="node.text" />
                                </div>
                                <div v-if="node.type === 'group' && node.label !== undefined" :class="node.class.border" style="max-width: 100%; font-size: calc(18px * var(--zoom-multiplier))" class="origin-bottom-left tracking-wider border-4 truncate inline-block text-light-100 dark:text-dark-100 absolute bottom-[100%] mb-2 px-2 py-1 font-thin">{{ node.label }}</div>
                            </div>
                        </div>
                        <template v-for="edge of edges">
                            <div :key="edge.id" v-if="edge.label" class="absolute z-10"
                                :style="{ transform: labelCenter(edge.from!, edge.fromSide, edge.to!, edge.toSide) }">
                                <div class="relative bg-light-20 dark:bg-dark-20 border border-light-35 dark:border-dark-35 px-4 py-2 -translate-x-[50%] -translate-y-[50%]">{{ edge.label }}</div>
                            </div>
                        </template>
                        <svg class="absolute top-0 left-0 overflow-visible w-full h-full origin-top pointer-events-none">
                            <g v-for="edge of edges" :key="edge.id" :style="{'--canvas-color': edge.color?.hex}" class="z-0">
                                <path :style="`stroke-linecap: butt; stroke-width: calc(3px * var(--zoom-multiplier));`" :class="edge.color?.class ? `stroke-light-${edge.color.class} dark:stroke-dark-${edge.color.class}` : ((edge.color && edge.color?.hex !== undefined) ? 'stroke-[color:var(--canvas-color)]' : 'stroke-light-40 dark:stroke-dark-40')" class="fill-none stroke-[4px]" :d="edge.path.path"></path>
                                <g :style="`transform: translate(${edge.path.to.x}px, ${edge.path.to.y}px) scale(var(--zoom-multiplier)) rotate(${rotation[edge.path.side]}deg);`">
                                    <polygon :class="edge.color?.class ? `fill-light-${edge.color.class} dark:fill-dark-${edge.color.class}` : ((edge.color && edge.color?.hex !== undefined) ? 'fill-[color:var(--canvas-color)]' : 'fill-light-40 dark:fill-dark-40')" points="0,0 6.5,10.4 -6.5,10.4"></polygon>
                                </g>
                            </g>
                        </svg>
                    </div>
                </div><!-- 
            </ContextMenuTrigger>
            <ContextMenuPortal>
                <ContextMenuContent>
                    <ContextMenuItem @select="(e) => canvas.nodes.push({ id: useId(), })" >Nouveau</ContextMenuItem>
                </ContextMenuContent>
            </ContextMenuPortal>
        </ContextMenuRoot> -->
    </div>
</template>