<template>
  <teleport to="body">
    <div
      :class="['qm-dialog', customClass]"
      :style="positionStyle"
      @click="increaseZIndex"
    >
      <div
        ref="mouseHandler"
        class="qm-dialog-header"
        @mousedown="handleDragMouseDown"
      >
        <div class="qm-dialog-title">
          {{ title }}
        </div>

        <a-button
          class="qm-dialog-close"
          @mousedown.stop
          @click="$emit('close')"
        >
        </a-button>
      </div>

      <div class="qm-dialog-body">
        <slot></slot>
      </div>

      <div
        ref="resizeHandler"
        :class="enableResize && 'resize-handler'"
        @mousedown="handleResizeMouseDown"
      ></div>
    </div>
  </teleport>
</template>

<script setup lang="ts">
import { onMounted, onUpdated, reactive } from "vue";
import { store } from "@/store/store";

// 因为要更改props取得的值，所以不需要reactivity
const {
  top = "10%",
  width = "30%",
  height = "30%",
  title = "无标题",
  zIndex = 1020,
  enableResize = true,
  fixedWidth = false,
  minWidth = 200,
  minHeight = 400,
  customClass = "",
} = defineProps<{
  title: string;
  top?: string;
  width?: string;
  height?: string;
  zIndex?: number;
  enableResize?: boolean;
  fixedWidth?: boolean;
  minWidth?: number;
  minHeight?: number;
  customClass?: string;
}>();

defineEmits(["close"]);
const positionStyle = reactive({
  top,
  left: "10%",
  width,
  height,
  zIndex,
});

const savedStyle = JSON.parse(
  sessionStorage.getItem("dialog-" + title) ?? "{}"
);
if (savedStyle) {
  Object.assign(positionStyle, savedStyle);
}
let mouseHandler = $ref<HTMLHeadElement>();
let resizeHandler = $ref<HTMLDivElement>();

const mousePosition = {
  offsetX: 0,
  offsetY: 0,
};

const handleDragMouseDown = (e: MouseEvent) => {
  document.addEventListener("mousemove", handleDragMouseMove);
  document.addEventListener("mouseup", handleDragMouseUp);
  // console.log(e);
  const { clientX, clientY } = e;
  mousePosition.offsetX = clientX;
  mousePosition.offsetY = clientY;
};
const handleDragMouseMove = (e: MouseEvent) => {
  const { clientX, clientY } = e;
  const windowWidth = window.innerWidth;
  const windowHeight = window.innerHeight;
  const newXRatio =
    parseFloat(positionStyle.left) / 100 +
    (clientX - mousePosition.offsetX) / windowWidth;
  const newYRatio =
    parseFloat(positionStyle.top) / 100 +
    (clientY - mousePosition.offsetY) / windowHeight;
  // console.log({
  //   offsetX: mousePosition.offsetX,
  //   offsetY: mousePosition.offsetY,
  //   newYRatio,
  //   newXRatio,
  // });
  if (newYRatio > 0 && newYRatio < 0.95) {
    positionStyle.top = newYRatio * 100 + "%";
  }
  if (newXRatio > 0 && newXRatio < 0.95) {
    positionStyle.left = newXRatio * 100 + "%";
  }

  mousePosition.offsetX = clientX;
  mousePosition.offsetY = clientY;
};
const handleDragMouseUp = () => {
  mousePosition.offsetX = 0;
  mousePosition.offsetY = 0;
  mouseHandler.removeEventListener("mousedown", handleDragMouseDown);
  document.removeEventListener("mousemove", handleDragMouseMove);
  document.removeEventListener("mouseup", handleDragMouseUp);
};

const handleResizeMouseDown = (e: MouseEvent) => {
  if (!enableResize) return;
  document.addEventListener("mousemove", handleResizeMouseMove);
  document.addEventListener("mouseup", handleResizeMouseUp);
  const { clientX, clientY } = e;
  mousePosition.offsetX = clientX;
  mousePosition.offsetY = clientY;
};
const handleResizeMouseMove = (e: MouseEvent) => {
  // console.log(e);
  // console.log("mouse move");
  const { clientX, clientY } = e;
  const newXRatio = clientX - mousePosition.offsetX;
  const newYRatio = clientY - mousePosition.offsetY;
  const positionStyleWidth = fixedWidth
    ? width
    : parseFloat(positionStyle.width) + newXRatio;
  positionStyle.width = Math.max(positionStyleWidth, minWidth) + "px";
  const positionStyleHeight = parseFloat(positionStyle.height) + newYRatio;
  positionStyle.height = Math.max(positionStyleHeight, minHeight) + "px";

  mousePosition.offsetX = clientX;
  mousePosition.offsetY = clientY;
};
const handleResizeMouseUp = () => {
  mousePosition.offsetX = 0;
  mousePosition.offsetY = 0;
  resizeHandler.removeEventListener("mousedown", handleResizeMouseDown);
  document.removeEventListener("mousemove", handleResizeMouseMove);
  document.removeEventListener("mouseup", handleResizeMouseUp);
};

onMounted(() => {
  increaseZIndex();
});

onUpdated(() => {
  if (title) {
    sessionStorage.setItem("dialog-" + title, JSON.stringify(positionStyle));
  }
});

const increaseZIndex = () => {
  positionStyle.zIndex = store.maxModalZIndex++;
  if (store.maxModalZIndex === 5000) {
    store.maxModalZIndex = 1020;
  }
};
</script>
