<template>
  <el-config-provider :locale="language">
    <div class="h-100 flex-column level-0">
      <router-view />
      <!-- 超时提醒框 -->
      <Dialog ref="timeoutRef" class="timeout" :config="timeoutConfig" @close="timeoutHandle">
        <template #other>
          <div class="timeout-container">
            <div class="icon">
              <el-icon :size="24"><IconError /></el-icon>
            </div>
            <div class="content">
              <h3>{{ traduction('COMMON_ERROR') }}</h3>
              <p>{{ timeoutMessage }}</p>
            </div>
          </div>
        </template>
      </Dialog>

      <el-tooltip
        v-model:visible="tooltipVisible"
        :content="tooltipContent"
        placement="top"
        trigger="hover"
        virtual-triggering
        :virtual-ref="tooltipTriggerRef"
        trigger-keys
      />
    </div>
    <div id="customizedHomepage"></div>
  </el-config-provider>
</template>

<script setup lang="ts">
// 这里设置全局的softwareName的值
import useStore from '@/stores';
import zhCn from 'element-plus/es/locale/lang/zh-cn';
import en from 'element-plus/es/locale/lang/en';
import fr from 'element-plus/es/locale/lang/fr';
import ja from 'element-plus/es/locale/lang/ja';
import ru from 'element-plus/es/locale/lang/ru';
import $http, { IbmcHttp } from '@/utils/http-service';
import { onMounted, reactive, ref, watch } from 'vue';
import { getStoreData, setStoreData } from './utils/composition';
import { traduction } from './utils/language';
import { IconError } from '@computing/opendesign-icons';
import { useRouter } from 'vue-router';
import { RouterChangeReason } from './model/base-enum';
import { UI_RESET_SESSIONS, UI_RESET_LOGINOUT } from './api/api';
import { clearCurrentLoginInfo } from './utils/common-service';
import { authorizeGuard } from './apps/app-bmc/guard/authorize.guard';
import {
  getBrowserType,
  isIE11,
  isSafari,
  urlReplace,
  escapeHeader,
  updateLocalLoginCount
} from './utils/utils';
import { ROUTER_BASE } from '@/model/router-utils';
import { tooltipVisible, tooltipContent, tooltipTriggerRef } from '@/directive/mouseEventDirective';

const store = useStore();
const router = useRouter();
const timeoutRef = ref();
const timeoutMessage = ref('');
const allowHttpDelete = getStoreData('loct', 'allowHttpDelete');

const timeoutConfig = reactive({
  title: traduction('COMMON_INFORMATION'),
  content: '',
  closeIcon: false,
  cancelButton: {
    hide: true
  }
});

let language: any = zhCn;
const localeKey = getStoreData('loct', 'locale');
switch (localeKey) {
  case 'en': {
    language = en;
    break;
  }
  case 'ja': {
    language = ja;
    break;
  }
  case 'ru': {
    language = ru;
    break;
  }
  case 'fr': {
    language = fr;
    break;
  }
  default: {
    language = zhCn;
  }
}

