<template>
  <div class="app-wrapper">
    <nav-bar :navs="navs" @on-nav-change="navChange" v-if="navs.length" />
    <side-bar class="sidebar-container" :menus="curMenus" />
    <div class="main-container">
      <app-main />
      <app-footer />
    </div>
  </div>
</template>

<script>
import AppMain from "./components/AppMain.vue";
import AppFooter from "./components/AppFooter.vue";
import SideBar from "./components/SideBar.vue";
import NavBar from "./components/NavBar.vue";
import { sysMenu } from "@/api/system-user";
import localMenu from "./components/menu";
import { deepCopy } from "@/utils/utils";
import { mapActions } from "vuex";

export default {
  name: "Layout",
  components: {
    NavBar,
    SideBar,
    AppMain,
    AppFooter,
  },
  data() {
    return {
      curMenus: [],
      navs: [],
      curNavName: "",
      validRoutes: [],
      loopSetTs: [],
      loopFuncList: [],
      loopRunning: false,
    };
  },
  created() {
    this.getMenu();
  },
  methods: {
    ...mapActions("invigilation", [
      "fetchRealtimeMonitoringCount",
      "fetchWarningManageCount",
      "fetchReexamPendingCount",
    ]),
    navChange(name) {
      if (this.curNavName === name) return;

      this.curNavName = name;
      const nav = this.navs.find((item) => item.name === name);
      this.curMenus = nav.children || [];

      if (name === "Invigilation") {
        this.initNavTips();
        if (!this.loopFuncList.length) return;
        this.loopRunning = true;
        this.timerUpdatePage();
      } else {
        this.loopRunning = false;
        this.clearLoopSetTs();
      }
    },
    async getMenu() {
      const res = await sysMenu();
      this.navs = this.menusToTree(res.data.data);

      const curRouterName = this.$route.meta.relate || this.$route.name;
      if (curRouterName === "Home") {
        this.$router.replace({
          name: this.navs[0].redirect,
        });
      } else {
        if (!this.validRoutes.includes(curRouterName)) {
          this.$router.replace({
            name: "404",
          });
          return;
        }
      }
    },
    buildLocalNavs() {
      const dmenu = deepCopy(localMenu);
      let localNavs = dmenu.headerMenuConfig;
      localNavs.map((item) => {
        item.children = dmenu[`${item.name.toLowerCase()}MenuConfig`];
      });
      return localNavs;
    },
    menusToTree(menus) {
      let localNavs = this.buildLocalNavs();
      const validRoutes = menus.map((menu) => menu.url);
      const anchorNav = (navs) => {
        let navHasAnchor = false;
        navs.forEach((item) => {
          let isFixed = validRoutes.includes(item.name);
          if (item.children && item.children.length) {
            isFixed = anchorNav(item.children);
          }
          item.fixed = isFixed;
          navHasAnchor = navHasAnchor || isFixed;
        });
        return navHasAnchor;
      };
      anchorNav(localNavs);

      const clearNoFixed = (navs) => {
        let list = [];
        navs.forEach((nav) => {
          if (nav["fixed"]) {
            let navItem = { title: nav.title, name: nav.name };
            if (nav.icon) navItem.icon = nav.icon;
            if (nav["children"])
              navItem.children = clearNoFixed(nav["children"]);
            list.push(navItem);
          }
        });
        return list;
      };

      this.validRoutes = validRoutes;
      this.validRoutes.push("Home");
      let navs = clearNoFixed(localNavs);
      navs.map((item) => {
        if (
          item.children[0] &&
          item.children[0].children[0] &&
          item.children[0].children[0].name
        )
          item.redirect = item.children[0].children[0].name;
      });
      return navs;
    },
    clearLoopSetTs() {
      if (!this.loopSetTs.length) return;
      this.loopSetTs.forEach((sett) => {
        clearTimeout(sett);
      });
      this.loopSetTs = [];
    },
    async timerUpdatePage() {
      this.clearLoopSetTs();
      if (!this.loopRunning) return;

      const user = this.$store.state.user;
      const datas = user.roleCodes.includes("INVIGILATE")
        ? { userId: user.id }
        : {};

      const fetchAll = this.loopFuncList.map((item) => item.call(this, datas));
      await Promise.all(fetchAll).catch(() => {});

      this.loopSetTs.push(
        setTimeout(() => {
          this.timerUpdatePage();
        }, 10 * 1000)
      );
    },
    initNavTips() {
      let validNav = {
        RealtimeMonitoring: {
          valid: false,
          func: this.fetchRealtimeMonitoringCount,
        },
        WarningManage: {
          valid: false,
          func: this.fetchWarningManageCount,
        },
        ReexamPending: {
          valid: false,
          func: this.fetchReexamPendingCount,
        },
      };
      const validNavNames = Object.keys(validNav);
      this.curMenus.forEach((nav) => {
        nav.children.forEach((subnav) => {
          if (validNavNames.includes(subnav.name)) {
            validNav[subnav.name].valid = true;
          }
        });
      });

      let loopFuncList = [];
      validNavNames.forEach((item) => {
        if (validNav[item].valid) loopFuncList.push(validNav[item].func);
      });
      this.loopFuncList = loopFuncList;
    },
  },
  beforeDestroy() {
    this.loopRunning = false;
    this.clearLoopSetTs();
  },
};
</script>

<style lang="scss" scoped>
.app-wrapper {
  position: relative;
  height: 100%;
  width: 100%;
  &:after {
    content: "";
    display: table;
    clear: both;
  }
}
.main-container {
  min-height: 100vh;
  transition: margin-left 0.28s;
  margin-left: 220px;
  padding-top: 60px;
  padding-bottom: 34px;
  background-color: #f0f4f9;
  position: relative;
}
.sidebar-container {
  background: #fff;
  transition: width 0.28s;
  width: 220px !important;
  top: 60px;
  position: fixed;
  bottom: 0;
  left: 0;
  z-index: 1001;
  overflow: hidden;
}
</style>
