/*
 * @Author: Zp 工具函数
 * @Date: 2020-03-12 16:14:38
 * @Last Modified by: Zp
 * @Last Modified time: 2020-04-15 16:59:40
 */

import routes from 'router/routes'

// 公用工具函数 start

/**
 * @description 判断要查询的数组是否至少有一个元素包含在目标数组中
 * @param {Array} target 目标数组
 * @param {Array} arr 需要查询的数组
 */
export const hasOneOf = (targetarr, arr) => {
  return targetarr.some(_ => arr.indexOf(_) > -1)
}

/**
 * @description 抽象循环函数
 * @param {Array} arr 循环的数组
 * @param {function} fn 循环调用的函数
 */
export const forEach = (arr, fn) => {
  if (!arr.length || !fn) return
  let i = -1
  const len = arr.length
  while (++i < len) {
    const item = arr[i]
    fn(item, i, arr)
  }
}

/**
 * @description 实现对象的深拷贝，包括循环引用
 * @param {Object|Array} target 需要深拷贝的对象
 * @param {WeakMap} map 弱引用的键值对集合，可以手动将引用对象=null，回收内存
 */
export const deepClone = (target, map = new WeakMap()) => {
  if (typeof target === 'object') {
    // 先浅拷贝目标对象，无论对象还是数组一律按对象处理
    const clone = Object.assign({}, target)

    // 解决循环引用
    if (map.get(target)) return map.get(target)
    map.set(target, clone)
    // 解决循环引用

    Object.keys(clone).forEach(key => deepClone(target[key]), map)

    return Array.isArray(target) ? Array.from(clone) : clone
  } else {
    return target
  }
}

export function getT() {}

/**
 * @description 判断item是否有children数组length并且不为0
 * @param {Object} item
 */
export const hasChild = item => {
  return item.children && item.children.length !== 0
}

/**
 * @description 根据路由上的meta和需要访问的权限判断是否能显示该菜单
 * @param {Object} item 当前路由源对象
 * @param {String} access 当前路由需要的访问权限 ['admin']
 */
const showThisMenuEle = (item, access) => {
  if (item.meta && item.meta.access && item.meta.access.length) {
    if (hasOneOf(item.meta.access, access)) return true
    else return false
  } else return true
}

export const localRead = (key) => {
  return localStorage.getItem(key) || ''
}

// 公用工具函数 end

// 权限控制工具函数 start

/**
 * @param {*} access 用户权限数组，如 ['super_admin', 'admin']
 * @param {*} route 路由列表
 */
const hasAccess = (access, route) => {
  if (route.meta && route.meta.access) return hasOneOf(access, route.meta.access)
  else return true
}

/**
 * 权鉴函数
 * @description 用户是否可跳转到该页
 * @param {*} name 即将跳转的路由name
 * @param {*} access 用户权限数组
 * @param {*} routes 路由列表
 */
export const canTurnTo = (name, access, routes) => {
  const routePermissionJudge = (list) => {
    return list.some(item => {
      if (item.children && item.children.length) {
        return routePermissionJudge(item.children)
      } else if (item.name === name) {
        return hasAccess(access, item)
      }
    })
  }

  return routePermissionJudge(routes)
}

/**
 * 跳转函数
 * @param {*} to 即将跳转的路由对象
 * @param {*} access 用户权限数组
 * @param {*} next 跳转函数
 */
export const turnTo = (to, access, next) => {
  if (canTurnTo(to.name, access, routes)) next() // 有权限，可访问
  else next({ replace: true, name: 'login' }) // 无权限，重定向到无权限访问页面
}

// 权限控制工具函数 end

// 其他工具函数 start

/**
 * @description 根据路由获取侧边栏菜单
 * @param {Array} list 通过路由列表得到菜单列表
 * @returns {Array}
 */
export const getMenuByRouter = (list, access) => {
  const res = []
  forEach(list, item => {
    if (!item.meta || (item.meta && !item.meta.hideInMenu)) {
      const obj = {
        icon: (item.meta && item.meta.icon) || '',
        name: item.name,
        meta: item.meta,
        path: item.path,
        redirect: item.redirect
      }
      if ((hasChild(item) || (item.meta && item.meta.showAlways)) && showThisMenuEle(item, access)) {
        obj.children = getMenuByRouter(item.children, access)
      }
      if (item.meta && item.meta.href) obj.href = item.meta.href
      if (showThisMenuEle(item, access)) res.push(obj)
    }
  })
  return res
}

// 其他工具函数 end
