<template>
  <div
    :class="{
      'tabs-view-default-background': getDarkTheme === false,
      'tabs-view-dark-background': getDarkTheme === true,
    }"
    :style="getChangeStyle"
    class="tabs-view"
  >
    <div class="tabs-view-main">
      <div ref="navWrap" :class="{ 'tabs-card-scrollable': scrollable }" class="tabs-card">
        <span
          :class="{ 'tabs-card-prev-hide': !scrollable }"
          class="tabs-card-prev"
          @click="scrollPrev"
        >
          <el-icon class="el-input__icon" size="16">
            <LeftOutlined />
          </el-icon>
        </span>
        <span
          :class="{ 'tabs-card-next-hide': !scrollable }"
          class="tabs-card-next"
          @click="scrollNext"
        >
          <el-icon class="el-input__icon" size="16">
            <RightOutlined />
          </el-icon>
        </span>
        <div ref="navScroll" class="tabs-card-scroll">
          <Draggable :list="tabsList" animation="300" class="flex" item-key="fullPath">
            <template #item="{ element, index }">
              <div
                :id="`tag${element.fullPath.split('/').join('\/')}`"
                :class="{ 'active-item': activeKey === element.fullPath }"
                class="shadow-sm tabs-card-scroll-item"
                @contextmenu="handleContextMenu($event, element, index)"
                @click.stop="goPage(element)"
              >
                <Render :ref="`renderDom_${index}`" :value="getRender(element.meta.title)" />
                <el-badge
                  class="ml-1"
                  style="vertical-align: -webkit-baseline-middle"
                  v-if="element.meta.state === 'undone'"
                  type="warning"
                  is-dot
                />
                <el-icon
                  class="el-input__icon"
                  v-if="!element.meta.affix"
                  size="14"
                  @click.stop="closeTabItem(element)"
                >
                  <CloseOutlined />
                </el-icon>
              </div>
            </template>
          </Draggable>
        </div>
      </div>
      <div class="tabs-close">
        <el-dropdown trigger="hover" @command="closeHandleSelect">
          <div class="tabs-close-btn">
            <el-icon class="el-input__icon" size="16">
              <DownOutlined />
            </el-icon>
          </div>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item command="7">
                <el-icon class="el-input__icon" size="16" v-if="getPageFullScreen">
                  <CompressOutlined />
                </el-icon>
                <el-icon class="el-input__icon" size="16" v-else>
                  <ExpandOutlined />
                </el-icon>
                {{ getPageFullScreen ? '退出全屏' : '内容全屏' }}
              </el-dropdown-item>
              <el-dropdown-item :disabled="refreshCurrent" command="1">
                <el-icon class="el-input__icon" size="16">
                  <ReloadOutlined />
                </el-icon>
                刷新当前
              </el-dropdown-item>
              <el-dropdown-item :disabled="closeCurrent || isDisabled" command="2">
                <el-icon class="el-input__icon" size="16"> <MinusOutlined /> </el-icon>关闭当前
              </el-dropdown-item>
              <el-dropdown-item :disabled="isDisabled" command="3">
                <el-icon class="el-input__icon" size="16"> <SwapOutlined /> </el-icon
                >关闭其他</el-dropdown-item
              >
              <el-dropdown-item :disabled="closeLeftTab" command="5">
                <el-icon class="el-input__icon" size="16"> <DoubleLeftOutlined /> </el-icon
                >关闭左侧</el-dropdown-item
              >
              <el-dropdown-item :disabled="closeRightTab" command="6">
                <el-icon class="el-input__icon" size="16"> <DoubleRightOutlined /> </el-icon
                >关闭右侧</el-dropdown-item
              >
              <el-dropdown-item :disabled="isDisabled" command="4">
                <el-icon class="el-input__icon" size="16"> <CloseOutlined /> </el-icon
                >关闭全部</el-dropdown-item
              >
            </el-dropdown-menu>
          </template>
        </el-dropdown>
      </div>
      <!-- <el-dropdown
        :options="TabsMenuOptions"
        :show="showDropdown"
        :x="dropdownX"
        :y="dropdownY"
        placement="bottom-start"
        @clickoutside="onClickOutside"
        @select="closeHandleSelect"
      /> -->
    </div>
  </div>
