<!-- 主画布 -->
<script setup lang="ts">
import { createNode, getMaterialComponent } from '@/materials'
import type { MaterialSchema } from '@/schema/materials'
import { useEditorStore } from '@/stores/editor'
import { storeToRefs } from 'pinia'
import Moveable from 'vue3-moveable'
import { VueSelecto } from 'vue3-selecto'
import SketchRuler from 'vue3-sketch-ruler'
import 'vue3-sketch-ruler/lib/style.css'
import { useCanvasRuler } from './composables/useCanvasRuler'
import { useMoveable } from './composables/useMoveable'
import { useSelection } from './composables/useSelection'

defineOptions({
  name: 'CanvasRoot',
})

const editorStore = useEditorStore()
const { nodes, canvas } = storeToRefs(editorStore)

const moveableRef = useTemplateRef('moveableRef')
const stageRef = useTemplateRef('stageRef')
// canvas容器的ref
const canvasRootRef = ref<HTMLElement | null>(null)

const { RULER_THICK, scale, lines, rulerCanvasSize, viewportSize, palette, onZoomChange } =
  useCanvasRuler(moveableRef, canvasRootRef)
const { onDrag, onResize, onDragGroup, onResizeGroup, onStart, onEnd } = useMoveable(moveableRef)
const { selectedTarget, onSelect, onClearSelect, onSelectEnd } = useSelection(stageRef, moveableRef)

/** 设计稿白底：宽高和背景色立刻跟 store */
const canvasStyle = computed(() => {
  return {
    width: canvas.value.width,
    height: canvas.value.height,
    backgroundColor: canvas.value.backgroundColor,
  }
})

// 获取节点的样式
const getNodeStyle = (node: MaterialSchema, zIndex: number) => {
  return {
    width: `${node.layout.width}px`,
    height: `${node.layout.height}px`,
    left: `${node.layout.x}px`,
    top: `${node.layout.y}px`,
    zIndex: zIndex + 1,
  }
}

// 拖拽放置节点
const onDrop = (e: DragEvent) => {
  const data = e.dataTransfer?.getData('schema')
  if (data) {
    const node = createNode(JSON.parse(data))
    node.layout.x = e.offsetX - node.layout.width / 2
    node.layout.y = e.offsetY - node.layout.height / 2

    editorStore.addNode(node)
    editorStore.selectNode(node.id)
  }
}

// 右键菜单操作映射
const commendMap = {
  copy: () => editorStore.selectedNode && editorStore.copyNode(editorStore.selectedNode),
  remove: () => editorStore.selectedNode && editorStore.removeNode(editorStore.selectedNode),
  moveBottom: () => editorStore.selectedNode && editorStore.moveTop(editorStore.selectedNode), // 列表渲染时反转了，这里也反转操作
  moveTop: () => editorStore.selectedNode && editorStore.moveBottom(editorStore.selectedNode),
  toggleLock: () => {
    if (editorStore.selectedNode) {
      editorStore.toggleLock(editorStore.selectedNode)
    }
    selectedTarget.value = []
  },
}

// 右键菜单操作
const onCommand = (command: keyof typeof commendMap) => {
  commendMap[command]?.()
}
</script>

<template>
  <div ref="canvasRootRef" class="relative h-full w-full min-h-0 min-w-0 overflow-hidden isolate">
    <SketchRuler
      v-if="viewportSize.width && viewportSize.height"
      :palette="palette"
      :thick="RULER_THICK"
      :width="viewportSize.width"
      :height="viewportSize.height"
      :canvas-width="rulerCanvasSize.width"
      :canvas-height="rulerCanvasSize.height"
      :scale="scale"
      :lines="lines"
      @zoomchange="onZoomChange"
    >
      <div
        ref="stageRef"
        class="relative"
        :style="{
          width: `${canvasStyle.width}px`,
          height: `${canvasStyle.height}px`,
          backgroundColor: canvasStyle.backgroundColor,
        }"
        @dragover.prevent
        @drop="onDrop"
        @mousedown.self="onClearSelect"
      >
        <el-dropdown
          v-for="(node, index) in nodes"
          :key="node.id"
          trigger="contextmenu"
          @command="onCommand"
        >
          <div
            :data-node-id="node.id"
            :data-node-locked="node.locked"
            class="canvas-node absolute"
            :style="getNodeStyle(node, index)"
            @mousedown="onSelect(node)"
          >
            <component :is="getMaterialComponent(node.type)" :schema="node" />
          </div>

          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item command="copy">复制</el-dropdown-item>
              <el-dropdown-item command="remove">移除</el-dropdown-item>
              <el-dropdown-item command="moveTop">置顶</el-dropdown-item>
              <el-dropdown-item command="moveBottom">置底</el-dropdown-item>
              <el-dropdown-item command="toggleLock">
                {{ node.locked ? '解锁' : '锁定' }}
              </el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
      </div>
    </SketchRuler>

    <VueSelecto
      v-if="stageRef"
      :container="stageRef"
      :dragContainer="stageRef"
      :select-from-inside="false"
      :selectableTargets="['.canvas-node']"
      toggle-continue-select="shift"
      @selectEnd="onSelectEnd"
    />
    <Moveable
      ref="moveableRef"
      :target="selectedTarget"
      :draggable="true"
      :resizable="true"
      :origin="false"
      @drag="onDrag"
      @drag-start="onStart"
      @drag-end="onEnd"
      @drag-group="onDragGroup"
      @drag-group-start="onStart"
      @drag-group-end="onEnd"
      @resize="onResize"
      @resize-start="onStart"
      @resize-end="onEnd"
      @resize-group="onResizeGroup"
      @resize-group-start="onStart"
      @resize-group-end="onEnd"
    />
  </div>
</template>

<style scoped></style>
