<!--
 * @Description:
 * @Author: 梁平贤
 * @LastEditors: 梁平贤
 * @Date: 2019-10-21 17:36:45
 * @LastEditTime: 2020-04-28 17:41:25
 -->
<template>
  <transition
    name="dialog-fade"
    @after-enter="afterEnter"
    @after-leave="afterLeave"
  >
    <div
      v-show="visible"
      v-dialogDrag="{ draggable, resizeable, resizeHandle }"
      class="el-dialog__wrapper"
      :class="{ 'en-fullscreen__wrapper':enFullscreen }"
      @click.self="handleWrapperClick"
    >
      <div
        ref="dialog"
        role="dialog"
        aria-modal="true"
        :aria-label="title || 'dialog'"
        class="el-dialog"
        :class="[{ 'is-fullscreen': fullscreen, 'el-dialog--center': center,'en-fullscreen':enFullscreen}, customClass]"
        :style="style"
      >
        <div class="el-dialog__header">
          <slot name="title">
            <span class="el-dialog__title">{{ title }}</span>
          </slot>
          <button
            v-if="showClose"
            type="button"
            class="el-dialog__headerbtn"
            aria-label="Close"
            @click="handleClose"
          >
            <i class="el-dialog__close el-icon el-icon-close"></i>
          </button>
        </div>
        <div
          v-if="rendered"
          class="el-dialog__body"
          :class="{'en-body-scroll':enBodyScroll}"
        >
          <slot></slot>
        </div>
        <div
          v-if="$slots.footer"
          class="el-dialog__footer"
        >
          <slot name="footer"></slot>
        </div>
      </div>
    </div>
  </transition>
</template>

<script>
import Popup from "element-ui/lib/utils/popup";
import Migrating from "element-ui/src/mixins/migrating";
import emitter from "element-ui/src/mixins/emitter";
const debounce = (handle, wait = 500) => {
  let timer = null;
  return function(...args) {
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      handle.apply(this, args)
    }, wait)
  }
}

