<template>
  <main class="canvas-area">
    <div class="canvas-shell">
      <div 
        class="canvas" 
        id="canvas"
        :class="{ 'grid-off': !store.showGrid }"
        :style="canvasStyle"
        @click.self="deselect"
      >
        <WidgetElement 
          v-for="widget in rootWidgets"
          :key="widget.id"
          :widget="widget"
          :scale="store.canvasScale"
          :selected="store.selectedWidgetId === widget.id"
          @select="store.selectedWidgetId = widget.id"
          @drag-start="startDrag($event)"
          @resize-start="startResize($event)"
        />
      </div>
    </div>
  </main>
</template>

<script setup>
import { computed, onMounted, onUnmounted, ref } from 'vue';
import { useEditorStore } from '../stores/editor';
import WidgetElement from './WidgetElement.vue';
import { DISPLAY_W, DISPLAY_H, WIDGET_TYPES } from '../constants';
import { clamp, minSizeFor } from '../utils';

const store = useEditorStore();

const rootWidgets = computed(() => {
    return store.activeScreen?.widgets.filter(w => w.parentId === -1) || [];
});

const canvasW = computed(() => {
    if (store.activeScreen?.mode === 1) { // Modal
        return store.activeScreen.modal.w || DISPLAY_W;
    }
    return DISPLAY_W;
});

const canvasH = computed(() => {
    if (store.activeScreen?.mode === 1) { // Modal
        return store.activeScreen.modal.h || DISPLAY_H;
    }
    return DISPLAY_H;
});

const canvasStyle = computed(() => ({
    width: `${canvasW.value * store.canvasScale}px`,
    height: `${canvasH.value * store.canvasScale}px`,
    '--canvas-bg': store.activeScreen?.bgColor || '#1A1A2E',
    '--grid-size': `${store.gridSize * store.canvasScale}px`
}));

function deselect() {
    store.selectedWidgetId = null;
}

function snap(val) {
    if (!store.snapToGrid) return val;
    const s = store.gridSize;
    return Math.round(val / s) * s;
}

let dragState = null;
let resizeState = null;

function startDrag(payload) {
    const { id, event: e } = payload;
    if (e.target.closest('.resize-handle')) return;
    e.preventDefault();
    store.selectedWidgetId = id;

    const cx = e.touches ? e.touches[0].clientX : e.clientX;
    const cy = e.touches ? e.touches[0].clientY : e.clientY;

    const widget = store.activeScreen.widgets.find(w => w.id === id);
    if (!widget) return;

    dragState = {
        id,
        startX: cx,
        startY: cy,
        origX: widget.x,
        origY: widget.y
    };
    resizeState = null;

    document.addEventListener('mousemove', drag);
    document.addEventListener('mouseup', endDrag);
    document.addEventListener('touchmove', drag, { passive: false });
    document.addEventListener('touchend', endDrag);
}

function drag(e) {
    if (!dragState) return;
    e.preventDefault();

    const cx = e.touches ? e.touches[0].clientX : e.clientX;
    const cy = e.touches ? e.touches[0].clientY : e.clientY;

    const dx = (cx - dragState.startX) / store.canvasScale;
    const dy = (cy - dragState.startY) / store.canvasScale;

    const w = store.activeScreen.widgets.find(x => x.id === dragState.id);
    if (w) {
        let nx = dragState.origX + dx;
        let ny = dragState.origY + dy;

        if (store.snapToGrid) {
            nx = snap(nx);
            ny = snap(ny);
        }

        // Determine bounds
        let maxW = canvasW.value;
        let maxH = canvasH.value;
        
        if (w.parentId !== -1) {
            const parent = store.activeScreen.widgets.find(p => p.id === w.parentId);
            if (parent) {
                if (parent.type === WIDGET_TYPES.TABPAGE) {
                    // Parent is a TabPage (w=0, h=0), so look at grandparent (TabView)
                    const grandParent = store.activeScreen.widgets.find(gp => gp.id === parent.parentId);
                    if (grandParent) {
                        maxW = grandParent.w;
                        maxH = grandParent.h;
                        // Adjust for tab bar? For simplicity use full size for now
                    }
                } else {
                    maxW = parent.w;
                    maxH = parent.h;
                }
            }
        }

        w.x = Math.max(0, Math.min(maxW - w.w, Math.round(nx)));
        w.y = Math.max(0, Math.min(maxH - w.h, Math.round(ny)));
    }
}

function endDrag() {
    dragState = null;
    document.removeEventListener('mousemove', drag);
    document.removeEventListener('mouseup', endDrag);
    document.removeEventListener('touchmove', drag);
    document.removeEventListener('touchend', endDrag);
}

function startResize(payload) {
    const { id, event: e } = payload;
    e.preventDefault();
    store.selectedWidgetId = id;

    const cx = e.touches ? e.touches[0].clientX : e.clientX;
    const cy = e.touches ? e.touches[0].clientY : e.clientY;

    const widget = store.activeScreen.widgets.find(w => w.id === id);
    if (!widget) return;

    resizeState = {
        id,
        startX: cx,
        startY: cy,
        origW: widget.w,
        origH: widget.h
    };
    dragState = null;

    document.addEventListener('mousemove', resizeDrag);
    document.addEventListener('mouseup', endResize);
    document.addEventListener('touchmove', resizeDrag, { passive: false });
    document.addEventListener('touchend', endResize);
}

function resizeDrag(e) {
    if (!resizeState) return;
    e.preventDefault();

    const cx = e.touches ? e.touches[0].clientX : e.clientX;
    const cy = e.touches ? e.touches[0].clientY : e.clientY;

    const dx = (cx - resizeState.startX) / store.canvasScale;
    const dy = (cy - resizeState.startY) / store.canvasScale;

    const w = store.activeScreen.widgets.find(x => x.id === resizeState.id);
    if (!w) return;

    const minSize = minSizeFor(w);
    const maxW = canvasW.value - w.x;
    const maxH = canvasH.value - w.y;

    let rawW = resizeState.origW + dx;
    let rawH = resizeState.origH + dy;

    if (store.snapToGrid) {
        rawW = snap(rawW);
        rawH = snap(rawH);
    }

    let newW = Math.round(rawW);
    let newH = Math.round(rawH);

    if (w.type === WIDGET_TYPES.LED) {
        const maxSize = Math.min(maxW, maxH);
        const size = clamp(Math.max(newW, newH), minSize.w, maxSize);
        newW = size;
        newH = size;
    } else {
        newW = clamp(newW, minSize.w, maxW);
        newH = clamp(newH, minSize.h, maxH);
    }

    w.w = newW;
    w.h = newH;
}

function endResize() {
    resizeState = null;
    document.removeEventListener('mousemove', resizeDrag);
    document.removeEventListener('mouseup', endResize);
    document.removeEventListener('touchmove', resizeDrag);
    document.removeEventListener('touchend', endResize);
}
</script>
