<template>
  <div class="scaleplate" id="scaleplate">
    <!-- 显示/隐藏参考线 -->
    <div class="refer-line-img" @click="projectStore.toggleReffer()">
      <EyeFilled v-if="projectStore.showReffer" />
      <EyeInvisibleFilled v-else />
    </div>
    <!-- 标尺 -->
    <div
      class="scaleplate-horizontal"
      ref="horizontalRef"
      @mousemove="handleMouseMoveHScaleplate($event, 'horizontal')"
      @mouseenter="virtualReferLine.type = 'horizontal'"
      @mouseleave="virtualReferLine.type = null"
      @click="handleAddReferLine"
    >
      <canvas
        id="scaleplateHorizontal"
        :style="{ width: windowSize.width + 'px', height: '20px' }"
      />
    </div>
    <div
      class="scaleplate-vertical"
      ref="verticalRef"
      @mousemove="handleMouseMoveHScaleplate($event, 'vertical')"
      @mouseenter="virtualReferLine.type = 'vertical'"
      @mouseleave="virtualReferLine.type = null"
      @click="handleAddReferLine"
    >
      <canvas
        id="scaleplateVertical"
        :style="{ width: '20px', height: windowSize.height + 'px' }"
      />
    </div>

    <!-- 参考线 -->
    <div
      class="refer-line"
      v-for="item in stageStore.getReferLines"
      v-show="projectStore.showReffer"
      :key="item.key"
      :style="{ left: item.x + 'px', top: item.y + 'px' }"
      :class="item.type === 'horizontal' ? 'refer-line-h' : 'refer-line-v'"
      @dblclick="projectStore.removeReferLine(item.key)"
    >
      <UseDraggable
        @move="
          (position, event) => handleDragReferLine(position, event, item.key)
        "
      >
        <span class="refer-line__txt">{{ item.value }}px</span>
        <span class="refer-line__line"></span>
      </UseDraggable>
    </div>
    <!-- 临时参考线 -->
    <div
      class="refer-line virtual-refer-line"
      :class="
        virtualReferLine.type === 'horizontal' ? 'refer-line-h' : 'refer-line-v'
      "
      :style="{
        left: virtualReferLine.x + 'px',
        top: virtualReferLine.y + 'px',
      }"
      v-show="virtualReferLine.type"
    >
      <span class="refer-line__txt">{{ virtualReferLine.value }}px</span>
      <span class="refer-line__line refer-line__dashed"></span>
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, ref, onBeforeUnmount, nextTick, watch } from "vue";
import type { Ref } from "vue";
import { EyeFilled, EyeInvisibleFilled } from "@ant-design/icons-vue";
import { UseDraggable } from "@vueuse/components";
import { drawScaleplate, uuid } from "@/utils";
import { useStageStore } from "@/store/modules/stage";
import { useProjectStore } from "@/store/modules/project";
import type { ReferLine } from "#/project";

const stageStore = useStageStore();
const projectStore = useProjectStore();
const horizontalRef = ref<HTMLElement | null>(null);
const verticalRef = ref<HTMLElement | null>(null);
const windowSize: Ref<{ width: number; height: number }> = ref({
  width: 0,
  height: 0,
});

/* 绘制标尺刻度 */
const handleDrawScaleplate = () => {
  // 水平轴
  const { scale, scrollX, scrollY, originX, originY } = stageStore;
  drawScaleplate({
    canvas: document.getElementById(
      "scaleplateHorizontal"
    ) as HTMLCanvasElement,
    canvasStyleWidth: windowSize.value.width,
    canvasStyleHeight: 20,
    direcotion: "horizontal",
    scale,
    scrollX,
    scrollY,
    originX,
    originY,
  });
  // 垂直轴
  drawScaleplate({
    canvas: document.getElementById("scaleplateVertical") as HTMLCanvasElement,
    canvasStyleWidth: 20,
    canvasStyleHeight: windowSize.value.height,
    direcotion: "vertical",
    scale,
    scrollX,
    scrollY,
    originX,
    originY,
  });
};

