<template>
  <div class="frame-container bg-card" v-loading="!routesLoaded">
    <!-- 左边导航 -->
    <div v-show="!hideNav" id="side" class="bg-card slide-shadow select-none">
      <div
        class="slide-title d-flex flex-space align-center"
        :class="{ 'is-collapse': isCollapse }"
      >
        <div v-show="!isCollapse" class="nowrap" style="position: relative; width: 100%; height: 56px;">
          <span style="position: absolute; z-index: 2;">{{ appName }}</span>
        </div>
        <div v-show="isCollapse">&nbsp;</div>
        <!-- 折叠、展开功能 -->
        <div>
          <!-- 选中的icon -->
          <img
            v-show="isCollapse"
            class="icon-16 pointer hover-primary"
            style="display: block;"
            @click="handleToggleCollapse"
            :src="require('@/assets/icon/fold1.png')"
            title="展开"
            alt="icon"
          />
          <!-- 未选中的icon -->
          <img
            v-show="!isCollapse"
            class="icon-16 pointer hover-primary"
            style="display: block;"
            @click="handleToggleCollapse"
            :src="require('@/assets/icon/fold2.png')"
            title="折叠"
            alt="icon"
          />
        </div>
      </div>
      <hr v-show="!isCollapse" class="hr ml-20px" style="width: calc(100% - 40px);" />
      <hr v-show="isCollapse" class="hr" style="width: 40px; margin-left: 5px;" />

      <div class="menu-list">
        <el-menu
          class="el-menu-vertical-demo"
          unique-opened
          :default-active="activeIndex"
          @select="handleSelect"
          :collapse="isCollapse"
        >
          <div v-for="(item, index) in routes" :key="`菜单${index}`">
            <!-- <el-menu-item :index="citem.route" v-if="citem.type == '1'" class="menu-item">
              <template slot="title">
                <span>{{ citem.name }}</span>
              </template>
            </el-menu-item> -->
            <template v-if="hasChildren(item)">
              <el-submenu :index="item.route" v-if="item.type == '1'">
                <template slot="title">
                  <div
                    class="d-inline-block"
                    :class="[{'ml-0px mr-18px': isParentSelected(item)}, { 'mr-18px': !isCollapse }]"
                  >
                    <i class="iconfont" :class="[{'color-primary': isParentSelected(item) && isCollapse }, item.iconClass]"></i>
                  </div>
                  <span slot="title" v-show="!isCollapse">{{ item.name }}</span>
                </template>
                <el-menu-item-group v-for="sub in item.children" :key="sub.name">
                  <el-menu-item :index="sub.route" v-if="sub.type == '1'">
                    <template slot="title">
                      <span :title="sub.name" style="margin-left: 12px;">{{ sub.name }}</span>
                    </template>
                  </el-menu-item>
                </el-menu-item-group>
              </el-submenu>
            </template>
            <template v-else>
              <el-menu-item :index="item.route">
                <div class="d-inline-block" :class="[{'ml-0px mr-18px': isSelected(item)}, { 'mr-18px': !isCollapse }]">
                  <i class="iconfont" :class="item.iconClass"></i>
                </div>
                <span slot="title">{{ item.name }}</span>
              </el-menu-item>
            </template>
          </div>
        </el-menu>
      </div>
    </div>
    <!-- 右边内容区域 -->
    <div class="right-container">
      <slot name="content">
        <div v-show="!hideNav" class="sub-header bottom-shadow nowrap">
          <div class="d-flex space-between w-100 border-box">
            <div v-if="routesLoaded" id="sub-header-left" class="w-25 d-flex">
              <slot name="sub-header-left"></slot>
            </div>
            <div id="sub-header-center" class="w-50 d-flex text-center">
              <slot name="sub-header-center"></slot>
            </div>
            <div id="sub-header-right" class="w-25 d-flex">
              <slot name="sub-header-right"></slot>
            </div>
          </div>
        </div>
        <div class="content-box border-box p-20px">
          <div
            v-if="isLogin && routesLoaded"
            id="main-content"
            class="right-content p-20px bg-white card-shadow"
          >
            <slot>默认slot</slot>
          </div>
        </div>
      </slot>
    </div>
  </div>
