<template>
  <Layout class="i-layout">
    <Sider v-if="!isMobile && !hideSider" class="i-layout-sider" :class="siderClasses" :width="menuSideWidth">
      <i-menu-side :hide-logo="isHeaderStick && headerFix && showHeader" />
    </Sider>
    <Layout class="i-layout-inside" :class="insideClasses">
      <transition name="fade-quick">
        <Header class="i-layout-header" :class="headerClasses" :style="headerStyle" v-show="showHeader" v-resize="handleHeaderWidthChange">
          <i-header-logo v-if="isMobile && showMobileLogo" />
          <i-header-logo v-if="!isMobile && isHeaderStick && headerFix" />
          <i-header-collapse v-if="(isMobile || showSiderCollapse) && !hideSider" @on-toggle-drawer="handleToggleDrawer" />
          <i-header-reload v-if="!isMobile && showReload" @on-reload="handleReload" />
          <i-menu-head v-if="headerMenu && !isMobile" ref="menuHead" />
          <i-header-breadcrumb v-if="showBreadcrumb && !headerMenu && !isMobile" ref="breadcrumb" />
          <i-header-search v-if="showSearch && !headerMenu && !isMobile && !showBreadcrumb" />
          <div class="i-layout-header-right">
            <slot name="header" />
            <slot name="search">
              <i-header-search v-if="(showSearch && isMobile) || (showSearch && (headerMenu || showBreadcrumb))" />
            </slot>
            <i-menu-head v-if="headerMenu && isMobile" />
            <!-- <i-header-log v-if="isDesktop && showLog" /> -->
            <i-header-fullscreen v-if="isDesktop && showFullscreen" />
            <slot name="notice">
              <i-header-notice ref="notice" v-if="showNotice" />
            </slot>
            <slot name="user">
              <i-header-user />
            </slot>
            <slot name="i18n">
              <i-header-i18n v-if="showI18n" />
            </slot>
            <slot name="setting">
              <i-header-setting v-if="enableSetting && !isMobile" />
            </slot>
          </div>
        </Header>
      </transition>
      <Content class="i-layout-content" :class="contentClasses">
        <transition name="fade-quick">
          <i-tabs v-if="tabs" v-show="showHeader" @on-reload="handleReload" />
        </transition>
        <div class="i-layout-content-main">
          <router-view #default="{ Component }">
            <keep-alive :include="keepAlive">
              <component :is="Component" :key="$route.name" v-if="loadRouter" />
            </keep-alive>
          </router-view>
        </div>
      </Content>
      <i-copyright />
    </Layout>
    <div v-if="isMobile && !hideSider">
      <Drawer v-model="showDrawer" placement="left" :closable="false" :class-name="drawerClasses">
        <i-menu-side />
      </Drawer>
    </div>
    <i-water-mark />
  </Layout>
