<template>
  <div
    class="component-wrapper"
    ref="componentWrapperRef"
    :style="warpperStyle"
  >
    <div class="component-content" @click="handleSelectComponent">
      <component :is="component" v-bind="componentData.props" />
    </div>
    <div v-if="showEditBox" class="edit-box" :style="editWapperStyle">
      <UseDraggable
        v-for="item in dragPointList"
        :key="item"
        @move="(_, e) => handleDragPoint(item, e)"
        @start="handleDragStart"
        @end="handleDragEnd"
      >
        <span class="edit-box-point" :class="item"></span>
      </UseDraggable>
    </div>
  </div>
</template>

<script setup lang="ts">
import { defineProps, defineAsyncComponent, computed, ref } from "vue";
import componentAll from "@/components";
import type { CustomElement } from "#/project";

import { useStageStore } from "@/store/modules/stage";
import { useProjectStore } from "@/store/modules/project";
import { useDraggable } from "@vueuse/core";
import { UseDraggable } from "@vueuse/components";

const { componentData } = defineProps<{ componentData: CustomElement }>();
// 动态引入组件
const component = defineAsyncComponent(
  componentAll[componentData.componentType]
);
const componentWrapperRef = ref<HTMLElement | null>(null);
const stageStore = useStageStore();
const projectStore = useProjectStore();
const editWapperStyle = computed(() => {
  const { width = 400, height = 260 } = componentData.props || {};
  return {
    transform: `scale(${1 / stageStore.scale})`,
    transformOrigin: "50% 50%",
    width: `${width * stageStore.scale}px`,
    height: `${height * stageStore.scale}px`,
    border: "1px solid #1890ff",
    left: (width / 2) * (1 - stageStore.scale) + "px",
    top: (height / 2) * (1 - stageStore.scale) + "px",
  };
});
const warpperStyle = computed(() => {
  const { width = 400, height = 260 } = componentData.props || {};
  const { position } = componentData || {};
  return {
    width: `${width}px`,
    height: `${height}px`,
    left: position.x + "px",
    top: position.y + "px",
  };
});
// 是否显示编辑框
const showEditBox = computed(() => {
  return (
    projectStore.mode === "edit" &&
    projectStore.selectedElementKeys.includes(componentData.key)
  );
});

let isPointDragFlag = false;
// 拖拽移动组件
useDraggable(componentWrapperRef, {
  onMove: (position) => {
    if(isPointDragFlag) return;

    const originPosition = componentWrapperRef.value!.getBoundingClientRect();
    // 计算移动的距离
    const x = position.x - originPosition.left;
    const y = position.y - originPosition.top;

    projectStore.updateElement(componentData.key, {
      position: {
        x: componentData.position.x + x,
        y: componentData.position.y + y,
      },
    });
  },
  onStart: () => {
    projectStore.setSelectedElementKeys([componentData.key]);
  }
});
const handleSelectComponent = () => {
  projectStore.setSelectedElementKeys([componentData.key]);
};

/* ===============================缩放组件==================================== */
const dragPointList = [
  "top-left",
  "top-center",
  "top-right",
  "left-center",
  "right-center",
  "bottom-left",
  "bottom-center",
  "bottom-right",
];

const startPoint = {
  x: 0,
  y: 0,
};
// 拖拽点移动
const handleDragPoint = (type: string, e: PointerEvent) => {
  const moveX = (e.x - startPoint.x) / stageStore.scale;
  const moveY = (e.y - startPoint.y) / stageStore.scale;
  
  let width = componentData.props.width;
  let height = componentData.props.height;
  let x = componentData.position.x;
  let y = componentData.position.y;

  switch (type) {
    case "top-left":
      width -= moveX;
      height -= moveY;
      x += moveX;
      y += moveY;
      break;
    case "top-center":
      height -= moveY;
      y += moveY;
      break;
    case "top-right":
      width += moveX;
      height -= moveY;
      y += moveY;
      break;
    case "left-center":
      width -= moveX;
      x += moveX;
      break;
    case "right-center":
      width += moveX;
      break;
    case "bottom-left":
      width -= moveX;
      height += moveY;
      x += moveX;
      break;
    case "bottom-center":
      height += moveY;
      break;
    case "bottom-right":
      width += moveX;
      height += moveY;
      break;
  }

  startPoint.x = e.x;
  startPoint.y = e.y;

  if(width < 10 || height < 10) return;

  projectStore.updateElement(componentData.key, {
    position: { x, y },
    props: { 
      ...componentData.props,
      width,
      height,
     },
  });
};
// 拖拽点开始
const handleDragStart = (_, e: PointerEvent) => {
  startPoint.x = e.x;
  startPoint.y = e.y;
  isPointDragFlag = true;
};
// 拖拽点结束
const handleDragEnd = () => {
  isPointDragFlag = false;
};
</script>

<style lang="less" scoped>
.component-wrapper {
  position: absolute;
}
.component-content {
  position: absolute;
  width: 100%;
  height: 100%;
  left: 0;
  top: 0;
}
.edit-box {
  position: absolute;
  &-point {
    position: absolute;
    width: 8px;
    height: 8px;
    background: #fff;
    border-radius: 50%;
    border: solid 1px @primary-color;
  }
  .top-left {
    top: -4px;
    left: -4px;
    cursor: nw-resize;
  }
  .top-center {
    top: -4px;
    left: 50%;
    transform: translateX(-50%);
    transform-origin: center;
    cursor: n-resize;
  }
  .top-right {
    top: -4px;
    right: -4px;
    cursor: ne-resize;
  }
  .left-center {
    top: 50%;
    left: -4px;
    transform: translateY(-50%);
    cursor: w-resize;
  }
  .right-center {
    top: 50%;
    right: -4px;
    transform: translateY(-50%);
    cursor: e-resize;
  }
  .bottom-left {
    bottom: -4px;
    left: -4px;
    cursor: sw-resize;
  }
  .bottom-center {
    bottom: -4px;
    left: 50%;
    transform: translateX(-50%);
    cursor: s-resize;
  }
  .bottom-right {
    bottom: -4px;
    right: -4px;
    cursor: se-resize;
  }
}
</style>