</template>

<script>
import '@/store/store'
import { getMenuAuthAsync } from '@/api/common'
import { getToken } from '@/utils/login-helper.ts'
import routeIcons from './routeIcons.json'
import { ROUTES_KEY, ROUTES_MAP_KEY } from '@/constants'
import bus from 'vue3-eventbus'
import { isPathInMenuItem, getAllCoveredRoutes } from '@/utils/utils'
import { useWindowSize } from '@vueuse/core'

let routesMap = null

export default {
  name: 'koala-side',
  components: {},
  props: {
    // routes: {
    //   type: Array
    // },
    activeIndex: {
      type: String,
      default: ''
    },
    currentRoute: Object,
    hideNav: Boolean, // 隐藏左边导航
    hideSubHeader: Boolean, // 隐藏上边头部
  },
  data() {
    return {
      isCollapse: false,
      selectedIndex: '',
      parentSelectedIndex: '',
      minWidth: '100%',
      isLogin: false,
      routesLoaded: false,
      routes: [],
      user: {
        platforms: []
      },
      appName: '',
    }
  },
  computed:{},
  watch: {
    activeIndex: {
      handler() {
        this.selectedIndex = this.activeIndex
      },
      immediate: true
    },
  },
  created() {
    // 需要监听token值的变化
    bus.on('getAppKey', this.getAppKey)
    bus.on('tokenChange', this.handleTokenChange)
    bus.on('logout', this.handleLogout)
    bus.on('getAppName', this.getAppName)

    window.addEventListener('resize', this.handleResize, false)
    this.handleResize()
  },
  mounted() {},
  methods: {
    getAppKey(appKey) {
      const token = getToken()
      this.isLogin = !!token
      if (this.isLogin) {
        this.getMenuAuth(appKey)
      }
    },
    getAppName(appName) {
      this.appName = appName
    },
    // 窗口缩放
    handleResize() {
      const { width } = useWindowSize()
      this.isCollapse = width.value < 1300
    },
    // 退出登录
    handleLogout() {
      this.isLogin = false
      this.routesLoaded = false
      // this.routes = []
      // routesMap = null
    },
    // token变化，代表登录成功，开始获取菜单数据
    handleTokenChange(token) {
      if (token) {
        this.isLogin = true
        this.getMenuAuth()
      }
    },
    // 获取菜单数据
    getMenuAuth(appKey) {
      if (!appKey) return
      let localRoutesMap = {}
      try {
        localRoutesMap = JSON.parse(localStorage.getItem(ROUTES_MAP_KEY) || '{}')
        this.routes = localRoutesMap[appKey] || []
        this.setRoutesMap(this.routes)
      } catch (error) { }
      getMenuAuthAsync({ appKey }).then(async res => {
        if (res.status == 200) {
          this.routes = res.data
          // 设置iconClass
          this.routes.forEach(v => {
            v.iconClass = routeIcons.find(icon => icon.route.includes(v.route))?.icon || 'icon-apps'
          })
          this.setRoutesMap(this.routes)
          this.parentSelectedIndex = routesMap.get(this.activeIndex)?.route

          const routesStr = JSON.stringify(this.routes)
          this.$emit('getRoutes', JSON.parse(routesStr))
          // 如果当前菜单没有权限则默认定位到路由的第一个菜单
          if (this.routes && this.routes.length) {
            // 判断当前路由是否在后端返回的菜单中
            const flag = this.routes.some(item => isPathInMenuItem(item, this.$route.path, 'dynamic'))
            // 如果没在，并且当前路由有meta.code，说明当前是没有权限的页面
            if (!flag && this.$route.meta.hasOwnProperty('code')) {
              // 一般一定会有静态路由
              if (this.$router.options.routes[0] && this.$router.options.routes[0].children) {
                const staticRoutes = this.$router.options.routes[0].children
                const rightRoute = getAllCoveredRoutes(staticRoutes, this.routes)
                // // 循环静态路由，找到第一个后端返回和静态路由集合中都有的路由
                // for (const staticItem of staticRoutes) {
                //   const rightOne = this.routes.find(item => isPathInMenuItem({
                //     ...staticItem,
                //     route: `/${staticItem.path}`
                //   }, item.route))
                //   if (rightOne) {
                //     rightRoute = rightOne
                //     break
                //   }
                // }
                //跳转
                if (rightRoute) {
                  this.$router.replace(rightRoute)
                } else {
                  this.$router.replace('/404')
                }
              }
            }
          } else {
            this.$router.replace('/404')
          }
          // 缓存当前routes
          localStorage.setItem(ROUTES_KEY, routesStr)
          // // 根据appKey缓存当前routes
          // localRoutesMap = Object.assign(localRoutesMap, { [appKey]: this.routes })
          // localStorage.setItem(ROUTES_MAP_KEY, JSON.stringify(localRoutesMap))
          this.routesLoaded = true
        }
      })
    },
    setRoutesMap(routes) {
      routesMap = new Map()
      routes.forEach((parent) => {
        parent.children?.forEach(child => {
          if (child.route) {
            routesMap.set(child.route, parent)
          }
        })
      })
    },
    // 判断是否有子导航菜单
    hasChildren(item) {
      if (item.children && item.children.length > 0) {
        let first = item.children[0]
        if (first.route) {
          return true
        } else {
          return false
        }
      }
      return false
    },
    // 当前节点是否选中
    isSelected(item) {
      return item.route === this.selectedIndex
    },
    // 父节点是否选中
    isParentSelected(parent) {
      if (routesMap.get(this.selectedIndex)) {
        return routesMap.get(this.selectedIndex).route === parent.route
      }
    },
    // 选中回调
    handleSelect(index, indexPath) {
      this.parentSelectedIndex = indexPath['0']
      this.selectedIndex = index
      this.$emit('handleSelect', index)
    },
    // 折叠、展开
    handleToggleCollapse() {
      this.isCollapse = !this.isCollapse
    },
  },
  destroyed() {
    window.removeEventListener('resize', this.handleResize)
  }
}
</script>