export default {
  name: "EnDialog",

  mixins: [
    Popup,
    emitter,
    Migrating
  ],

  props: {
    // 是否需要body支持滚动 默认false
    enBodyScroll: {
      type: Boolean,
      default: false
    },
    // 增加的属性,支持特定的全屏弹窗
    enFullscreen: {
      type: Boolean,
      default: false
    },
    title: {
      type: String,
      default: ""
    },

    modal: {
      type: Boolean,
      default: true
    },

    modalAppendToBody: {
      type: Boolean,
      default: true
    },

    appendToBody: {
      type: Boolean,
      default: false
    },

    lockScroll: {
      type: Boolean,
      default: true
    },

    closeOnClickModal: {
      type: Boolean,
      default: true
    },

    closeOnPressEscape: {
      type: Boolean,
      default: true
    },

    showClose: {
      type: Boolean,
      default: true
    },

    width: String,

    fullscreen: Boolean,

    customClass: {
      type: String,
      default: ""
    },

    top: {
      type: String,
      default: "15vh"
    },
    beforeClose: Function,
    center: {
      type: Boolean,
      default: false
    },
    resizeable: {
      type: Boolean,
      default: true
    },
    draggable: {
      type: Boolean,
      default: true
    },
    resizeHandle: {
      type: Function,
      default: () => {
        console.log("resize")
      }
    }
  },

  data() {
    return {
      closed: false,
      screenWidth: document.body.clientWidth,
      screenHeight: document.body.clientHeight
    };
  },

  computed: {
    style() {
      const style = {};
      if (!this.fullscreen && !this.enFullscreen) {
        // 正常布局
        style.marginTop = this.top;
        if (this.width) {
          style.width = this.width;
        }
      } else if (this.enFullscreen) {
        if (this.needWindowStyle) {
          style.marginTop = `${(this.screenHeight - 827 - 68) / 2.5 + 60}px`;
        } else {
          style.marginTop = "60px";
        }
      }
      return style;
    },
    // enFullscreen的窗口模式,修改margin-top
    needWindowStyle() {
      return this.enFullscreen && this.screenHeight > 827 + 68;
    },
    // appendToBody需要根据enFullscreen来,如果是的话 一定为true
    needAppendToBody() {
      return this.enFullscreen || this.appendToBody;
    }
  },

  watch: {
    visible(val) {
      if (val) {
        this.closed = false;
        this.$emit("open");
        this.$el.addEventListener("scroll", this.updatePopper);
        this.$nextTick(() => {
          this.$refs.dialog.scrollTop = 0;
        });
        if (this.needAppendToBody) {
          document.body.appendChild(this.$el);
        }
        this.bindResizeFeatures();
      } else {
        this.$el.removeEventListener("scroll", this.updatePopper);
        if (!this.closed) {
          this.$emit("close");
        }
      }
    }
  },

  mounted() {
    if (this.visible) {
      this.rendered = true;
      this.open();
      if (this.needAppendToBody) {
        document.body.appendChild(this.$el);
      }
    }
    this.bindResizeFeatures();
  },

  destroyed() {
    // if appendToBody is true, remove DOM node after destroy
    if (this.needAppendToBody && this.$el && this.$el.parentNode) {
      this.$el.parentNode.removeChild(this.$el);
    }
  },
  directives: {
    /* eslint-disable */
    dialogdrag: {
      bind(el, binding, vnode, oldVnode) {
        const dialogHeaderEl = el.querySelector(".el-dialog__header");
        const dragDom = el.querySelector(".el-dialog");
        const docWidth = document.documentElement.offsetWidth;
        const docHeight = document.documentElement.offsetHeight;
        let hasGetAttr = false;
        let criticalLeft;
        let criticalTop;
        let criticalRight;
        let criticalBottom;
        if (!dragDom.className.includes("is-fullscreen")) {
          dialogHeaderEl.style.cursor = "move";
        }
        // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
        const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null);
        // const fixedX =
        // const fixedY =
        dialogHeaderEl.onmousedown = (e) => {
          // 判断当前是否为全屏状态
          if (!hasGetAttr) {
            hasGetAttr = true;
            criticalLeft = dragDom.offsetLeft;
            criticalTop = dragDom.offsetTop;
            criticalRight = docWidth - dragDom.clientWidth - criticalLeft;
            criticalBottom = docHeight - dragDom.clientHeight - criticalTop;
          }
          const path = event.path || (event.composedPath && event.composedPath());
          const isFull = path.find((s) => {
            if (s.className === undefined || typeof(s.className) === "object") {
              return false;
            }
              return s.className.indexOf("is-fullscreen") > -1;
          });
          if (isFull !== undefined) {
            return;
          }
          const isMinix = path.find((s) => {
            if (s.className === undefined || typeof(s.className) === "object") {
              return false;
            }
              return s.className.indexOf("isminimize") > -1;
          });
          if (isMinix !== undefined) {
            return;
          }
          // 鼠标按下，计算当前元素距离可视区的距离
          const disX = e.clientX - dialogHeaderEl.offsetLeft;
          const disY = e.clientY - dialogHeaderEl.offsetTop;

          // 获取到的值带px 正则匹配替换
          let styL; let styT;

          // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
          if (sty.left.includes("%")) {
            styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, "") / 100);
            styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, "") / 100);
          } else {
            styL = +sty.left.replace("px", "");
            styT = +sty.top.replace("px", "");
          }

          document.onmousemove = function(e) {
            // 通过事件委托，计算移动的距离
            const l = e.clientX - disX;
            const t = e.clientY - disY;
            // 移动当前元素
            dragDom.style.left = `${l + styL}px`;
            dragDom.style.top = `${t + styT}px`;
            const dom = e.path.find((s) => s.querySelector(".el-dialog")).children[0];
            // 处理边界问题
            if (dom.offsetTop <= 0) {
              dragDom.style.top = `-${criticalTop}px`
            }
            if (dom.offsetTop >= criticalBottom + criticalTop) {
              dragDom.style.top = `${criticalBottom}px`
            }
            if (dom.offsetLeft <= 0) {
              dragDom.style.left = `-${criticalLeft}px`
            }
            if (dom.offsetLeft >= criticalRight + criticalLeft) {
              dragDom.style.left = `${criticalRight}px`
            }
          // 将此时的位置传出去
          // binding.value({x:e.pageX,y:e.pageY})
          };

          document.onmouseup = function(e) {
            const dragDom = el.querySelector(".el-dialog");
            const offsetLeft = dragDom.offsetLeft;
            const offsetTop = dragDom.offsetTop;
            const left = Number(dragDom.style.left.replace("px", ""));
            const top = Number(dragDom.style.top.replace("px", ""));
            const windowWidth = window.innerWidth;
            const windowHeight = window.innerHeight - 50;
            const offsetRight = offsetLeft + dragDom.offsetWidth - windowWidth;
            const offsetBottom = offsetTop + dragDom.offsetHeight - windowHeight;
            if (offsetLeft < 0) {
              dragDom.style.left = `${left - offsetLeft }px`;
            }
            if (offsetTop < 0) {
              dragDom.style.top = `${top - offsetTop }px`;
            }
            if (offsetRight > 0) {
              dragDom.style.left = `${left - offsetRight }px`;
            }
            if (offsetBottom > 0) {
              dragDom.style.top = `${top - offsetBottom }px`;
            }
            document.onmousemove = null;
            document.onmouseup = null;
          };
        };
      }
    },
    dialogDrag: {
      bind(el, binding, vnode, oldVnode) {
        const { resizeable, draggable, resizeHandle } = binding.value;
        const debounceResizeHandle = debounce(resizeHandle);
        // 弹框可拉伸最小宽高
        const minWidth = 400
        const minHeight = 300
        // 初始非全屏
        let isFullScreen = false
        // 当前顶部高度
        let nowMarginTop = 0
        // 获取弹框头部（这部分可双击全屏）
        const dialogHeaderEl = el.querySelector('.el-dialog__header')
        const dragDom = el.querySelector('.el-dialog')
        const elHeader = dragDom.querySelector(".el-dialog__header") || {};
        const elFooter = dragDom.querySelector(".el-dialog__footer") || {};
        let moveDown = () => {};
        if (draggable) {
          // 弹窗
          // 给弹窗加上overflow auto；不然缩小时框内的标签可能超出dialog；
          dragDom.style.overflow = 'auto'
          // 清除选择头部文字效果
          // dialogHeaderEl.onselectstart = new Function("return false");
          // 头部加上可拖动cursor
          dialogHeaderEl.style.cursor = 'move'
          // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
          const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null)
          moveDown = e => {
            // 鼠标按下，计算当前元素距离可视区的距离
            const disX = e.clientX - dialogHeaderEl.offsetLeft
            const disY = e.clientY - dialogHeaderEl.offsetTop
            // 获取到的值带px 正则匹配替换
            let styL, styT
            // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
            if (sty.left.includes('%')) {
              styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100)
              styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100)
            } else {
              styL = +sty.left.replace(/\px/g, '')
              styT = +sty.top.replace(/\px/g, '')
            }
            document.onmousemove = function(e) {
              // 通过事件委托，计算移动的距离
              const l = e.clientX - disX
              const t = e.clientY - disY
              // 移动当前元素
              dragDom.style.left = `${l + styL}px`
              dragDom.style.top = `${t + styT}px`
              // 将此时的位置传出去
              // binding.value({x:e.pageX,y:e.pageY})
            }
            document.onmouseup = function(e) {
              const dragDom = el.querySelector(".el-dialog");
              const offsetLeft = dragDom.offsetLeft;
              const offsetTop = dragDom.offsetTop;
              const left = Number(dragDom.style.left.replace("px", ""));
              const top = Number(dragDom.style.top.replace("px", ""));
              const windowWidth = window.innerWidth;
              const windowHeight = window.innerHeight - 50;
              const offsetRight = offsetLeft + dragDom.offsetWidth - windowWidth;
              const offsetBottom = offsetTop + dragDom.offsetHeight - windowHeight;
              if (offsetLeft < 0) {
                dragDom.style.left = `${left - offsetLeft }px`;
              }
              if (offsetTop < 0) {
                dragDom.style.top = `${top - offsetTop }px`;
              }
              if (offsetRight > 0) {
                dragDom.style.left = `${left - offsetRight }px`;
              }
              if (offsetBottom > 0) {
                dragDom.style.top = `${top - offsetBottom }px`;
              }
              document.onmousemove = null
              document.onmouseup = null
            }
          }
          dialogHeaderEl.onmousedown = moveDown
        }
        // 当前宽高
        let nowWidth = 0
        // let nowHight = 0
        // 双击头部全屏效果
        dialogHeaderEl.ondblclick = e => {
          if (isFullScreen === false) {
            // nowHight = dragDom.clientHeight
            nowWidth = dragDom.clientWidth
            nowMarginTop = dragDom.style.marginTop
            dragDom.style.left = 0
            dragDom.style.top = 0
            dragDom.style.height = '100VH'
            dragDom.style.width = '100VW'
            dragDom.style.marginTop = 0
            isFullScreen = true
            dialogHeaderEl.style.cursor = 'initial'
            dialogHeaderEl.onmousedown = null
          } else {
            dragDom.style.height = 'auto'
            dragDom.style.width = nowWidth + 'px'
            dragDom.style.marginTop = nowMarginTop
            isFullScreen = false
            if (draggable) {
              dialogHeaderEl.style.cursor = 'move'
            }
            dialogHeaderEl.onmousedown = moveDown
          }
          debounceResizeHandle();
        }
        if (!resizeable) return;
        dragDom.onmousemove = function(e) {
          // let moveE = e
          if (
            e.clientX > dragDom.offsetLeft + dragDom.clientWidth - 10 ||
            dragDom.offsetLeft + 10 > e.clientX
          ) {
            dragDom.style.cursor = 'w-resize'
          } else if (
            el.scrollTop + e.clientY >
            dragDom.offsetTop + dragDom.clientHeight - 10
          ) {
            dragDom.style.cursor = 's-resize'
          } else {
            dragDom.style.cursor = 'default'

            dragDom.onmousedown = null
          }
          dragDom.onmousedown = e => {
            const clientX = e.clientX
            const clientY = e.clientY
            const elW = dragDom.clientWidth
            const elH = dragDom.clientHeight
            const EloffsetLeft = dragDom.offsetLeft
            const EloffsetTop = dragDom.offsetTop
            dragDom.style.userSelect = 'none'
            const ELscrollTop = el.scrollTop
            // 判断点击的位置是不是为头部
            if (
              clientX > EloffsetLeft &&
              clientX < EloffsetLeft + elW &&
              clientY > EloffsetTop &&
              clientY < EloffsetTop + 100
            ) {
              // 如果是头部在此就不做任何动作，以上有绑定dialogHeaderEl.onmousedown = moveDown;
            } else {
              document.onmousemove = function(e) {
                // 移动时禁用默认事件
                e.preventDefault()
                // 左侧鼠标拖拽位置
                if (clientX > EloffsetLeft && clientX < EloffsetLeft + 10) {
                  // 往左拖拽
                  if (clientX > e.clientX) {
                    dragDom.style.width = elW + (clientX - e.clientX) * 2 + 'px'
                  }
                  // 往右拖拽
                  if (clientX < e.clientX) {
                    if (dragDom.clientWidth < minWidth) {
                      console.log()
                    } else {
                      dragDom.style.width = elW - (e.clientX - clientX) * 2 + 'px'
                    }
                  }
                }
                // 右侧鼠标拖拽位置
                if (
                  clientX > EloffsetLeft + elW - 10 &&
                  clientX < EloffsetLeft + elW
                ) {
                  // 往左拖拽
                  if (clientX > e.clientX) {
                    if (dragDom.clientWidth < minWidth) {
                      console.log()
                    } else {
                      dragDom.style.width = elW - (clientX - e.clientX) * 2 + 'px'
                    }
                  }
                  // 往右拖拽
                  if (clientX < e.clientX) {
                    dragDom.style.width = elW + (e.clientX - clientX) * 2 + 'px'
                  }
                }
                // 底部鼠标拖拽位置
                if (
                  ELscrollTop + clientY > EloffsetTop + elH - 20 &&
                  ELscrollTop + clientY < EloffsetTop + elH
                ) {
                  const elBody = dragDom.querySelector(".el-dialog__body");
                  const headAndFooterHeight = (elHeader.offsetHeight || 0) + (elFooter.offsetHeight || 0);
                  // 往上拖拽
                  if (clientY > e.clientY) {
                    if (dragDom.clientHeight < minHeight) {
                      console.log()
                    } else {
                      const dragDomHeight = elH - (clientY - e.clientY);
                      dragDom.style.height = dragDomHeight + 'px';
                      elBody.style.height = dragDomHeight - headAndFooterHeight + "px";
                    }
                  }
                  // 往下拖拽
                  if (clientY < e.clientY) {
                    const dragDomHeight = elH + (e.clientY - clientY);
                    // const headAndFooterHeight = elHeader.offsetHeight || 0 + elFooter.offsetHeight || 0;
                    dragDom.style.height = dragDomHeight  + 'px';
                    elBody.style.height = dragDomHeight - headAndFooterHeight + "px";
                  }
                }
                debounceResizeHandle();
              }
              // 拉伸结束
              document.onmouseup = function(e) {
                document.onmousemove = null

                document.onmouseup = null
              }
            }
          }
        }
      }
    }
  },

  methods: {
    // 绑定resize功能
    bindResizeFeatures() {
      const that = this;
      window.onresize = () => {
        return (() => {
          that.screenWidth = document.body.clientWidth;
          that.screenHeight = window.innerHeight;
        })();
      };
    },
    getMigratingConfig() {
      return { props: { "size": "size is removed." } };
    },
    handleWrapperClick() {
      if (!this.closeOnClickModal) {
        return;
      }
      this.handleClose();
    },
    handleClose() {
      if (typeof this.beforeClose === "function") {
        this.beforeClose(this.hide);
      } else {
        this.hide();
      }
    },
    hide(cancel) {
      if (cancel !== false) {
        this.$emit("update:visible", false);
        this.$emit("close");
        this.closed = true;
      }
    },
    updatePopper() {
      this.broadcast("ElSelectDropdown", "updatePopper");
      this.broadcast("ElDropdownMenu", "updatePopper");
    },
    afterEnter() {
      this.$emit("opened");
    },
    afterLeave() {
      this.$emit("closed");
    }
  }
};
</script>

<style lang="scss" scoped>
// 全屏弹窗的样式
.en-fullscreen__wrapper {
  overflow: auto;
}

.el-dialog.en-fullscreen {
  position: relative;
  width: calc(100% - 16px);
  max-width: 1536px;
  margin-bottom: 8px;
  height: calc(100% - 68px);
  max-height: 827px;
  overflow: hidden;
  border-radius: 6px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  .el-dialog__body {
    flex-grow: 1;
    overflow: hidden;
    padding: 13px 20px 16px 20px;
  }
  .en-body-scroll.el-dialog__body {
    overflow: auto;
  }
  .el-dialog__footer {
    height: auto;
    margin-bottom: 0px;
  }
}
</style>
<style>
.el-dialog {
  margin: 0 auto;
}
</style>