<script lang="ts" setup>
import { ComponentPublicInstance, ref } from 'vue'
import { useContext, useParentViewDOMRect, useScale } from '../context'
import { DddView } from '../views'
import DddCanvas from './Canvas.vue'

defineOptions({
  name: 'DddDesigner',
})

const ctx = useContext()
const scale = useScale()

let pageX = 0
let pageY = 0

const canMove = ref(false)
const x = ref((window.innerWidth - 375 - 324) / 2 + 324)
const y = ref(24)

function onMousedown(e: MouseEvent): void {
  canMove.value = true
  pageX = e.pageX - x.value
  pageY = e.pageY - y.value

  ctx.activeBlockId = undefined
  ctx.activeViewId = undefined
  ctx.configurator = undefined
  ctx.canvas.focused = true
}

function onMousemove(e: MouseEvent): void {
  if (canMove.value) {
    x.value = e.pageX - pageX!
    y.value = e.pageY - pageY!
  }
}

function onMouseup(): void {
  canMove.value = false
}

function onMousewheel(e: WheelEvent): void {
  if (e.ctrlKey || e.metaKey) {
    if (e.deltaY < 0) {
      scale.incr()
    } else {
      scale.decr()
    }
  } else {
    x.value -= e.deltaX
    y.value -= e.deltaY
  }
}

const canvasRef = ref<HTMLElement | null>(null)
const domRect = useParentViewDOMRect()

const setCanvasRef = (a: ComponentPublicInstance) => {
  canvasRef.value = a?.$el ?? null
}

// TODO(hupeh): 不使用 Vue 更新相关鼠标移入移出的效果，防止频繁更新视图
function onMouseover(e: MouseEvent): void {
  if (!ctx.draggingViewId) {
    let el = e.target as HTMLElement | null | undefined
    while (el) {
      const widgetId = (el as HTMLElement)?.dataset?.viewId
      if (widgetId && widgetId !== ctx.activeViewId) {
        ctx.hoverViewId = widgetId
        Object.assign(domRect, el.getBoundingClientRect().toJSON())
        return
      }
      el = el?.parentNode as HTMLElement
    }
    ctx.hoverViewId = '#canvas'
    Object.assign(domRect, canvasRef.value!.getBoundingClientRect())
  }
}
</script>

<template>
  <div
    class="ddd-designer"
    @mouseleave="onMouseup"
    @mousemove="onMousemove"
    @mouseup="onMouseup"
    @mousedown.left="onMousedown"
    @wheel.passive="onMousewheel"
  >
    <DddView
      :is="DddCanvas"
      :style="`transform: translate(${x}px,${y}px) scale(${ctx.canvas.scale})`"
      :ref="setCanvasRef"
      vid="#canvas"
      @mouseover="onMouseover"
      @mousedown.stop
      @mousemove.stop
    />
  </div>
</template>

<style lang="less" scoped>
.ddd-designer {
  z-index: 1;
  position: relative;
  width: 100%;
  height: 100%;
  background-color: #eee;
}
</style>
