<template>
  <teleport to="body">
    <div
      class="dialog-container"
      :style="positionStyle"
      @click="increaseZIndex"
    >
      <header
        ref="mouseHandler"
        class="tw-flex tw-place-content-between tw-items-center"
      >
        <div
          class="
            tw-text-base
            tw-ml-5
            tw-my-2
            tw-cursor-move
            tw-flex-grow
            tw-font-bold
          "
          @mousedown="handleDragMouseDown"
        >
          {{ title }}
        </div>
        <a-button shape="circle" size="small" @click="$emit('close')">
          <template #icon><CloseOutlined /></template>
        </a-button>
      </header>

      <div class="tw-m-1 tw-overflow-auto" style="height: calc(100% - 50px)">
        <slot></slot>
      </div>

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

<script lang="ts">
// 不能用 <script setup lang="ts"> ，因为被上层用ref了，暂时没有解决方案
import { defineComponent, onMounted, onUpdated, reactive, ref } from "vue";
import { CloseOutlined } from "@ant-design/icons-vue";
import { store } from "@/features/mark/store";

export default defineComponent({
  name: "QmDialog",
  components: { CloseOutlined },
  props: {
    title: { type: String, default: "" },
    top: { type: String, default: "10%" },
    width: { type: String, default: "30%" },
    height: { type: String, default: "30%" },
    zIndex: { type: Number, default: 1020 },
  },
  emits: ["close"],
  setup({ top, width, height, title, zIndex }) {
    const positionStyle = reactive({
      top,
      left: "10%",
      width,
      height,
      zIndex,
    });

    const savedStyle = JSON.parse(
      sessionStorage.getItem("dialog-" + title) ?? "{}"
    );
    if (savedStyle?.top) positionStyle.top = savedStyle?.top;
    if (savedStyle?.left) positionStyle.left = savedStyle?.left;
    if (savedStyle?.width) positionStyle.width = savedStyle?.width;
    if (savedStyle?.height) positionStyle.height = savedStyle?.height;
    const mouseHandler = ref(null as unknown as HTMLHeadElement);
    const resizeHandler = ref(null as unknown as 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 = (e: MouseEvent) => {
      mousePosition.offsetX = 0;
      mousePosition.offsetY = 0;
      mouseHandler.value.removeEventListener("mousedown", handleDragMouseDown);
      document.removeEventListener("mousemove", handleDragMouseMove);
      document.removeEventListener("mouseup", handleDragMouseUp);
    };

    const handleResizeMouseDown = (e: MouseEvent) => {
      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;
      // @ts-ignore
      const newXRatio = clientX - mousePosition.offsetX;
      const newYRatio = clientY - mousePosition.offsetY;
      positionStyle.width = parseFloat(positionStyle.width) + newXRatio + "px";
      positionStyle.height =
        parseFloat(positionStyle.height) + newYRatio + "px";

      mousePosition.offsetX = clientX;
      mousePosition.offsetY = clientY;
    };
    const handleResizeMouseUp = (e: MouseEvent) => {
      mousePosition.offsetX = 0;
      mousePosition.offsetY = 0;
      resizeHandler.value.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;
      }
    };
    return {
      positionStyle,
      mouseHandler,
      resizeHandler,
      handleDragMouseDown,
      handleResizeMouseDown,
      increaseZIndex,
    };
  },
});
</script>

<style scoped>
.dialog-container {
  z-index: 1020;
  position: absolute;
  min-width: 100px;
  background-color: var(--app-container-bg-color);
  border: 1px solid var(--app-main-bg-color);
  border-radius: 5px;
  box-shadow: 0px 4px 8px 0px rgba(25, 27, 55, 0.1);
}
header {
  color: var(--app-main-text-color);
  border-bottom: 1px solid var(--app-main-bg-color);
}
.resize-handler {
  position: absolute;
  bottom: -10px;
  right: -10px;
  width: 20px;
  height: 20px;
  cursor: nwse-resize;
}
</style>
