import routerMap from '@/router/router.map'
import { mergeI18nFromRoutes } from '@/utils/i18n'
import Router from 'vue-router'
import deepMerge from 'deepmerge'
import basicOptions from '@/router/async/config.async'

//应用配置 初始化 
let appOptions = {
  router: undefined,
  i18n: undefined,
  store: undefined
}

/**
 * 设置应用配置
 * @param options
 */
function setAppOptions(options) { // 设置应用配置
  const { router, store, i18n } = options // 获取路由、状态管理、国际化
  appOptions.router = router // 路由
  appOptions.store = store // 状态管理
  appOptions.i18n = i18n // 国际化
}

/**
 * 根据 路由配置 和 路由组件注册 解析路由
 * @param routesConfig 路由配置
 * @param routerMap 本地路由组件注册配置
 */
function parseRoutes(routesConfig, routerMap) { // 解析路由
  let routes = [] // 初始化路由为空数组

  routesConfig.forEach(item => { // 遍历路由配置
    // 获取注册在 routerMap 中的 router，初始化 routeCfg
    let router = undefined, routeCfg = {} // 初始化路由和路由配置
    if (typeof item === 'string') { // 如果路由配置是字符串
      router = routerMap[item] // 从 routerMap 中获取路由
      routeCfg = { path: (router && router.path) || item, router: item } // 路由配置获取路由的 path 和 router
    } else if (typeof item === 'object') { // 如果路由配置是对象
      if(!item.router){
        return; 
      }
      router = routerMap[item.router] // 从 routerMap 中获取路由
      routeCfg = item // 路由配置为 item
    }
    if (!router) {  // 如果没有获取到路由 或者是路由不为数组及对象
      console.warn(`can't find register for router ${routeCfg.router}, please register it in advance.`) // 打印警告
      router = typeof item === 'string' ? { path: item, name: item } : item // 如果路由配置是字符串，路由为 {path: item, name: item}，否则为 item
    }
    // 从 router 和 routeCfg 解析路由
    const meta = { // 路由元信息
      authority: router.authority, // 路由权限
      icon: router.icon,  // 图标
      page: router.page, // 页面
      link: router.link, // 链接
      params: router.params, // 参数
      query: router.query, // 查询
      ...router.meta // 路由元信息
    }
    const cfgMeta = { // 路由配置元信息
      authority: routeCfg.authority, // 路由权限
      icon: routeCfg.icon, // 图标
      page: routeCfg.page, // 页面
      link: routeCfg.link, // 链接
      params: routeCfg.params, // 参数
      query: routeCfg.query, // 查询
      ...routeCfg.meta // 路由元信息
    }
    Object.keys(cfgMeta).forEach(key => { // 遍历路由配置元信息
      if (cfgMeta[key] === undefined || cfgMeta[key] === null || cfgMeta[key] === '') { // 如果路由配置元信息的值为 undefined、null、''
        delete cfgMeta[key] // 删除路由配置元信息的值
      }
    })
    Object.assign(meta, cfgMeta) // 合并路由元信息和路由配置元信息

    const route = {
      path: routeCfg.path || router.path || routeCfg.router, // 路由路径
      name: routeCfg.name || router.name, // 路由名称
      component: router.component, // 路由组件
      redirect: routeCfg.redirect || router.redirect, // 重定向
      meta: { ...meta, authority: meta.authority || '*' } // 路由元信息
    }
    if (routeCfg.invisible || router.invisible) { // 如果路由配置或者路由不可见
      route.meta.invisible = true
    }
    if (routeCfg.children && routeCfg.children.length > 0) { // 如果路由配置有子路由
      route.children = parseRoutes(routeCfg.children, routerMap)
    }
    routes.push(route)
  })
  return routes
}


// 根据权限过滤路由
function filterRoutesConfig(routes, permissions) {
  const res = []

  routes.forEach(route => {
    const tmp = { ...route }
    if (hasPermission(permissions, tmp)) {
      if (tmp.children) {
        tmp.children = filterRoutesConfig(tmp.children, permissions)
      }
      res.push(tmp)
    }
  })
  return res
}

// 判断是否有权限
function hasPermission(permissions, route) {
  if (route.meta && route.meta.authority && route.meta.authority.permission) {
    return permissions.some(permission => {
      return route.meta.authority.permission === '' || route.meta.authority.permission === permission
    })
  } else {
    return true
  }
}

