<template>
  <section>
    <a-layout
      :class="{
          [`yo-layout--top-nav--${$root.global.settings.container}`]: $root.global.settings.layout === 'top-nav',
          [`yo-layout--${$root.global.settings.layout}`]: true,
        }"
    >
      <Sider :nav="nav" v-if="$root.global.settings.layout === 'left-menu'" />
      <a-layout>
        <Header :nav="nav" @reload="onReloadContentWindow" @setting="setting.visible = true" />
        <a-layout>
          <Content
            :panes="panes"
            :tabActived="tabActived"
            @change="onChangeContentWindow"
            @close="onCloseContentWindow"
            @close-other="onCloseOtherContentWindow"
            @close-right="onCloseRightContentWindow"
            ref="content"
          />
        </a-layout>
      </a-layout>
      <Sider :nav="nav" v-if="$root.global.settings.layout === 'right-menu'" />
    </a-layout>
    <Setting :visible="setting.visible" @close="setting.visible = false" />
  </section>
</template>
<script>
import Vue from 'vue';

import Header from './_layout/header';
import Sider from './_layout/sider/index';
import Content from './_layout/content';

import Setting from './setting';

import { EMPTY_ID, setGlobal } from '@/util/global';

const getNewID = () => {
  return Math.random().toString(16).slice(2);
};

export default {
  components: {
    Header,
    Sider,
    Content,
    Setting,
  },
  data() {
    return {
      panes: new Array(),
      tabActived: '',

      setting: {
        visible: false,
      },
      nav: {
        loading: false,
        content: [],
      },
    };
  },

  mounted() {
    Vue.prototype.openContentWindow = this.onOpenContentWindow;
    Vue.prototype.closeContentWindow = this.onCloseContentWindow;

    this.nav.loading = true;

    this.$api.getLoginUser().then(async ({ data }) => {
      // 去除应用和菜单信息,存储基本信息
      const info = this.$_.cloneDeep(data);
      delete info.apps;
      delete info.menus;
      setGlobal(info);

      this.nav.content = await this.onSetNav(data);
      this.nav.loading = false;

      this.$root.global.defaultWindow.map((options) => {
        this.onOpenContentWindow(options);
      });
    });
  },

  methods: {
    /**
     * 打开一个新的标签页
     * settings: {
     *  title: String,
     *  path: String,
     *  icon: String,
     *  param: Object,
     *  closable: Boolean = true,
     * }
     */
    onOpenContentWindow(settings) {
      if (settings.path) {
        const key = settings.key || getNewID();

        /**
         * 如果当前标签页已打开,则只需要选中
         */
        const pane = this.panes.find((p) => p.key === key);
        if (pane) {
          this.onChangeContentWindow(key);
          return;
        }

        const path = settings.path.startsWith('/') ? settings.path : `/${settings.path}`;

        /**
         * 向标签页队列中添加一个新的标签页
         */
        this.panes.push({
          key,
          closable: settings.closable === undefined ? true : settings.closable,
          icon: settings.icon,
          title: settings.title || '新建窗口',
          component: null,
          path,
          param: settings.param,
          loaded: false,
        });

        this.onChangeContentWindow(key);

        this.$refs.content.onLoadContentWindow(key);
      } else {
        console.warn('wrong component path');
      }
    },

    onCloseContentWindow(key) {
      key = key || this.tabActived;
      const i = this.$_.findIndex(this.panes, (p) => p.key === key);
      this.panes.splice(i, 1);

      if (this.panes.length) {
        if (key === this.tabActived) {
          const pane = this.panes[i];
          if (pane) {
            this.onChangeContentWindow(pane.key);
          } else {
            this.onChangeContentWindow(this.panes[i - 1].key);
          }
        }
      }
    },

    onCloseOtherContentWindow(key) {
      const panes = Object.assign([], this.panes);
      let flag = false;
      for (let i = panes.length - 1; i >= 0; i--) {
        const p = panes[i];
        if (p.key !== key && p.closable) {
          if (p.key === this.tabActived) {
            flag = true;
          }
          panes.splice(i, 1);
        }
      }
      this.panes = panes;
      if (flag) {
        this.onChangeContentWindow(this.$_.last(panes).key);
      }
    },

    onCloseRightContentWindow(key) {
      const panes = Object.assign([], this.panes);
      let flag = false;
      for (let i = panes.length - 1; i >= 0; i--) {
        const p = panes[i];
        if (p.key !== key && p.closable) {
          if (p.key === this.tabActived) {
            flag = true;
          }
          panes.splice(i, 1);
        } else if (p.key === key) {
          break;
        }
      }
      this.panes = panes;
      if (flag) {
        this.onChangeContentWindow(this.$_.last(panes).key);
      }
    },

    onChangeContentWindow(key) {
      this.tabActived = key;
    },

    onReloadContentWindow(key) {
      if (!key) key = this.tabActived;
      this.$refs.content.onLoadContentWindow(key);
    },

    onSetNav(nav) {
      const getNav = [];
      nav.apps.forEach((app) => {
        getNav.push({
          app,
        });
      });

      return this.$api
        .$queue(getNav.map((p) => this.$api.sysMenuChangeAwait({ application: p.app.code })))
        .then((menus) => {
          menus.forEach((menu, i) => {
            getNav[i].menu = this.serializeMenu(menu.data);
          });
          return getNav;
        });
    },

    serializeMenu(menus) {
      const menu = this.$_.cloneDeep(menus);
      const children = this.$_.groupBy(menu, 'pid');

      const serialize = (m) => {
        m.map((p) => {
          if (children[p.id]) {
            p.children = serialize(children[p.id]);
          }
        });
        return m;
      };

      return children[EMPTY_ID] ? serialize(children[EMPTY_ID]) : new Array();
    },
  },
};
</script>