<template>
  <a-modal
    ref="modalRef"
    width="850px"
    :visible="props.visible"
    :wrap-style="{ overflow: 'hidden' }"
    @ok="handleOk"
    :mask-closable="maskClosable"
    :centered="props.centered"
    :footer="props.footer"
    @cancel="handleCancel"
    :confirm-loading="props.confirmLoading"
    :destroyOnClose="props.destroyOnClose"
  >
    <slot></slot>

    <template #title>
      <div ref="modalTitleRef" style="width: 100%; cursor: move">{{ props.title }}</div>
    </template>

    <template #modalRender="{ originVNode }">
      <div :style="transformStyle">
        <component :is="originVNode" />
      </div>
    </template>
  </a-modal>
</template>
<script lang="ts" setup>
  import { computed, CSSProperties, ref, watch, watchEffect } from 'vue';
  import { useDraggable } from '@vueuse/core';

  // 定义Props接口，描述组件的属性
  interface Props {
    title?: string; // 对话框的标题，默认为"提示"
    footer?: null; // 对话框的页脚，默认为null
    visible: boolean; // 对话框是否可见
    confirmLoading?: boolean; // 确认按钮是否处于加载状态，默认为false
    destroyOnClose?: boolean; // 对话框关闭时是否销毁组件，默认为false
    maskClosable?: boolean; // 点击遮罩层是否可关闭对话框，默认为false
    centered?: boolean; // 对话框是否居中显示，默认为false
  }

  // 设置props的默认值
  const props = withDefaults(defineProps<Props>(), { title: '摄像头信息', visible: false, destroyOnClose: false, maskClosable: true });

  // 创建ref引用modalTitleRef，用于引用组件中的标题元素
  const modalTitleRef = ref<HTMLElement | null | any>(null);

  // 使用useDraggable钩子，获取拖拽相关属性
  const { x, y, isDragging } = useDraggable(modalTitleRef);

  // 创建emit函数，用于触发自定义事件
  const emit = defineEmits(['ok', 'update:visible', 'cancel']);

  // 处理ok事件的函数
  const handleOk = (e: MouseEvent) => {
    emit('ok');
  };

  // 处理cancel事件的函数
  const handleCancel = () => {
    emit('update:visible', false);
    emit('cancel');
  };

  // 创建各种响应式数据
  const startX = ref<number>(0); // 记录起始点的 x 坐标
  const startY = ref<number>(0); // 记录起始点的 y 坐标
  const startedDrag = ref(false); // 标志位，表示是否开始拖拽，默认为 false
  const transformX = ref(0); // x 偏移量
  const transformY = ref(0); // y 偏移量
  const preTransformX = ref(0); // 拖拽前的 x 偏移量
  const preTransformY = ref(0); // 拖拽前的 y 偏移量
  const dragRect = ref({ left: 0, right: 0, top: 0, bottom: 0 }); // 可拖拽的边界

  // 监听x和y的变化
  watch([x, y], () => {
    // 监听鼠标移动事件的函数
    if (!startedDrag.value) {
      // 如果尚未开始拖拽
      startX.value = x.value; // 记录起始点的 x 坐标
      startY.value = y.value; // 记录起始点的 y 坐标
      const bodyRect = document.body.getBoundingClientRect(); // 获取页面 body 元素的边界信息
      const titleRect = modalTitleRef.value.getBoundingClientRect(); // 获取 modalTitle 元素的边界信息
      dragRect.value.right = bodyRect.width - titleRect.width; // 计算可拖拽的最大右边界
      dragRect.value.bottom = bodyRect.height - titleRect.height; // 计算可拖拽的最大下边界
      preTransformX.value = transformX.value; // 记录拖拽前的 x 偏移量
      preTransformY.value = transformY.value; // 记录拖拽前的 y 偏移量
    }
    startedDrag.value = true; // 设置已开始拖拽标志
  });

  // 监听isDragging的变化
  watch(isDragging, () => {
    // 监听 isDragging 变量的改变
    if (!isDragging) {
      // 如果 isDragging 变为 false
      startedDrag.value = false; // 将 startedDrag.value 设置为 false，表示拖拽操作结束
    }
  });

  // 使用watchEffect监听响应式数据的变化
  watchEffect(() => {
    // 响应 startedDrag.value 的变化
    if (startedDrag.value) {
      // 如果 startedDrag.value 为 true，表示正在进行拖拽操作
      transformX.value = preTransformX.value + Math.min(Math.max(dragRect.value.left, x.value), dragRect.value.right) - startX.value; // 计算 x 偏移量
      transformY.value = preTransformY.value + Math.min(Math.max(dragRect.value.top, y.value), dragRect.value.bottom) - startY.value; // 计算 y 偏移量
    }
  });

  // 计算transformStyle，用于动态设置对话框的位置
  const transformStyle = computed<CSSProperties>(() => {
    return {
      transform: `translate(${transformX.value}px, ${transformY.value}px)`,
    };
  });
</script>
