// bind 只调用一次，指令第一次绑定到元素时候调用，用这个钩子可以定义一个绑定时执行一次的初始化动作。
// inserted:被绑定的元素插入父节点的时候调用(父节点存在即可调用，不必存在document中)
// update: 被绑定与元素所在模板更新时调用，而且无论绑定值是否有变化，通过比较更新前后的绑定值，忽略不必要的模板更新
// componentUpdate :被绑定的元素所在模板完成一次更新更新周期的时候调用
// unbind: 只调用一次，指令月元素解绑的时候调用
// demo
// Vue.directive("hello",{
//   bind:function(el,bingind,vnode){
//     el.style["color"] = bingind.value;
//     console.log("1-bind");
// },
// inserted:function(){
//     console.log("2-insert");
// },
// update:function(){
//     console.log("3-update");
// },
// componentUpdated:function(){
//     console.log('4 - componentUpdated');
// },
// unbind:function(){
//     console.log('5 - unbind');
// }
// })
// 输入框只允许输入数字  v-number-input.float

/**
 * 拖动
 */
const drag = {
    install(Vue, options = {}) {
        Vue.directive('drag', {
            bind(el, binding, vnode) {
                const dialogHeaderEl = el.querySelector('.el-dialog__header')
                const dragDom = el.querySelector('.el-dialog')
                dialogHeaderEl.style.cssText += ';cursor:move;'
                dragDom.style.cssText += ';top:0px;'

                // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
                const getStyle = (function() {
                    if (window.document.currentStyle) {
                        return (dom, attr) => dom.currentStyle[attr]
                    } else {
                        return (dom, attr) => getComputedStyle(dom, false)[attr]
                    }
                })()

                dialogHeaderEl.onmousedown = e => {
                    // 鼠标按下，计算当前元素距离可视区的距离
                    const disX = e.clientX - dialogHeaderEl.offsetLeft
                    const disY = e.clientY - dialogHeaderEl.offsetTop

                    const dragDomWidth = dragDom.offsetWidth
                    const dragDomHeight = dragDom.offsetHeight

                    const screenWidth = document.body.clientWidth
                    const screenHeight = document.body.scrollHeight

                    const minDragDomLeft = dragDom.offsetLeft
                    const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth

                    const minDragDomTop = dragDom.offsetTop
                    const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomHeight

                    // 获取到的值带px 正则匹配替换
                    let styL = getStyle(dragDom, 'left')
                    let styT = getStyle(dragDom, 'top')

                    if (styL.includes('%')) {
                        styL = +document.body.clientWidth * (+styL.replace(/\\%/g, '') / 100)
                        styT = +document.body.scrollHeight * (+styT.replace(/\\%/g, '') / 100)
                    } else {
                        styL = +styL.replace(/\px/g, '')
                        styT = +styT.replace(/\px/g, '')
                    }

                    document.onmousemove = function(e) {
                        // 通过事件委托，计算移动的距离
                        let left = e.clientX - disX
                        let top = e.clientY - disY
                        if ((left <= 5 && left >= -5) || (top <= 5 && top >= -5)) {
                            return
                        }

                        // 边界处理
                        if (-left > minDragDomLeft) {
                            left = -minDragDomLeft
                        } else if (left > maxDragDomLeft) {
                            left = maxDragDomLeft
                        }

                        if (-top > minDragDomTop) {
                            top = -minDragDomTop
                        } else if (top > maxDragDomTop) {
                            top = maxDragDomTop
                        }

                        // 移动当前元素
                        dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`
                        console.info(dragDom.style.cssText)

                        // emit onDrag event
                        vnode.child.$emit('dragDialog')
                    }

                    document.onmouseup = function(e) {
                        document.onmousemove = null
                        document.onmouseup = null
                    }
                }
            }
        })
    }
}

function onInput(el, ele, binding, vnode) {
    function handle() {
        let val = ele.value
            // modifiers为修饰符对象， 传入了float， 则其float属性为true
        if (binding.modifiers.float) {
            // 清除"数字"和"."以外的字符
            val = val.replace(/[^\d.]/g, '')
                // 只保留第一个, 清除多余的
            val = val.replace(/\.{2,}/g, '.')
                // 第一个字符如果是.号，则补充前缀0
            val = val.replace(/^\./g, '0.')
            if (typeof binding.value !== 'undefined') {
                // 期望保留的最大小数位数
                let pointKeep = 0
                if (typeof binding.value === 'string' ||
                    typeof binding.value === 'number') {
                    pointKeep = parseInt(binding.value)
                }
                const str = '^(\\d+)\\.(\\d\\{' + pointKeep + '}).*$'
                const reg = new RegExp(str)
                if (pointKeep === 0) {
                    // 不需要小数点
                    val = val.replace(reg, '$1')
                } else {
                    // 通过正则保留小数点后指定的位数
                    val = val.replace(reg, '$1.$2')
                }
            }
        }
        ele.value = val
        if (vnode.componentInstance) {
            vnode.componentInstance.$emit('input', ele.value)
        } else {
            vnode.elm.dispatchEvent(new CustomEvent('input', ele.value))
        }
    }
    return handle
}

const numberInput = {
    install(Vue, options = {}) {
        Vue.directive('number-input', {
            bind(el, binding, vnode) {
                const ele = (el && el.tagName === 'INPUT') ? el : el.querySelector('input')
                ele.addEventListener('input', onInput(el, ele, binding, vnode), true)
            },
        })
    }
}

const loadmore = {
    install(Vue, options = {}) {
        Vue.directive('loadmore', {
            bind(el, binding, vnode) {
                const selectWrap = el.querySelector('.el-table__body-wrapper')
                selectWrap.addEventListener('scroll', function() {
                    let sign = 0;
                    const scrollDistance = this.scrollHeight - this.scrollTop - this.clientHeight
                    if (scrollDistance <= sign) {
                        binding.value()
                    }
                })
            }
        })
    }
}
const permission = (el, binding, vnode) => {
    const roles = vnode.context.$store.getters.roles;
    if (!roles) {
        return;
    }

    let userPermissionList = Array.isArray(binding.value) ? binding.value : [binding.value];
    // 当前用户的权限列表
    if (!userPermissionList.some(e => roles.includes(e))) {
        el.parentNode && el.parentNode.removeChild(el);
    }
}

const permissionCheck = {
    install(Vue, options = {}) {
        Vue.directive('hasPermission', {
            inserted: permission,
            componentUpdated: permission
        })
    }
}
export default {
    numberInput,
    loadmore,
    drag,
    permissionCheck
}