<template>
  <div class="drag-container" v-show="show">
    <slot />
  </div>
</template>

<script lang="ts">
import {
  defineComponent,
  reactive,
  toRefs,
  onMounted,
  watch,
  watchEffect
} from 'vue';
export default defineComponent({
  props: {
    show: {
      type: Boolean,
      default: () => false
    },
    domClassName: {
      type: String,
      default: ''
    }
  },
  setup(props: any, ctx: any) {
    const data = reactive({
      show: false,
      domClassName: '',
      startPosition: {
        left: '',
        top: '',
        cssText: ''
      }
    });

    watchEffect(() => {
      data.show = props.show;
      data.domClassName = props.domClassName;
    });

    onMounted(() => {
      const dragDom = document.getElementsByClassName(
        props.domClassName ? props.domClassName : 'drag-container'
      )[0] as HTMLElement;
      if (!dragDom) return;
      let isDrag = false;
      watch(
        () => data.show,
        (newVal, oldVal) => {
          data.show = newVal;
          if (newVal === oldVal) return;
          if (data.show === true) {
            dragDom.style.left = data.startPosition?.left;
            dragDom.style.top = data.startPosition?.top;
            dragDom.style.cssText = data.startPosition?.cssText;
          }
        }
      );
      const mouseDown = (e: MouseEvent) => {
        isDrag = true;
        const X = e.clientX - dragDom.offsetLeft;
        const Y = e.clientY - dragDom.offsetTop;
        const move = (e: MouseEvent) => {
          e.preventDefault();
          if (isDrag) {
            dragDom.style.left = `${e.clientX - X}Px`;
            dragDom.style.top = `${e.clientY - Y}Px`;
          }
        };
        document.addEventListener('mousemove', throttle(move, 20), false);
        document.addEventListener('mouseup', () => {
          isDrag = false;
          document.removeEventListener('mousemove', move);
        });
      };
      dragDom.addEventListener('mousedown', mouseDown);
    });

    function throttle(
      fn: { (e: MouseEvent): void; apply?: any },
      timer: number
    ) {
      let initTime = 0;
      return function (...args: any) {
        const nowTime = +new Date();
        if (nowTime - initTime > timer) {
          initTime = nowTime;
          fn.apply(ctx, args);
        }
      };
    }

    const positionReset = () => {
      const dragDom = document.getElementsByClassName(
        props.domClassName ? props.domClassName : 'drag-container'
      )[0] as HTMLElement;
      data.startPosition = {
        left: '',
        top: '',
        cssText: ''
      };
      dragDom.style.left = data.startPosition?.left;
      dragDom.style.top = data.startPosition?.top;
      dragDom.style.cssText = data.startPosition?.cssText;
    };

    ctx.expose({
      positionReset
    });

    return {
      ...toRefs(data),
      throttle
    };
  }
});
</script>
<style lang="scss" scoped>
@import url('../../styles/common.scss');
@import url('../../styles/icon.scss');
.drag-container {
  position: fixed;
  z-index: 100;
}
</style>
