<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"
          class="tw-mr-2"
          @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="enableResize && 'resize-handler'"
        @mousedown="handleResizeMouseDown"
      ></div>
    </div>
  </teleport>
</template>

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

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

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;
  positionStyle.width = fixedWidth
    ? width
    : parseFloat(positionStyle.width) + newXRatio + "px";
  positionStyle.height = parseFloat(positionStyle.height) + newYRatio + "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>

<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>
