<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"
        @change-app="onChangeApp"
        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 { setGlobal } from '@/common/login';
import { ACTIVE_APP_KEY } from '@/common/storage';

import { EMPTY_ID } 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,
        apps: [],
        menus: [],
      },
    };
  },

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

    this.nav.loading = true;

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

      data.apps.map((p) => (p.active = p.active));
      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);
    },

    onChangeApp(app) {
      this.nav.loading = true;
      this.$api.sysMenuChange({ application: app.code }).then(({ data }) => {
        this.nav.apps.map((p) => (p.active = p.code === app.code));
        window.localStorage.removeItem(ACTIVE_APP_KEY);
        this.onSetNav({
          apps: this.nav.apps,
          menus: data,
        });

        this.nav.loading = false;
      });
    },

    onSetNav(nav) {
      // 从本地存储获取当前选中的应用及菜单
      this.nav.apps = nav.apps;
      const code = window.localStorage.getItem(ACTIVE_APP_KEY);
      if (code) {
        this.nav.apps.map((p) => (p.active = p.code === code.code));
        this.onChangeApp({
          code,
        });
      } else {
        // 将默认选中菜单存储
        const app = nav.apps.find((p) => p.active);
        if (app) {
          window.localStorage.setItem(ACTIVE_APP_KEY, app.code);
          this.serializeMenu(nav.menus);
        }
      }
    },

    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;
      };

      this.nav.menus = children[EMPTY_ID] ? serialize(children[EMPTY_ID]) : new Array();
    },
  },
};
</script>