// 点击超时确认按钮时的回调
function timeoutHandle() {
  timeoutRef.value.hide();
  IbmcHttp.errorCount = 0;
  router.push('/login');
  setTimeout(() => {
    self.location.reload();
  }, 1000);
}
/* eslint-disable-next-line max-lines-per-function*/
onMounted(() => {
  // 监听error401错误, 页面注销时无需取消监听,因为这是顶级App根组件,若发生unMounted,则页面不是刷新就是关闭
  watch(
    () => store.state.event.error401,
    newVal => {
      // 1. 已经超时 2.登录页 3.路由为空 这3种情况下,忽略401错误弹窗
      const path = router.currentRoute.value.fullPath;
      if (
        getStoreData('glob', 'isTimeOut') ||
        path.indexOf('login') > -1 ||
        path === '' ||
        path === '/'
      ) {
        return;
      }
      clearCurrentLoginInfo();
      setStoreData('glob', 'isTimeOut', true);
      timeoutMessage.value = newVal.replace(/\d/g, '');
      timeoutRef.value.show();
    }
  );

  /**
   * 路由跳转错误,主要包括以下几种,
   * 1. 用户未登录, (跳转到登录页)
   * 2. 路由路径不存在 (已登录时,跳转到首页,未登录时跳转到登录页)
   * 3. 用户无权限访问路由 (跳转到登录页,若已经登录,则注销会话)
   */
  watch(
    () => store.state.event.routeChangeError,
    newVal => {
      const val = newVal.replace(/(\.|\d)/g, '');
      switch (val) {
        case RouterChangeReason.notLogin:
          router.push('/login');
          break;
        case RouterChangeReason.invalid:
          router.push('/navigate/home');
          break;
        case RouterChangeReason.noPermission: {
          const rn = getStoreData('loct', 'rn');
          if (rn) {
            const request = allowHttpDelete
              ? $http.delete(urlReplace(UI_RESET_LOGINOUT, { sid: rn }))
              : $http.post(UI_RESET_SESSIONS, { RequestMethod: 'DELETE', SessionId: rn });
            request.finally(() => {
              clearCurrentLoginInfo();
            });
          }
          setTimeout(() => router.push('/login'), 1000);
          break;
        }
        default:
          router.push('/navigate/home');
          break;
      }
    }
  );

  // 绑定全局路由鉴权事件
  router.beforeEach((to, from, next) => {
    // 若地址参数的pathname不符合标准,重置pathname
    if (self.location.pathname !== ROUTER_BASE) {
      self.location.pathname = ROUTER_BASE || '/';
    }

    // 检查hash值是否是合法的
    const position = to.fullPath.lastIndexOf('navigate');
    if (position > -1 && !to.fullPath.includes('login') && position !== 1) {
      self.location.hash = '#/' + to.fullPath.slice(position);
    }

    const result = authorizeGuard(to);
    if (result) {
      next();
    }
  });

  // 绑定页面点击事件,发送KeepAlive请求(登录页不发送保持会话请求)
  document.addEventListener('click', sendActived);

  /**
   * tab页切换时,触发刷新操作, 登录页直接进入到Home
   * visibilitychange事件触发的场景
   * 1.页面刷新 2.tab页切换 3.tab页关闭 4.浏览器关闭
   */
  document.addEventListener('visibilitychange', () => {
    const path = router?.currentRoute?.value?.fullPath;
    if (path?.indexOf('kvm_h5') > -1 || path?.indexOf('videoPlayer') > -1) {
      return;
    }
    const loct = localStorage.getItem('loct');
    const loctJson = loct ? JSON.parse(loct) : null;
    if (loctJson) {
      const rn = getStoreData('loct', 'rn');
      if (rn === loctJson.rn) {
        return;
      }
      self.location.reload();
    }
  });

  let tabsCount = JSON.parse(localStorage.getItem('tabs') || '0');
  const tabValid = sessionStorage.getItem('tabIsValid');
  if (tabValid) {
    tabsCount++;
    localStorage.setItem('tabs', JSON.stringify(tabsCount));
  }

  // 绑定刷新浏览器时,注销会话事件
  window.addEventListener('beforeunload', () => {
    let tabIsValidUnload = JSON.parse(sessionStorage.getItem('tabIsValid') || 'null');
    if (tabIsValidUnload) {
      let tabsUnload = JSON.parse(localStorage.getItem('tabs') || '0');
      tabsUnload--;
      localStorage.setItem('tabs', JSON.stringify(tabsUnload));
    }
    const isValid = sessionStorage.getItem('tabIsValid');
    if (isValid) {
      const tabIsValid = JSON.parse(isValid);
      if (!tabIsValid) {
        return;
      }
    }

    // IE11, 苹果浏览器直接注销会话,不判断有几个Tab页(因为这2个浏览器关闭时是全部一起关闭的,不会出现顺序关闭Tab页,导致tabs数量无法递减到0)
    if (isIE11() || isSafari()) {
      sendDeactive();
    } else {
      const tabs = JSON.parse(localStorage.getItem('tabs') as string);
      if (tabs !== null && tabs <= 0) {
        sendDeactive();
      }
    }
  });

  // 通过keepALive 关闭浏览器时注销会话
  function sendDeactive(): void {
    const browser = getBrowserType();
    // IE11,火狐需发同步请求
    if (isIE11() || browser.browser === 'firefox') {
      const xml = new XMLHttpRequest();
      const data = JSON.stringify({ Mode: 'Deactivate' });
      xml.open('POST', '/UI/Rest/KeepAlive', false);
      xml.withCredentials = true;
      xml.setRequestHeader('From', 'WebUI');
      xml.setRequestHeader('Content-Type', 'application/json');
      xml.setRequestHeader('X-CSRF-Token', escapeHeader(getStoreData('loct', 'to')));
      xml.send(data);
    } else {
      $http.keepAlive('Deactivate');
    }
  }

  // 发送keepAlive
  function sendActived() {
    const path = router.currentRoute.value.fullPath;
    if (path.indexOf('login') === -1 && path.indexOf('kvm_h5') === -1) {
      $http.keepAlive('Activate');
    }
  }
});
</script>

<style scoped lang="scss">
:deep(.timeout-container) {
  display: flex;
  .content {
    margin-left: 16px;
    h3 {
      font-size: 16px;
      line-height: 24px;
      color: var(--o-text-color-primary);
    }
    p {
      margin-top: 16px;
    }
  }
}
</style>