</template>

<script lang="ts" setup>
  import { computed, ref, unref, provide, watch, onMounted, nextTick, toRaw, inject } from 'vue';
  import { useRoute, useRouter } from 'vue-router';
  import { storage } from '@/utils/Storage';
  import { TABS_ROUTES,FIRST_ROUTE } from '@/store/mutation-types';
  import { useTabsViewStore } from '@/store/modules/tabsView';
  import { useAsyncRouteStore } from '@/store/modules/asyncRoute';
  import { RouteItem } from '@/store/modules/tabsView';
  import { useProjectSetting } from '@/hooks/setting/useProjectSetting';
  import { ElMessage, ElMessageBox } from 'element-plus';
  import Draggable from 'vuedraggable';
  import { PageEnum } from '@/enums/pageEnum';
  import {
    DownOutlined,
    ReloadOutlined,
    CloseOutlined,
    SwapOutlined,
    LeftOutlined,
    RightOutlined,
    DoubleLeftOutlined,
    DoubleRightOutlined,
    MinusOutlined,
    CompressOutlined,
    ExpandOutlined,
  } from '@vicons/antd';
  // import { renderIcon } from '@/utils/index';
  import elementResizeDetectorMaker from 'element-resize-detector';
  import { useDesignSetting } from '@/hooks/setting/useDesignSetting';
  import { useProjectSettingStore } from '@/store/modules/projectSetting';
  import { useGo, useRedo } from '@/hooks/web/usePage';
  import { Render, getRender } from '@/components/Render';

  const props = defineProps({
    collapsed: {
      type: Boolean,
    },
  });

  const emit = defineEmits(['pageFullScreen']);

  const { getDarkTheme, getAppTheme } = useDesignSetting();
  const { getNavMode, getMenuSetting } = useProjectSetting();
  const settingStore = useProjectSettingStore();
  const go = useGo();
  const route = useRoute();
  const router = useRouter();
  const tabsViewStore = useTabsViewStore();
  const asyncRouteStore = useAsyncRouteStore();
  const navScroll: any = ref(null);
  const navWrap: any = ref(null);
  const activeKey = ref(route.fullPath);
  const scrollable = ref(false);
  const dropdownX = ref(0);
  const dropdownY = ref(0);
  const showDropdown = ref(false);
  const closeLeftTab = ref(false);
  const closeRightTab = ref(false);
  const closeCurrent = ref(false);
  const currentTabRoute = ref(null);
  const refreshCurrent = ref(true);

  // 获取简易的路由对象
  const getSimpleRoute = (route): RouteItem => {
    const { fullPath, hash, meta, name, params, path, query } = route;
    return { fullPath, hash, meta, name, params, path, query };
  };

  const isMixMenuNoneSub = computed(() => {
    const mixMenu = settingStore.menuSetting.mixMenu;
    const currentRoute = useRoute();
    const navMode = unref(getNavMode);
    if (unref(navMode) != 'horizontal-mix') return true;
    if (unref(navMode) === 'horizontal-mix' && mixMenu && currentRoute.meta.isRoot) {
      return false;
    }
    return true;
  });

  //动态组装样式 菜单缩进
  const getChangeStyle = computed(() => {
    const { collapsed } = props;
    const navMode = unref(getNavMode);
    const { minMenuWidth, menuWidth }: any = unref(getMenuSetting);
    let lenNum =
      navMode === 'horizontal' || !isMixMenuNoneSub.value
        ? '0px'
        : collapsed
        ? `${minMenuWidth}px`
        : `${menuWidth}px`;
    return {
      left: lenNum,
      width: `calc(100%)`,
    };
  });

  const getPageFullScreen = inject('isPageFullScreen');

  //tags 右键右侧下拉菜单
  // const TabsMenuOptions = computed(() => {
  //   const disabled = unref(tabsList).length === 1;
  //   return [
  //     {
  //       label: unref(getPageFullScreen) ? '退出全屏' : '内容全屏',
  //       key: '7',
  //       icon: getPageFullScreen ? renderIcon(CompressOutlined) : renderIcon(ExpandOutlined),
  //     },
  //     {
  //       label: '刷新当前',
  //       key: '1',
  //       icon: renderIcon(ReloadOutlined),
  //       disabled: refreshCurrent.value,
  //     },
  //     {
  //       label: `关闭当前`,
  //       key: '2',
  //       disabled: closeCurrent.value || disabled,
  //       icon: renderIcon(MinusOutlined),
  //     },
  //     {
  //       label: '关闭其他',
  //       key: '3',
  //       disabled: disabled,
  //       icon: renderIcon(SwapOutlined),
  //     },
  //     {
  //       label: '关闭左侧',
  //       key: '5',
  //       disabled: closeLeftTab.value,
  //       icon: renderIcon(DoubleLeftOutlined),
  //     },
  //     {
  //       label: '关闭右侧',
  //       key: '6',
  //       disabled: closeRightTab.value,
  //       icon: renderIcon(DoubleRightOutlined),
  //     },
  //     {
  //       label: '关闭全部',
  //       key: '4',
  //       disabled: disabled,
  //       icon: renderIcon(CloseOutlined),
  //     },
  //   ];
  // });

  let routes: RouteItem[] = [];
  try {
    const routesStr = storage.get(TABS_ROUTES) as string | null | undefined;
    routes = routesStr ? JSON.parse(routesStr) : [getSimpleRoute(route)];
  } catch (e) {
    routes = [getSimpleRoute(route)];
  }
  // 初始化标签页
  tabsViewStore.initTabs(routes);

  // 移除缓存组件名称
  const delKeepAliveCompName = () => {
    if (route.meta.keepAlive) {
      const name = router.currentRoute.value.matched.find((item) => item.name == route.name)
        ?.components?.default.name;
      if (name) {
        asyncRouteStore.keepAliveComponents = asyncRouteStore.keepAliveComponents.filter(
          (item) => item != name,
        );
      }
    }
  };

  // 标签页列表
  const tabsList: any = computed(() => tabsViewStore.tabsList);
  const whiteList: string[] = [
    PageEnum.BASE_LOGIN_NAME,
    PageEnum.REDIRECT_NAME,
    PageEnum.ERROR_PAGE_NAME,
  ];

  const isDisabled = computed(() => unref(tabsList).length === 1);

  watch(
    () => route.fullPath,
    (to) => {
      // 如果您用的路由模式是 hash 请去掉，|| route.hash 判断条件
      if (whiteList.includes(route.name as string) || route.hash || route.meta.tagView === false)
        return;
      activeKey.value = to;
      currentTabRoute.value = null;
      refreshCurrent.value = false;
      tabsViewStore.addTabs(getSimpleRoute(route));
      nextTick().then(() => {
        updateNavScroll(true);
        refreshTabDisabled(getTabIndex());
      });
    },
    { immediate: true },
  );
  // 在页面关闭或刷新之前，保存数据
  window.addEventListener('beforeunload', () => {
    storage.set(TABS_ROUTES, JSON.stringify(tabsList.value));
  });
  // 关闭当前页面
  const removeTab = (route) => {
    if (tabsList.value.length === 1) {
      return ElMessage({
        message: '这已经是最后一页，不能再关闭了！',
        type: 'warning',
      });
    }
    const routeInfo = unref(route);
    //判断当前页标签状态 阻止关闭 只是提供思路，更多个性化功能，自行调整
    if (routeInfo.meta.state && routeInfo.meta.state === 'undone') {
      const { content } = routeInfo.meta.dialogOptions;
      ElMessageBox.confirm(content, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
        center: true,
      }).then(() => {
        directRemoveTab(route);
      });
    } else directRemoveTab(route);
  };

  function directRemoveTab(route) {
    delKeepAliveCompName();
    tabsViewStore.closeCurrentTab(route);
    asyncRouteStore.removeKeepAliveComponents([route.value.name]);
    // 如果关闭的是当前页
    if (activeKey.value === route.value.fullPath) {
      const currentRoute = tabsList.value[Math.max(0, tabsList.value.length - 1)];
      activeKey.value = currentRoute.fullPath;
      router.push(currentRoute);
    }
    updateNavScroll();
  }

  // 刷新页面
  async function reloadPage() {
    delKeepAliveCompName();
    const redo = useRedo(router);
    await redo();
  }

  // 注入刷新页面方法
  provide('reloadPage', reloadPage);

  // 关闭左侧
  const closeLeft = (route) => {
    tabsViewStore.closeLeftTabs(route, activeKey.value);
    router.replace(route.fullPath);
    updateNavScroll();
  };

  // 关闭右侧
  const closeRight = (route) => {
    tabsViewStore.closeRightTabs(route, activeKey.value);
    router.replace(route.fullPath);
    updateNavScroll();
  };
  // 关闭其他
  const closeOther = (route) => {
    tabsViewStore.closeOtherTabs(route, activeKey.value);
    router.replace(route.fullPath);
    updateNavScroll();
  };
  // 关闭全部
  const closeAll = () => {
    tabsViewStore.closeAllTabs();
    router.replace(storage.get(FIRST_ROUTE));
    // router.replace(PageEnum.BASE_HOME_REDIRECT);
    updateNavScroll();
  };

  //当前路由对象 或者 右键选择tab路由对象
  const getCurrentTabRoute = computed(() =>
    currentTabRoute.value ? currentTabRoute.value : route,
  );

  //tab 操作
  const closeHandleSelect = (key) => {
    switch (key) {
      //刷新
      case '1':
        reloadPage();
        break;
      //关闭
      case '2':
        removeTab(getCurrentTabRoute);
        break;
      //关闭其他
      case '3':
        closeOther(getCurrentTabRoute);
        break;
      //关闭所有
      case '4':
        closeAll();
        break;
      //关闭左侧
      case '5':
        closeLeft(getCurrentTabRoute);
        break;
      //关闭右侧
      case '6':
        closeRight(getCurrentTabRoute);
        break;
      //内容页全屏
      case '7':
        emit('pageFullScreen');
        break;
    }
    updateNavScroll();
    showDropdown.value = false;
  };

  /**
   * @param value 要滚动到的位置
   * @param amplitude 每次滚动的长度
   */
  function scrollTo(value: number, amplitude: number) {
    const currentScroll = navScroll.value.scrollLeft;
    const scrollWidth =
      (amplitude > 0 && currentScroll + amplitude >= value) ||
      (amplitude < 0 && currentScroll + amplitude <= value)
        ? value
        : currentScroll + amplitude;
    navScroll.value && navScroll.value.scrollTo(scrollWidth, 0);
    if (scrollWidth === value) return;
    return window.requestAnimationFrame(() => scrollTo(value, amplitude));
  }

  function scrollPrev() {
    const containerWidth = navScroll.value.offsetWidth;
    const currentScroll = navScroll.value.scrollLeft;
    if (!currentScroll) return;
    const scrollLeft = currentScroll > containerWidth ? currentScroll - containerWidth : 0;
    scrollTo(scrollLeft, (scrollLeft - currentScroll) / 20);
  }

  function scrollNext() {
    const containerWidth = navScroll.value.offsetWidth;
    const navWidth = navScroll.value.scrollWidth;
    const currentScroll = navScroll.value.scrollLeft;
    if (navWidth - currentScroll / 2 <= containerWidth) return;
    const scrollLeft =
      navWidth - currentScroll > containerWidth * 2
        ? currentScroll + containerWidth
        : navWidth - containerWidth;
    scrollTo(scrollLeft, (scrollLeft - currentScroll) / 20);
  }

  /**
   * @param autoScroll 是否开启自动滚动功能
   */
  function updateNavScroll(autoScroll?: boolean) {
    if (!navScroll.value) return;
    const containerWidth = navScroll.value.offsetWidth;
    const navWidth = navScroll.value.scrollWidth;
    if (containerWidth < navWidth) {
      scrollable.value = true;
      if (autoScroll) {
        let tagList = navScroll.value.querySelectorAll('.tabs-card-scroll-item') || [];
        [...tagList].forEach((tag: HTMLElement) => {
          // fix SyntaxError
          if (tag.id === `tag${activeKey.value.split('/').join('\/')}`) {
            tag.scrollIntoView && tag.scrollIntoView();
          }
        });
      }
    } else {
      scrollable.value = false;
    }
  }

  function handleResize() {
    updateNavScroll(true);
  }

  function handleContextMenu(e, item, index) {
    e.preventDefault();
    showDropdown.value = false;
    currentTabRoute.value = toRaw(item);
    refreshCurrent.value = !(activeKey.value === item.fullPath);
    refreshTabDisabled(index);

    nextTick().then(() => {
      showDropdown.value = true;
      dropdownX.value = e.clientX;
      dropdownY.value = e.clientY;
    });
  }

  function getTabIndex() {
    return unref(tabsList).findIndex((item) => item.fullPath === activeKey.value);
  }

  // function onClickOutside() {
  //   showDropdown.value = false;
  //   currentTabRoute.value = null;
  //   refreshCurrent.value = false;
  //   const index = getTabIndex();
  //   refreshTabDisabled(index);
  // }

  function refreshTabDisabled(index) {
    closeCurrent.value = unref(tabsList)[index].meta?.affix ?? false;
    closeLeftTab.value = !(unref(tabsList).length > 0 && index > 0);
    closeRightTab.value = !(index < unref(tabsList).length && index != unref(tabsList).length - 1);
  }

  //tags 跳转页面
  function goPage(e) {
    const { fullPath } = e;
    closeCurrent.value = e.meta?.affix ?? false;
    if (fullPath === route.fullPath) return;
    activeKey.value = fullPath;
    go(e, true);
  }

  //删除tab
  function closeTabItem(e) {
    const { fullPath } = e;
    const routeInfo = ref(tabsList.value.find((item) => item.fullPath == fullPath));
    removeTab(routeInfo);
  }

  onMounted(() => {
    onElementResize();
  });

  function onElementResize() {
    let observer;
    observer = elementResizeDetectorMaker();
    observer.listenTo(navWrap.value, handleResize);
  }