/* =============================== 参考线 ================================= */
const virtualReferLine: Ref<ReferLine> = ref({
  key: '0',
  x: 0,
  y: 0,
  value: 0,
  type: null,
});
/* 临时参考线位置 */
const handleMouseMoveHScaleplate = (
  e: MouseEvent,
  type: "horizontal" | "vertical"
) => {
  const { offsetX, offsetY } = e;
  const { scale, originX, originY, scrollX, scrollY } = stageStore;

  virtualReferLine.value.x = type === "horizontal" ? offsetX + 20 : 0;
  virtualReferLine.value.y = type === "vertical" ? offsetY + 20 : 0;
  // 计算当前位置数值
  if (type === "horizontal") {
    const offset = scrollX - originX;
    virtualReferLine.value.value = Math.round((offset + offsetX) / scale);
  } else {
    const offset = scrollY - originY;
    virtualReferLine.value.value = Math.round((offset + offsetY) / scale);
  }
};
/* 添加参考线 */
const handleAddReferLine = () => {
  if (!virtualReferLine.value.type) return;

  projectStore.addReferLine({
    ...virtualReferLine.value,
    key: uuid(),
  });
};
/* 拖拽参考线 */
const handleDragReferLine = (
  { x, y }: { x: number; y: number },
  _: PointerEvent,
  key: string
) => {
  const referLine = projectStore.referLines.find((item) => item.key === key);
  if (!referLine) return;

  const { scale, originX, originY, scrollX, scrollY } = stageStore;
  const { left, top } = horizontalRef.value!.getBoundingClientRect();

  if (referLine.type === "horizontal") {
    const lineX = x - left + 20;
    const offsetX = scrollX - originX;

    referLine.value = Math.round((lineX + offsetX - 20) / scale);
    referLine.x = lineX;
  } else {
    const lineY = y - top;
    const offsetY = scrollY - originY;

    referLine.value = Math.round((lineY + offsetY - 20) / scale);
    referLine.y = lineY;
  }

  projectStore.updateReferLine(referLine);
};
/* ===============================参考线结束================================= */

/* 设置刻度宽高 */
const setWindowSize = async () => {
  windowSize.value = {
    width: horizontalRef.value!.clientWidth,
    height: verticalRef.value!.clientHeight,
  };
  await nextTick();
  handleDrawScaleplate();
};

watch(
  () => [
    stageStore.scrollX,
    stageStore.scrollY,
    stageStore.scale,
    stageStore.viewportHeight,
    stageStore.viewportWidth,
  ],
  () => {
    handleDrawScaleplate();
  },
  { immediate: false }
);

let observer: ResizeObserver;
onMounted(() => {
  setWindowSize();

  observer = new ResizeObserver(setWindowSize);
  /* 监听画布尺寸变化 */
  const element = document.getElementsByClassName('workspace-wrapper')?.[0];
  if(element) {
    observer.observe(element);
  }
});
onBeforeUnmount(() => {
  observer.disconnect();
});
</script>

<style lang="less" scoped>
.refer-line-img {
  width: 20px;
  height: 20px;
  background: #fff;
  text-align: center;
  font-size: 12px;
  line-height: 20px;
  border-bottom: solid 1px #eee;
  border-right: solid 1px #eee;
  cursor: pointer;
}
.scaleplate-horizontal {
  position: absolute;
  left: 20px;
  top: 0;
  width: calc(100% - 20px);
  height: 20px;
  background: #fff;
  border-bottom: solid 1px #eee;
}
.scaleplate-vertical {
  position: absolute;
  top: 20px;
  left: 0;
  height: calc(100% - 20px);
  width: 20px;
  background: #fff;
  border-right: solid 1px #eee;
}

.refer-line {
  position: absolute;
  font-size: 12px;
  color: red;
  &-h {
    width: 5px;
    height: 100%;
    .refer-line__line {
      border-left: solid 1px red;
      cursor: e-resize;
    }
    .refer-line__dashed {
      border-left: dashed 1px red;
    }
  }
  &-v {
    width: 100%;
    height: 5px;
    .refer-line__line {
      border-top: solid 1px red;
      cursor: n-resize;
    }
    .refer-line__dashed {
      border-top: dashed 1px red;
    }
    .refer-line__txt {
      transform: rotate(-90deg);
      transform-origin: -4px 2px;
    }
  }
  &__line {
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
  }
  &__txt {
    font-size: 12px;
    position: absolute;
    top: 0px;
    left: 4px;
    pointer-events: none;
  }
}
.virtual-refer-line {
  pointer-events: none;
}
</style>