</template>
<script>
  import { nextTick } from 'vue';
  import { mapState, mapGetters, mapMutations } from 'vuex';

  import iMenuHead from './menu-head/index.vue';
  import iMenuSide from './menu-side/index.vue';
  import iHeaderLogo from './header-logo/index.vue';
  import iHeaderCollapse from './header-collapse/index.vue';
  import iHeaderReload from './header-reload/index.vue';
  import iHeaderBreadcrumb from './header-breadcrumb/index.vue';
  import iHeaderSearch from './header-search/index.vue';
  import iHeaderLog from './header-log/index.vue';
  import iHeaderFullscreen from './header-fullscreen/index.vue';
  import iHeaderNotice from './header-notice/index.vue';
  import iHeaderUser from './header-user/index.vue';
  import iHeaderI18n from './header-i18n/index.vue';
  import iHeaderSetting from './header-setting/index.vue';
  import iTabs from './tabs/index.vue';
  import iWaterMark from './water-mark/index.vue';
  import iCopyright from '../../components/copyright/index.vue';

  import Setting from '../../setting';

  export default {
    name: 'BasicLayout',
    components: {
      iMenuHead,
      iMenuSide,
      iCopyright,
      iHeaderLogo,
      iHeaderCollapse,
      iHeaderReload,
      iHeaderBreadcrumb,
      iHeaderSearch,
      iHeaderUser,
      iHeaderI18n,
      iHeaderLog,
      iHeaderFullscreen,
      iHeaderSetting,
      iHeaderNotice,
      iTabs,
      iWaterMark
    },
    data() {
      return {
        showDrawer: false,
        ticking: false,
        headerVisible: true,
        oldScrollTop: 0,
        isDelayHideSider: false, // hack，当从隐藏侧边栏的 header 切换到正常 header 时，防止 Logo 抖动
        loadRouter: true
      };
    },
    computed: {
      ...mapState('admin/layout', [
        'siderTheme',
        'headerTheme',
        'headerStick',
        'tabs',
        'tabsFix',
        'siderFix',
        'headerFix',
        'headerHide',
        'headerMenu',
        'isMobile',
        'isTablet',
        'isDesktop',
        'menuCollapse',
        'showMobileLogo',
        'showSearch',
        'showNotice',
        'showFullscreen',
        'showSiderCollapse',
        'showBreadcrumb',
        'showLog',
        'showI18n',
        'showReload',
        'enableSetting'
      ]),
      ...mapState('admin/page', ['keepAlive']),
      ...mapGetters('admin/menu', ['hideSider']),
      // 如果开启 headerMenu，且当前 header 的 hideSider 为 true，则将顶部按 headerStick 处理
      // 这时，即使没有开启 headerStick，仍然按开启处理
      isHeaderStick() {
        let state = this.headerStick;
        if (this.hideSider) state = true;
        return state;
      },
      showHeader() {
        let visible = true;
        if (this.headerFix && this.headerHide && !this.headerVisible) visible = false;
        return visible;
      },
      headerClasses() {
        return [
          `i-layout-header-color-${this.headerTheme}`,
          {
            'i-layout-header-fix': this.headerFix,
            'i-layout-header-fix-collapse': this.headerFix && this.menuCollapse,
            'i-layout-header-mobile': this.isMobile,
            'i-layout-header-stick': this.isHeaderStick && !this.isMobile,
            'i-layout-header-with-menu': this.headerMenu,
            'i-layout-header-with-hide-sider': this.hideSider || this.isDelayHideSider
          }
        ];
      },
      headerStyle() {
        const menuWidth = this.isHeaderStick ? 0 : this.menuCollapse ? Setting.menuSideCollapseWidth : Setting.menuSideWidth;
        return this.isMobile || !this.headerFix
          ? {}
          : {
              width: `calc(100% - ${menuWidth}px)`
            };
      },
      siderClasses() {
        return {
          'i-layout-sider-fix': this.siderFix,
          'i-layout-sider-dark': this.siderTheme === 'dark'
        };
      },
      contentClasses() {
        return {
          'i-layout-content-fix-with-header': this.headerFix,
          'i-layout-content-with-tabs': this.tabs,
          'i-layout-content-with-tabs-fix': this.tabs && this.tabsFix
        };
      },
      insideClasses() {
        return {
          'i-layout-inside-fix-with-sider': this.siderFix,
          'i-layout-inside-fix-with-sider-collapse': this.siderFix && this.menuCollapse,
          'i-layout-inside-with-hide-sider': this.hideSider,
          'i-layout-inside-mobile': this.isMobile
        };
      },
      drawerClasses() {
        let className = 'i-layout-drawer';
        if (this.siderTheme === 'dark') className += ' i-layout-drawer-dark';
        return className;
      },
      menuSideWidth() {
        return this.menuCollapse ? Setting.menuSideCollapseWidth : Setting.menuSideWidth;
      }
    },
    watch: {
      hideSider() {
        this.isDelayHideSider = true;
        setTimeout(() => {
          this.isDelayHideSider = false;
        }, 0);
      },
      $route(to, from) {
        if (to.name === from.name) {
          // 相同路由，不同参数，跳转时，重载页面
          if (Setting.sameRouteForceUpdate) {
            this.handleReload();
          }
        }
      }
    },
    methods: {
      ...mapMutations('admin/layout', ['updateMenuCollapse']),
      ...mapMutations('admin/page', ['keepAlivePush', 'keepAliveRemove']),
      handleToggleDrawer(state) {
        if (typeof state === 'boolean') {
          this.showDrawer = state;
        } else {
          this.showDrawer = !this.showDrawer;
        }
      },
      handleScroll() {
        if (!this.headerHide) return;

        const scrollTop = document.body.scrollTop + document.documentElement.scrollTop;

        if (!this.ticking) {
          this.ticking = true;

          requestAnimationFrame(() => {
            if (this.oldScrollTop > scrollTop) {
              this.headerVisible = true;
            } else if (scrollTop > 300 && this.headerVisible) {
              this.headerVisible = false;
            } else if (scrollTop < 300 && !this.headerVisible) {
              this.headerVisible = true;
            }
            this.oldScrollTop = scrollTop;
            this.ticking = false;
          });
        }
      },
      handleHeaderWidthChange() {
        const $breadcrumb = this.$refs.breadcrumb;
        if ($breadcrumb) {
          $breadcrumb.handleGetWidth();
          $breadcrumb.handleCheckWidth();
        }
        const $menuHead = this.$refs.menuHead;
        if ($menuHead) {
          // todo $menuHead.handleGetMenuHeight();
        }
      },
      handleReload() {
        // 针对缓存的页面也生效
        const isCurrentPageCache = this.keepAlive.indexOf(this.$route.name) > -1;
        const pageName = this.$route.name;
        if (isCurrentPageCache) {
          this.keepAliveRemove(pageName);
        }
        this.loadRouter = false;
        nextTick(() => {
          this.loadRouter = true;
          if (isCurrentPageCache) {
            this.keepAlivePush(pageName);
          }
        });
      }
    },
    mounted() {
      document.addEventListener('scroll', this.handleScroll, { passive: true });

      // 非移动端，根据系统缩放比率调整界面大小
      if (
        Setting.layout.autoFixRatio == true &&
        window.screen.width < 1920 &&
        window.screen.width * window.devicePixelRatio <= 1920 &&
        !navigator.userAgent.match(/AppleWebKit.*Mobile.*/) &&
        !navigator.userAgent.match(/.*Android.*/)
      ) {
        document.body.style.zoom = 1 / window.devicePixelRatio;

        // document.body.style.transform = 'scale(' + 1 / window.devicePixelRatio + ')';
        // document.body.style.transformOrigin = '0%0%';
        // document.body.style.width = window.devicePixelRatio * 100 + '%';

        setTimeout(() => {
          let sider = document.getElementsByClassName('i-layout-sider');
          if (sider.length > 0) {
            sider[0].style.height = window.devicePixelRatio * 100 + 'vh';
          }
          var menu = document.getElementsByClassName('i-layout-menu-side');
          if (menu.length > 0) {
            menu[0].style.height = 'calc(' + window.devicePixelRatio * 100 + 'vh - 64px)';
          }
        });
      }
    },
    beforeUnmount() {
      document.removeEventListener('scroll', this.handleScroll);
    },
    created() {
      if (this.isTablet && this.showSiderCollapse) this.updateMenuCollapse(true);
    }
  };
</script>