//合并菜单项
function mergeMenus(routesConfig) {
  if (!routesConfig) return routesConfig;

  let root = routesConfig[0];

  let routes = [];
  let groups = ['basic']; //要合并的菜单项
  let appendedGroups = []; //已经处理的菜单项

  let children = JSON.parse(JSON.stringify(root.children));
  // console.log(children)
  root.children.forEach(item => {

    if (appendedGroups.filter(a => a == item.router).length) {
      return;
    }
    if (groups.filter(a => a == item.router).length) {
      let newItem = {
        authority: item.authority,
        icon: item.icon,
        name: item.name,
        router: item.router,
        children: []
      };
      children.forEach(subitem => {
        if (subitem.router == item.router) {
          subitem.children = subitem.children || [];
          newItem.children = [...newItem.children, ...subitem.children]; //合并子菜单项
        }
      });
      routes.push(newItem);
      appendedGroups.push(item.router);
    } else {

      routes.push(item);
    }
  }); 

  root.children = routes;
  return [root];

}
console.log(mergeMenus)

/**
 * 加载路由
 * @param routesConfig {RouteConfig[]} 路由配置
 */
function loadRoutes(routesConfig) { // 加载路由

  
  // 应用配置
  const { router, store, i18n } = appOptions

  //兼容 0.6.1 以下版本
  /*************** 兼容 version < v0.6.1 *****************/
  // if (arguments.length > 0) {  // 如果arguments的数量大于0
  //   const arg0 = arguments[0] // 获取第一个参数
  //   console.log("+++++arg0:",arg0)
  //   if (arg0.router || arg0.i18n || arg0.store) {
  //     routesConfig = arguments[1]
  //     console.log("+++++arguments[1]:",arguments[1])
  //     console.error('the usage of signature loadRoutes({router, store, i18n}, routesConfig) is out of date, please use the new signature: loadRoutes(routesConfig).')
  //     console.error('方法签名 loadRoutes({router, store, i18n}, routesConfig) 的用法已过时, 请使用新的方法签名 loadRoutes(routesConfig)。')
  //   }
  // }
  /*************** 兼容 version < v0.6.1 *****************/

  // console.log("=================routesConfig:")
  // console.log("=================routesConfig:"+routesConfig)
  //routesConfig = mergeMenus(routesConfig);
  if (!routesConfig) {
   var  routesconfig = store.getters['account/routesConfig']
    console.log("=================routesConfig:", routesconfig)
    if (!routesconfig) {
      return; 
    }else{
      routesConfig = routesconfig
    }
  }

  const Permission = store.getters['account/permissions'] //  获取权限
  if (routesConfig) { // 如果routesConfig已经存在 
    store.commit('account/setRoutesConfig', routesConfig) // 通过store的account模块的setRoutesConfig方法更新路由配置
  } else {
    routesConfig = store.getters['account/routesConfig'] // 通过store的account模块的routesConfig方法获取路由配置
  }
  // 如果 routesConfig 有值，则更新到本地，否则从本地获取

  // 根据权限过滤路由配置
  const filteredRoutesConfig = filterRoutesConfig(routesConfig, Permission) // 根据权限过滤路由配置
  // console.log("=====filteredRoutesConfig:", filteredRoutesConfig)
  filteredRoutesConfig
  // routesConfig = filteredRoutesConfig // 路由配置等于过滤后的路由配置

  // 如果开启了异步路由，则加载异步路由配置
  const asyncRoutes = store.state.setting.asyncRoutes // 获取store的setting模块的asyncRoutes
  if (asyncRoutes) { // 如果动态路由存在 

    if (routesConfig && routesConfig.length > 0) { // 如果本地路由配置存在 并且 数量大于0
      const routes = parseRoutes(routesConfig, routerMap) // 解析路由

      // 合并路由 生成路由表
      const finalRoutes = mergeRoutes(basicOptions.routes, routes)
      // 格式化路由
      formatRoutes(finalRoutes)
      router.options = { ...router.options, routes: finalRoutes } // 路由配置 
      router.matcher = new Router({ ...router.options, routes: [] }).matcher // 重置路由


      router.addRoutes(finalRoutes) // 添加路由


      //for (let x of finalRoutes) {
      //    router.addRoute(x)
      //}
    }
  }
  // 提取路由国际化数据
  mergeI18nFromRoutes(i18n, router.options.routes) // 合并路由国际化数据
  // 初始化Admin后台菜单数据
  const rootRoute = router.options.routes.find(item => item.path === '/') // 获取根路由
  const menuRoutes = rootRoute && rootRoute.children // 获取根路由的子路由
 
  if (menuRoutes) { // 如果子路由存在
    store.commit('setting/setMenuData', menuRoutes)  // 通过store的setting模块的setMenuData方法更新菜单数据
  }
}



/**
 * 合并路由
 * @param target {Route[]}
 * @param source {Route[]}
 * @returns {Route[]}
 */
function mergeRoutes(target, source) { // 合并路由
  const routesMap = {} // 路由映射表
  target.forEach(item => routesMap[item.path] = item) // 将target中的路由添加到路由映射表中
  source.forEach(item => routesMap[item.path] = item) // 将source中的路由添加到路由映射表中
  return Object.values(routesMap) // 返回路由映射表的值
}

