/**
 * 指令，仅用于element-plus 中的 dialog 使用
 * 可基于窗口各种拖拽使用
 */
const drag = {
  mounted(el, binding) {
    if (binding.value) {
      handleElShow(el)
    }
  },
  updated(el, binding) {
    if (binding.value) {
      handleElShow(el)
    } else {
      handleElHide(el)
    }
  },
  beforeUnmount(el) {
    handleElHide(el)
  }
}

async function handleElShow(el) {
  // 防止时间太快，拿不到dom
  await myPromise()
  const dialog = el.querySelector('.el-dialog')
  if (!dialog) {
    return
  }
  const header = el.querySelector('.el-dialog__header')
  const dialogMask = el.querySelector('.el-overlay')
  dialogMask.style.cssText += "overflow: hidden;"
  header.style.cursor = 'move'
  let dragStatus = false
  let data = { // 数据源，不变部分为：window信息、dialog信息、mouse初始值信息，可变部分为：拖拽坐标位移
    window: { // window信息
      width: 0,
      height: 0,
    },
    dialog: {
      x: 0,
      y: 0,
      width: 0,
      height: 0,
      marginTop: ""
    }, // dialog信息
    mouse: { // 鼠标初始信息
      x: 0,
      y: 0
    },
    drag: { // 拖拽过程信息
      x: 0,
      y: 0
    }
  }
  // 所有的监听只为了修改data数据
  header.addEventListener('mousedown', mouseDown)
  document.addEventListener('mousemove', mouseMove)
  document.addEventListener('mouseup', mouseUp)
  window.addEventListener('resize', sizeChange)
  // 边界处理，防止拖动位置溢出
  function handlePosition() {
    if (data.mouse.x - data.drag.x >= data.dialog.x) {
      data.drag.x = data.mouse.x - data.dialog.x
    }
    if (data.drag.x - data.mouse.x >= data.window.width - (data.dialog.x + data.dialog.width)) {
      data.drag.x = data.mouse.x + data.window.width - data.dialog.x - data.dialog.width
    }
    if (data.mouse.y - data.drag.y >= data.dialog.y) {
      data.drag.y = data.mouse.y - data.dialog.y
    }
    if (data.drag.y - data.mouse.y >= data.window.height - (data.dialog.y + data.dialog.height)) {
      data.drag.y = data.mouse.y + data.window.height - data.dialog.y - data.dialog.height
    }
    setPosition()
  }
  // 根据data来设置拖动后的位置
  function setPosition() {
    let top = data.drag.y - data.mouse.y + data.dialog.y
    let left = data.drag.x - data.mouse.x + data.dialog.x
    dialog.style.cssText += `position: absolute; top: calc(${top}px - ${data.dialog.marginTop}); left: ${left}px;`
  }
  function mouseDown(e) {
    // 获取dialog目前的位置，坐标, 以及屏幕当前的宽高
    // 一切初始数据的获取应该放置于此，避免其他如：宽度修改等一系列的影响
    if (e.button !== 0) {
      return
    }
    data.window = {
      width: document.body.clientWidth,
      height: document.body.clientHeight
    }
    data.dialog = dialog.getBoundingClientRect()
    data.dialog.marginTop = window.getComputedStyle(dialog).marginTop
    data.mouse = {
      x: e.clientX,
      y: e.clientY
    }
    dragStatus = true
  }
  function mouseMove(e) {
    if (dragStatus) {
      data.drag = {
        x: e.clientX,
        y: e.clientY
      }
      dialogMask.style.userSelect = "none"
      handlePosition()
    }  
  }
  function mouseUp(e) {
    dialogMask.style.userSelect = "auto"
    dragStatus = false
  }
  function sizeChange(e) {
    // dialog.style.cssText += 'position: static';
  }
  function myPromise() {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve()
      }, 500)
    })
  }
  // 方便卸载使用
  el.__mouseDown__ = mouseDown
  el.__mouseUp__ = mouseUp
  el.__mouseMove__ = mouseMove
  el.__sizeChange__ = sizeChange
}

function handleElHide(el) {
  // 避免重复开销，卸载所有的监听
  // 解决问题：多次创建新的实例 =》 监听不取消 =》 同时存在多个无用的监听，导致页面卡顿
  document.removeEventListener('mousedown', el.__mouseDown__)
  document.removeEventListener('mousemove', el.__mouseMove__)
  document.removeEventListener('mouseup', el.__mouseUp__)
  window.removeEventListener('resize', el.__sizeChange__)
}

export default drag