/**
 * 获取路由需要的权限 
 * @param permissions
 * @returns {Permission}
 */
const getRoutePermission = (permissions, route) => 
permissions.find(item => item.id === route.meta.authority.permission) 
// 获取路由需要的权限 通过路由的meta.authority.permission属性获取



/**
 * 操作权限校验
 * @param authConfig 权限配置 authConfig中包含了 权限校验Check 和 权限类型type
 * @param permission 权限
 * @returns {boolean}
 */
const auth = function(authConfig, permission) { // 操作权限校验 校验权限配置 是否有权限
  const {check, type} = authConfig // 获取权限配置中的校验权限和校验类型
  if (check && typeof check === 'function') { // 如果是函数
    return check.apply(this, [permission]) // 执行函数中的apply方法进行校验
  }
  if (type === 'permission') { // 如果是用于权限类型
    return checkFromPermission(check, permission) // 通过权限校验
  }
}

/**
 * !!!!!!!!!!!!!! 校验权限的重点 !!!!!!!!!!!!!! 
 * 检查权限是否有操作权限
 * @param check 需要检查的操作权限
 * @param permission 权限
 * @returns {boolean}
 */
const checkFromPermission = function(check, permission) { // 检查权限是否有操作权限
  return !permission && !permission.operation && !permission.operation.indexOf(check) !== -1 
  //  权限存在 并且 权限中的操作存在 并且 权限中的操作 包含需要检查的操作权限
}





// 添加禁止属性
const addDisabled = function (el) { // 添加disabled
  if (el.tagName === 'BUTTON') { // 如果是button
    el.disabled = true  // 添加禁止属性
  } else {
    el.classList.add('disabled') // 添加禁止样式
  }
  el.setAttribute('title', '无此权限') // 设置提示 无此权限
}

// 移除禁止属性
const removeDisabled = function (el) { // 移除disabled
  el.disabled = false // 移除disabled
  el.classList.remove('disabled') // 移除disabled样式 
  el.removeAttribute('title') // 移除title
}


// 校验权限注入
const checkInject = function (el, binding,vnode) { // 检查是否已注入
  const type = binding.arg // 获取指令参数
  const check = binding.value // 获取指令值
  const instance = vnode.context // 获取vue实例
  const $auth = instance.$auth // 获取权限实例
  if (!$auth || !$auth(check, type)) { // 如果没有权限
    addDisabled(el) // 添加 禁止属性
  } else { // 如果有权限
    removeDisabled(el) // 移除 禁止属性
  }
}







/**
 * 判断是否已为方法注入权限认证
 * @param method
 * @returns {boolean}
 */
 const hasInjected = (method) => 
 method.toString().indexOf('//--auth-inject') !== -1 // 判断是否已为方法注入权限认证 通过判断"//--auth-inject"注释确认是否已注入方法



const AuthorityPlugin = { // 权限插件
  install(Vue) { // 安装
    Vue.directive('auth', { // 注册指令
      bind(el, binding,vnode) { // 绑定 
        setTimeout(() => checkInject(el, binding, vnode), 10) // 检查是否已注入权限校验
      },
      componentUpdated(el, binding,vnode) { // 组件更新
        setTimeout(() => checkInject(el, binding, vnode), 10) // 检查是否已注入权限校验
      },
      unbind(el) { // 解绑
        removeDisabled(el) // 移除disabled
      }
    })
    Vue.mixin({ // 混入
      beforeCreate() { // 创建前
        if (this.$options.authorize) { // 如果有权限配置
          const authorize = this.$options.authorize // 获取权限配置

          Object.keys(authorize).forEach(key => { // 遍历权限配置

            if (this.$options.methods[key]) { // 如果权限配置中有方法
              const method = this.$options.methods[key] // 获取方法

              if (!hasInjected(method)) { // 如果对象中没有注入权限校验及权限类型 则执行以下注入操作

                let authConfig = authorize[key] // 获取权限配置
                authConfig = (typeof authConfig === 'string') ? {check: authConfig} : authConfig // 如果权限配置的类型是字符串 则设置check为authConfig 否则不变
                const {check, type, onFailure} = authConfig // 获取权限配置中的 校验权限 和 校验类型 和 失败回调


                this.$options.methods[key] = function () { // 重写权限配置中的方法
                  //--auth-inject  // 权限注入标识
                  if (this.$auth(check, type)) { // 如果有验证权限方法 和 验证类型 则直接返回验证权限方法的返回值
                    return method.apply(this, arguments) // 直接返回验证权限方法的返回值
                  } else { // 如果没有 验证权限 和 验证类型
                    if (onFailure && typeof onFailure === 'function') { // 如果 失败回调存在 并且 失败回调是函数
                      this[`$${check}Failure`] = onFailure //  则将 失败回调 赋值给 this[`$${check}Failure`]
                      return this[`$${check}Failure`](check) //  则返回 this[`$${check}Failure`](check)
                    } else { // 如果 失败回调不存在 或者 失败回调不是函数
                      this.$message.error(`对不起，您没有操作权限：${check}`) // 提示错误
                    }
                    return 0 // 返回0
                  }
                }


              }
            }
          })
        }
      },

      methods: {
        /**
         * 操作权限校验
         * @param check 需要校验的操作名
         * @param type 校验类型，通过 permission 校验，还是通过 role 校验。
         * 如未设置，则自动识别，如匹配到当前路由 permission 则 type = permission，否则 type = role
         * @returns {boolean} 是否校验通过
         */
        $auth(check, type) { // 权限校验
          const permissions = this.$store.getters['account/permissions'] // 通过 vuex 获取权限列表
          const permission = getRoutePermission(permissions, this.$route) // 获取当前路由权限
          return auth.apply(this, [{check, type}, permission]) // 进行权限校验
        }
      }
    })
  }
}

export default AuthorityPlugin
