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

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

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

<script lang="ts">
import { defineComponent, onUnmounted, 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: 1000 },
  },
  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) => {
      mouseHandler.value.addEventListener("mousemove", handleDragMouseMove);
      mouseHandler.value.addEventListener("mouseup", handleDragMouseUp);
      // console.log(e);
      const { offsetX, offsetY } = e;
      mousePosition.offsetX = offsetX;
      mousePosition.offsetY = offsetY;
    };
    const handleDragMouseMove = (e: MouseEvent) => {
      const { clientX, clientY } = e;
      const windowWidth = window.innerWidth;
      const windowHeight = window.innerHeight;
      const newXRatio = (clientX - mousePosition.offsetX) / windowWidth;
      const newYRatio = (clientY - mousePosition.offsetY) / windowHeight;
      // console.log({
      //   offsetX: mousePosition.offsetX,
      //   offsetY: mousePosition.offsetY,
      //   newYRatio,
      //   newXRatio,
      // });
      positionStyle.top = newYRatio * 100 + "%";
      positionStyle.left = newXRatio * 100 + "%";
    };
    const handleDragMouseUp = (e: MouseEvent) => {
      mousePosition.offsetX = 0;
      mousePosition.offsetY = 0;
      mouseHandler.value.removeEventListener("mousemove", handleDragMouseMove);
      mouseHandler.value.removeEventListener("mouseup", handleDragMouseUp);
    };

    const handleResizeMouseDown = (e: MouseEvent) => {
      resizeHandler.value.addEventListener("mousemove", handleResizeMouseMove);
      resizeHandler.value.addEventListener("mouseup", handleResizeMouseUp);
      resizeHandler.value.addEventListener("mouseout", handleResizeMouseOut);
    };
    const handleResizeMouseMove = (e: MouseEvent) => {
      // console.log(e);
      // console.log("mouse move");
      // @ts-ignore
      const dialog = e.target.parentElement as HTMLDivElement;
      // console.log(dialog);
      const newXRatio =
        parseFloat(getComputedStyle(dialog).width) + e.movementX;
      const newYRatio =
        parseFloat(getComputedStyle(dialog).height) + e.movementY;
      positionStyle.width = newXRatio + "px";
      positionStyle.height = newYRatio + "px";
    };
    const handleResizeMouseUp = (e: MouseEvent) => {
      resizeHandler.value.removeEventListener(
        "mousemove",
        handleResizeMouseMove
      );
      resizeHandler.value.removeEventListener("mouseup", handleResizeMouseUp);
      resizeHandler.value.removeEventListener("mouseout", handleResizeMouseOut);
    };
    const handleResizeMouseOut = (e: MouseEvent) => {
      resizeHandler.value.removeEventListener(
        "mousemove",
        handleResizeMouseMove
      );
      resizeHandler.value.removeEventListener("mouseup", handleResizeMouseUp);
      resizeHandler.value.removeEventListener("mouseout", handleResizeMouseOut);
    };

    onUnmounted(() => {
      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: 1000;
  position: absolute;
  min-width: 100px;
  background-color: white;
  border: 1px solid grey;
  border-radius: 5px;
  box-shadow: 4px 6px 2px grey;
}
header {
  background-color: #eff3f6;
}
.resize-handler {
  position: absolute;
  bottom: 0;
  right: 0;
  width: 100px;
  height: 100px;
  cursor: nwse-resize;
}
</style>