</script>

<style lang="scss" scoped>
  .tabs-view {
    width: 100%;
    padding: 6px 0;
    display: flex;
    transition: all 0.2s ease-in-out;

    &-main {
      height: 32px;
      display: flex;
      max-width: 100%;
      min-width: 100%;
      padding: 0 10px;
      box-sizing: border-box;

      .tabs-card {
        -webkit-box-flex: 1;
        flex-grow: 1;
        flex-shrink: 1;
        overflow: hidden;
        position: relative;

        .tabs-card-prev,
        .tabs-card-next {
          width: 32px;
          text-align: center;
          position: absolute;
          line-height: 32px;
          cursor: pointer;

          .n-icon {
            display: flex;
            align-items: center;
            justify-content: center;
            height: 32px;
            width: 32px;
          }
        }

        .tabs-card-prev {
          left: 0;
        }

        .tabs-card-next {
          right: 0;
        }

        .tabs-card-next-hide,
        .tabs-card-prev-hide {
          display: none;
        }

        &-scroll {
          white-space: nowrap;
          overflow: hidden;

          &-item {
            // background: v-bind(getCardColor);
            // color: v-bind(getBaseColor);
            background: #fff;
            color: #333;
            height: 32px;
            padding: 6px 16px 4px;
            border-radius: 3px;
            margin-right: 6px;
            cursor: pointer;
            display: inline-block;
            position: relative;
            flex: 0 0 auto;

            span {
              float: left;
              vertical-align: middle;
            }

            &:hover {
              color: #515a6e;
            }

            .el-icon {
              height: 22px;
              width: 21px;
              margin-right: -6px;
              position: relative;
              vertical-align: middle;
              text-align: center;
              color: #808695;

              &:hover {
                color: #515a6e !important;
              }

              svg {
                height: 21px;
                display: inline-block;
              }
            }
          }

          .active-item {
            color: v-bind(getAppTheme);
          }
        }
      }

      .tabs-card-scrollable {
        padding: 0 32px;
        overflow: hidden;
      }
    }

    .tabs-close {
      min-width: 32px;
      width: 32px;
      height: 32px;
      line-height: 32px;
      text-align: center;
      display: flex;
      justify-content: center;
      background: #fff;
      border-radius: 2px;
      cursor: pointer;
      //margin-right: 10px;
      &-btn {
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
      }
    }
  }

  .tabs-view-default-background {
    background: #f5f7f9;
  }

  .tabs-view-dark-background {
    background: #101014;
  }

  .tabs-view-fix {
    position: fixed;
    z-index: 5;
    padding: 6px 19px 6px 10px;
    left: 200px;
  }

  .tabs-view-fixed-header {
    top: 0;
  }
</style>
