<template>
  <div
    class="component-wrapper"
    ref="componentWrapperRef"
    :style="warpperStyle"
  >
    <Container v-bind="componentData.container" @click="handleSelectComponent">
      <component
        :is="component"
        v-bind="componentData.props"
        :width="getComponentWidth"
        :height="getComponentHeight"
      />
    </Container>
    <div v-if="showEditBox" class="edit-box" :style="editWapperStyle">
      <span class="name-tip">{{ getTip }}</span>
      <UseDraggable
        v-for="item in dragPointList"
        :key="item"
        @move="(_, e) => handleDragPoint(item, e)"
        @start="handleDragStart"
        @end="handleDragEnd"
      >
        <span
          v-if="!componentData.locked"
          class="edit-box-point"
          :class="item"
        ></span>
      </UseDraggable>
    </div>
  </div>
</template>

<script setup lang="ts">
import type { CustomElement } from "#/project";
import { defineProps, defineAsyncComponent, computed, ref } from "vue";
import { useStageStore } from "@/store/modules/stage";
import { useProjectStore } from "@/store/modules/project";
import { useDraggable } from "@vueuse/core";
import { UseDraggable } from "@vueuse/components";
import { asyncComponentAll } from 'shalu-dashboard-ui';
import Container from "@/components/Container/index.vue";

const { componentData } = defineProps<{ componentData: CustomElement }>();
// 动态引入组件
const component = defineAsyncComponent(
  asyncComponentAll[componentData.componentType]
);

const componentWrapperRef = ref<HTMLElement | null>(null);
const stageStore = useStageStore();
const projectStore = useProjectStore();
const editWapperStyle = computed(() => {
  const { width = 400, height = 260 } = componentData.container.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 getComponentWidth = computed(() => {
  const { width = 400 } = componentData.container.props || {};
  const { paddingLeft = 0, paddingRight = 0 } = componentData.container.props || {};
  return width - paddingLeft - paddingRight;
});

// 组件高--根据边距计算
const getComponentHeight = computed(() => {
  const { height = 260 } = componentData.container.props || {};
  const { paddingTop = 0, paddingBottom = 0 } = componentData.container.props || {};
  return height - paddingTop - paddingBottom;
});

const warpperStyle = computed(() => {
  const {
    width = 400,
    height = 260,
    x,
    y,
  } = componentData.container.props || {};
  // const style = transformStyle(componentData.container?.style || {});
  
  return {
    width: `${width}px`,
    height: `${height}px`,
    left: x + "px",
    top: y + "px",
  };
});
// 是否显示编辑框
const showEditBox = computed(() => {
  return (
    projectStore.mode === "edit" &&
    projectStore.selectedElementKeys.includes(componentData.key)
  );
});
// 获取提示信息
const getTip = computed(() => {
  const { x, y } = componentData.container.props || {};
  return showNameTip.value
    ? componentData.name
    : `x: ${Math.round(x)} y: ${Math.round(y)}`;
});

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

    const originPosition = componentWrapperRef.value!.getBoundingClientRect();
    // 计算移动的距离
    const xMoveLength = position.x - originPosition.left;
    const yMoveLentgh = position.y - originPosition.top;
    const { x, y } = componentData.container.props || {};

    projectStore.updateElement(
      componentData.key,
      "container.props.x",
      Math.round(x + xMoveLength)
    );
    projectStore.updateElement(
      componentData.key,
      "container.props.y",
      Math.round(y + yMoveLentgh)
    );
  },
  onStart: () => {
    projectStore.setSelectedElementKeys([componentData.key]);
    showNameTip.value = false;
  },
  onEnd: () => {
    showNameTip.value = true;
  },
});
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 { x, y, width, height } = componentData.container.props || {};

  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, "container.props.x", Math.round(x));
  projectStore.updateElement(componentData.key, "container.props.y", Math.round(y));
  projectStore.updateElement(componentData.key, "container.props.width", Math.round(width));
  projectStore.updateElement(
    componentData.key,
    "container.props.height",
    Math.round(height)
  );
};
// 拖拽点开始
const handleDragStart = (_: any, e: PointerEvent) => {
  startPoint.x = e.x;
  startPoint.y = e.y;
  isPointDragFlag = true;
  showNameTip.value = false;
};
// 拖拽点结束
const handleDragEnd = () => {
  isPointDragFlag = false;
  showNameTip.value = true;
};
</script>

<style lang="less" scoped>
.component-wrapper {
  position: absolute;
}
.edit-box {
  position: absolute;
  &-point {
    position: absolute;
    width: 8px;
    height: 8px;
    background: #fff;
    border-radius: 50%;
    border: solid 1px @primary-color;
  }
  .name-tip {
    position: absolute;
    top: -20px;
    left: 4px;
    font-size: 12px;
    color: #fff;
    background: @primary-color;
    padding: 2px 4px;
  }
  .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>