/**
 * 深度合并路由
 * @param target {Route[]}
 * @param source {Route[]}
 * @returns {Route[]}
 */
function deepMergeRoutes(target, source) {
  // 映射路由数组
  const mapRoutes = routes => { // 映射路由数组
    const routesMap = {} // 路由映射表
    routes.forEach(item => { // 遍历路由
      routesMap[item.path] = { // 将路由添加到路由映射表中
        ...item,
        children: item.children ? mapRoutes(item.children) : undefined // 如果路由有子路由，则递归调用mapRoutes方法
      }
    })
    return routesMap // 返回路由映射表
  }
  const tarMap = mapRoutes(target) // 映射target
  const srcMap = mapRoutes(source) // 映射source

  // 合并路由
  const merge = deepMerge(tarMap, srcMap)

  // 转换为 routes 数组
  const parseRoutesMap = routesMap => {
    return Object.values(routesMap).map(item => {
      if (item.children) {
        item.children = parseRoutesMap(item.children)
      } else {
        delete item.children
      }
      return item
    })
  }
  return parseRoutesMap(merge)
}

/**
 * 格式化路由
 * @param routes 路由配置
 */
function formatRoutes(routes) { // 格式化路由
  routes.forEach(route => { // 遍历路由
    const { path } = route // 获取路由的path
    if (path && !path.startsWith('/') && path !== '*') { // 如果路由的path不是以/开头 并且 不是*
      route.path = '/' + path // 将路由的path添加/
    }
  })
  formatAuthority(routes) // 将路由的authority属性转换为meta.authority属性
}

/**
 * 格式化路由的权限配置
 * @param routes 路由
 * @param pAuthorities 父级路由权限配置集合
 */
function formatAuthority(routes, pAuthorities = []) { // 格式化路由的权限配置
  routes.forEach(route => { // 遍历路由
    const meta = route.meta // 获取路由的meta
    const defaultAuthority = pAuthorities[pAuthorities.length - 1] || { permission: '*' } // 获取默认权限 首先获取父级路由权限配置集合的最后一个元素，如果没有则获取{permission: '*'}
    if (meta) { // 如果meta存在
      let authority = {} // 权限
      if (!meta.authority) { // 如果meta.authority不存在
        authority = defaultAuthority // 权限为默认权限
      } else if (typeof meta.authority === 'string') { // 如果meta.authority是字符串
        authority.permission = meta.authority // 权限的permission为meta.authority
      } else if (typeof meta.authority === 'object') { // 如果meta.authority是对象
        authority = meta.authority // 权限为meta.authority
        const { role } = authority // 获取权限的role
        if (typeof role === 'string') { // 如果权限的role是字符串
          authority.role = [role] // 权限的role为数组
        }
        if (!authority.permission && !authority.role) { // 如果权限的permission和role都不存在
          authority = defaultAuthority // 权限为默认权限
        }
      }
      meta.authority = authority // 将权限赋值给meta.authority
    } else { // 如果meta不存在
      const authority = defaultAuthority // 权限为默认权限
      route.meta = { authority } // 将权限赋值给meta
    }
    route.meta.pAuthorities = pAuthorities // 将父级路由权限配置集合赋值给meta.pAuthorities
    if (route.children) { // 如果路由有子路由 递归调用formatAuthority方法
      formatAuthority(route.children, [...pAuthorities, route.meta.authority])
    }
  })
}

/**
 * 从路由 path 解析 i18n key
 * @param path
 * @returns {*}
 */
function getI18nKey(path) { // 从路由 path 解析 i18n key
  const keys = path.split('/').filter(item => !item.startsWith(':') && item != '') // 获取路由的path，将path以/分割，过滤掉以:开头的元素，过滤掉空元素
  keys.push('name') // 将name添加到keys中
  return keys.join('.') // 将keys以.连接
}

/**
 * 加载导航守卫 进度条
 * @param guards
 * @param options
 */
function loadGuards(guards, options) { // 加载导航守卫 guards 
  const { beforeEach, afterEach } = guards // 解构出 beforeEach 和 afterEach
  const { router } = options // 解构出 router
  beforeEach.forEach(guard => { // 遍历 beforeEach
    if (guard && typeof guard === 'function') { // 如果guard存在 并且 guard是函数
      router.beforeEach((to, from, next) => guard(to, from, next, options)) // 调用router.beforeEach方法
    }
  })
  afterEach.forEach(guard => { // 遍历 afterEach
    if (guard && typeof guard === 'function') { // 如果guard存在 并且 guard是函数
      router.afterEach((to, from) => guard(to, from, options)) // 调用router.afterEach方法
    }
  })
}

export { parseRoutes, loadRoutes, formatAuthority, getI18nKey, loadGuards, deepMergeRoutes, formatRoutes, setAppOptions }
