<template>
  <div
    ref="boxRef"
    style="width: 100%; height: 100%; position: relative;"
    @mousedown="handleMouseDown"
    @mousemove="handleMouseMove"
    @mouseup="handleMouseUp"
  >
    <Flex class="workspace" vertical>
      <div class="workspace-top">
        <Stage ref="stageRef" />
        <Scaleplate />
      </div>
      <Flex class="workspace-bottom" justify="space-between" align="center">
        <div class="bottom-left">
          <span style="margin-right: 12px"
            >画布尺寸：{{ projectStore.projectInfo.width }} *
            {{ projectStore.projectInfo.height }}px</span
          >
          <span
            >画布自适应：<Select
              size="small"
              style="width: 120px"
              :value="projectStore.projectInfo.fillType"
              :options="fillOptions"
              @change="projectStore.setFillType"
          /></span>
        </div>
        <div class="bottom-right">
          <Button
            size="small"
            type="text"
            :disabled="stageStore.scale <= 0.1"
            @click="handleSizeChange(Number(stageStore.scale) - 0.1)"
            ><MinusCircleOutlined
          /></Button>
          <AutoComplete
            size="small"
            style="width: 120px"
            :options="sizeOptions"
            :value="(stageStore.scale * 100).toFixed(0) + '%'"
            @change="handleSizeChange"
          />
          <Button
            size="small"
            type="text"
            :disabled="stageStore.scale >= 4"
            @click="handleSizeChange(Number(stageStore.scale) + 0.1)"
            ><PlusCircleOutlined
          /></Button>
        </div>
      </Flex>
    </Flex>
    <div class="selectBox" ref="selectBoxRef"></div>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";
import { Button, Select, AutoComplete, Flex } from "ant-design-vue";
import { MinusCircleOutlined, PlusCircleOutlined } from "@ant-design/icons-vue";
import Scaleplate from "./Scaleplate.vue";
import Stage from "./Stage.vue";
import { useProjectStore } from "@/store/modules/project";
import { useStageStore } from "@/store/modules/stage";
import { ScreenFillEnum } from "@/enum/screenFillEnum";
import { throttle } from "lodash";

const projectStore = useProjectStore();
const stageStore = useStageStore();
const stageRef = ref<{getPosition: HTMLElement['getBoundingClientRect']} | null>();

const sizeOptions = [
  { value: 0.1, label: "10%" },
  { value: 0.25, label: "25%" },
  { value: 0.5, label: "50%" },
  { value: 0.75, label: "75%" },
  { value: 1, label: "100%" },
  { value: 1.25, label: "125%" },
  { value: 1.5, label: "150%" },
  { value: 2, label: "200%" },
  { value: 3, label: "300%" },
  { value: 4, label: "400%" },
  { value: 0, label: "适应大小" },
];

const fillOptions = [
  { value: ScreenFillEnum.AUTO, label: "自动" },
  { value: ScreenFillEnum.FILL_HEIGHT, label: "宽度填充" },
  { value: ScreenFillEnum.FILL_WIDTH, label: "高度填充" },
  { value: ScreenFillEnum.FILL_BOTH, label: "双向铺满" },
  { value: ScreenFillEnum.NONE, label: "无" },
];

const handleSizeChange = (val: any) => {
  if (Number.isFinite(val)) {
    // 为0时为自动适应大小
    if(val === 0) {
      stageStore.setScale(0);
      return;
    }
    stageStore.setScale((val as number) < 0.1 ? 0.1 : val);
  }
  if (typeof val === "string") {
    const n = +(val + "").replace("%", "");
    if (Number.isNaN(n) && n >= 10 && n <= 400) {
      stageStore.setScale((n / 100).toFixed(2) as unknown as number);
    } else {
      stageStore.setScale(0.1);
    }
  }
};