<style lang="scss" scoped>
$sub-header-height: 56px;
// 右边（除开导航菜单）最小宽度
$content-min-width: 1180px;

.frame-container {
  display: flex;
  justify-content: space-between;
  box-sizing: border-box;
  width: 100%;
  height: calc(100vh - 51px);
  overflow-y: auto;
  .right-container {
    width: 100%;
    overflow: hidden;
    .sub-header {
      display: flex;
      justify-content: space-between;
      box-sizing: border-box;
      // margin-left: 4px;
      padding: 0 20px;
      width: calc(100% - 4px);
      height: $sub-header-height + 1px;
      line-height: $sub-header-height + 1px;
      border-bottom: 1px solid var(--color-border);
      background-image: url('@/assets/img/sub-header.png');
      background-size: 100% 100%;
      .sub-header-left {
        font-weight: 600;
      }
    }
    .content-box {
      height: calc(100% - 60px);
      overflow-y: auto;
    }
  }
}

#side {
  height: calc(100vh - 51px);
  overflow-x: hidden;
  overflow-y: auto;
  box-sizing: border-box;
  flex-shrink: 0;
  &.slide-shadow {
    box-shadow: 1px 0 4px 0 rgba(33, 76, 217, 0.1);
    border-right: 1px solid var(--color-border);
  }
  .slide-title {
    padding: 0 20px;
    height: $sub-header-height;
    line-height: $sub-header-height;
    &.is-collapse {
      padding: 0 16px;
    }
  }
}

#main-content {
  padding: 24px;
  border-radius: 4px;
  box-sizing: border-box;
  min-height: 100%;
  min-width: $content-min-width;
}

::v-deep #sub-header-left {
  .el-breadcrumb {
    line-height: $sub-header-height;
  }
}
</style>