/* ====================处理框选多个组件======================== */
const selectBoxRef = ref<HTMLElement | null>(null);
const boxRef = ref<HTMLElement | null>(null);
let isMouseDown = ref(false);
let startX = 0; // 框选起始x坐标
let startY = 0; // 框选起始y坐标
let workspaceLeft = 0;
let workspaceTop = 0;
// 鼠标按下
const handleMouseDown = (e: MouseEvent) => {
  if (
    e?.target?.closest(".edit-box") ||
    e?.target?.closest(".component-content") ||
    e?.target?.closest(".component-wrapper") ||
    e?.target?.closest(".scaleplate-horizontal") ||
    e?.target?.closest(".scaleplate-vertical") ||
    e?.target?.closest(".refer-line-img") ||
    e?.target?.closest(".workspace-bottom") ||
    e?.target?.closest(".refer-line")
  ) {
    return;
  }
  
  const { top, left } = boxRef.value!.getBoundingClientRect();
  const { clientX, clientY } = e;
  isMouseDown.value = true;
  workspaceLeft = left;
  workspaceTop = top;
  startX = clientX - left;
  startY = clientY - top;
  selectBoxRef.value!.style.display = "block";
  selectBoxRef.value!.style.left = `${startX}px`;
  selectBoxRef.value!.style.top = `${startY}px`;
};
/* 鼠标移动 */
const handleMouseMove = throttle((e: MouseEvent) => {
  if (!isMouseDown.value) return;
  const { clientX, clientY } = e;
  const width = clientX - workspaceLeft - startX;
  const height = clientY - workspaceTop - startY;

  const left = width > 0 ? startX : clientX - workspaceLeft;
  const top = height > 0 ? startY : clientY - workspaceTop;

  selectBoxRef.value!.style.width = `${Math.abs(width)}px`;
  selectBoxRef.value!.style.height = `${Math.abs(height)}px`;
  selectBoxRef.value!.style.left = `${left}px`;
  selectBoxRef.value!.style.top = `${top}px`;
}, 50);
/* 鼠标抬起 */
const handleMouseUp = (e: MouseEvent) => {
  if (!isMouseDown || (startX === 0 && startY === 0)) return;

  isMouseDown.value = false;
  selectBoxRef.value!.style.display = "none";
  selectBoxRef.value!.style.width = "0";
  selectBoxRef.value!.style.height = "0";

  const { clientX, clientY } = e;
  const { left: stageLeft = 0, top: stageTop = 0} = stageRef.value?.getPosition() || {};

  // 框选的起始位置
  const x1 = (Math.min(startX + workspaceLeft, clientX) - stageLeft) / stageStore.scale;
  const y1 = (Math.min(startY + workspaceTop, clientY) - stageTop) / stageStore.scale;
  // 框选的结束位置
  const x2 = (Math.max(startX + workspaceLeft, clientX) - stageLeft) / stageStore.scale;
  const y2 = (Math.max(startY + workspaceTop, clientY) - stageTop) / stageStore.scale;
  handleSelectComponent(x1, y1, x2, y2);

  // 清空临时数据
  startX = startY = workspaceLeft = workspaceTop = 0;
};
/* 处理框选的组件 */
const handleSelectComponent = (startX: number, startY: number, endX: number, endY: number) => {
  const selectKeys = projectStore.currentPage.elements.filter((item) => {
    const { x, y, width, height } = item.container.props;
    const x1 = Math.min(startX, endX);
    const x2 = Math.max(startX, endX);
    const y1 = Math.min(startY, endY);
    const y2 = Math.max(startY, endY);
    // 返回判断完全包裹组件
    return x >= x1 && y >= y1 && x + width <= x2 && y + height <= y2;
  }).map((item) => item.key);
  projectStore.setSelectedElementKeys(selectKeys);
};
/* ====================处理框选多个组件======================== */
</script>

<style lang="less" scoped>
.workspace {
  height: 100%;
  user-select: none;
  &-top {
    flex: 1;
    position: relative;
  }
  &-bottom {
    padding: 0 20px;
    height: 40px;
    background: #fff;
    border-top: solid 1px #eee;
    font-size: 12px;
    color: #666;
  }
}
.selectBox {
  display: none;
  position: absolute;
  left: 0;
  top: 0;
  z-index: 9999;
  border: solid 1px #2c76bd;
  box-sizing: border-box;
  background-color: #2c76bd90;
  width: 0;
  height: 0;
}
</style>
