<template>
  <div class="tabs-box">
    <div class="tabs-menu">
      <div class="scroll-container" ref="scrollContainer" @wheel.prevent="onScroll">
        <t-tag
          v-for="item in tabsMenuList"
          :key="item.title"
          :class="[isActive(item) ? 'active' : '']"
          :closable="item.close"
          @click="tabClick(item)"
          @close="tabRemove(item)"
          @contextmenu.prevent="openMenu(item, $event)"
        >
          {{ item.title }}
        </t-tag>
      </div>
    </div>
    <ul v-show="contextmenuVisible" :style="{ left: left + 'px', top: top + 10 + 'px' }" class="contextmenu">
      <li @click="refresh">刷新</li>
      <li v-if="currentActionRoute.close" @click="closeCurrentTab">关闭当前</li>
      <li @click="closeOtherTab">关闭其他</li>
      <li @click="closeSomeTags('left')">关闭左侧</li>
      <li @click="closeSomeTags('right')">关闭右侧</li>
      <li @click="closeAllTab">关闭全部</li>
    </ul>
  </div>
</template>

<script setup lang="ts">
import { computed, inject, nextTick, reactive, ref, watch } from 'vue'
import { RouteRecordRaw, useRoute, useRouter } from 'vue-router'
import { HOME_URL } from '@/config'
import { useTabsStore } from '@/stores/modules/tabs'
import { useAuthStore } from '@/stores/modules/auth'
import { useKeepAliveStore } from '@/stores/modules/keepAlive'
import { routes } from '@/routers'
import { TabsMenuProps } from '@/stores/interface'

// const $emit = defineEmits(['scroll'])
const route = useRoute()
const router = useRouter()
const tabStore = useTabsStore()
const authStore = useAuthStore()
const keepAliveStore = useKeepAliveStore()

const tabsMenuValue = ref(route.fullPath)
const tabsMenuList = computed(() => tabStore.tabsMenuList)
const contextmenuVisible = ref(false)
const left = ref(0)
const top = ref(0)
// 当前右键选中的tab标签
let currentActionRoute = reactive<Partial<TabsMenuProps>>({})

const scrollContainer = ref()

onMounted(() => {
  initTabs()
})

// 监听路由的变化（防止浏览器后退/前进不变化 tabsMenuValue）
watch(
  () => route.fullPath,
  () => {
    if (route.meta.noTopTag) return
    tabsMenuValue.value = route.fullPath
    const tabsParams = {
      icon: route.meta.icon as string,
      title: route.meta.title as string,
      path: route.fullPath,
      name: route.name as string,
      close: !route.meta.affix
    }
    tabStore.addTabs(tabsParams)
    route.meta.keepAlive && keepAliveStore.addKeepAliveName(route.name as string)
  },
  { immediate: true }
)
// 监听右键操作弹窗，控制显示隐藏
watch(contextmenuVisible, val => {
  if (val) {
    document.body.addEventListener('click', closeRightMenu)
  } else {
    document.body.removeEventListener('click', closeRightMenu)
  }
})

// 滚动标签栏
const onScroll = (e: any) => {
  const eventDelta = e.wheelDelta || -e.deltaY * 40
  const $scrollWrapper = scrollContainer
  $scrollWrapper.value.scrollLeft = $scrollWrapper.value.scrollLeft - eventDelta / 4
}
const openMenu = (item: TabsMenuProps, e: MouseEvent) => {
  contextmenuVisible.value = true
  left.value = e.clientX
  top.value = e.clientY
  currentActionRoute = item
}

const closeRightMenu = () => {
  contextmenuVisible.value = false
}

// 当前标签是否为激活项
const isActive = (item: TabsMenuProps) => {
  // 如果当前路由不需要顶部tab，则激活当前路由父级为菜单路由项
  if (route.meta?.noTopTag) {
    return item.name === authStore.menuSign
  } else {
    return item.name === route.name
  }
}

// 筛选路由表中的固定展示标签的路由
const filterAffixTags = (routes: RouteRecordRaw[]) => {
  routes.forEach(item => {
    if (item.meta && item.meta?.affix && !item.meta?.noTopTag) {
      const tabsParams = {
        title: item.meta?.title as string,
        path: item.path,
        name: item.name as string,
        close: !item.meta?.affix
      }
      tabStore.addTabs(tabsParams)
    }
    if (item.children) {
      filterAffixTags(item.children)
    }
  })
}

// 初始化需要固定的 tabs
const initTabs = () => {
  filterAffixTags(routes)
}

// 切换标签
const tabClick = (tabItem: TabsMenuProps) => {
  // const fullPath = tabItem.path
  // router.push(fullPath)
  router.push({
    name: tabItem.name
  })
}

// 删除标签
const tabRemove = (tabItem: TabsMenuProps) => {
  const name = tabStore.tabsMenuList.filter(item => item.path == tabItem.path)[0].name || ''
  keepAliveStore.removeKeepAliveName(name)
  tabStore.removeTabs(tabItem.path as string, tabItem.path == route.fullPath)
}

// 刷新
const refreshCurrentPage: Function = inject('refresh') as Function
const refresh = () => {
  setTimeout(() => {
    keepAliveStore.removeKeepAliveName(route.name as string)
    refreshCurrentPage(false)
    nextTick(() => {
      keepAliveStore.addKeepAliveName(route.name as string)
      refreshCurrentPage(true)
    })
  }, 0)
}

// 关闭当前
const closeCurrentTab = () => {
  const isCurrent = currentActionRoute.path === route.path
  if (route.meta.affix) return
  tabStore.removeTabs(currentActionRoute.path!, isCurrent)
  keepAliveStore.removeKeepAliveName(route.name as string)
}

// 关闭其他
const closeOtherTab = () => {
  tabStore.closeMultipleTab(currentActionRoute.path)
  keepAliveStore.setKeepAliveName([route.name] as string[])
  router.push(currentActionRoute)
}

// 关闭全部
const closeAllTab = () => {
  tabStore.closeMultipleTab()
  keepAliveStore.setKeepAliveName()
  router.push(HOME_URL)
}

// 关闭左侧/右侧
const closeSomeTags = (direction: string) => {
  const index = tabStore.tabsMenuList.findIndex(item => item.path === currentActionRoute.path)
  if ((direction === 'left' && index <= 0) || (direction === 'right' && index >= tabStore.tabsMenuList.length - 1)) {
    return
  }
  // 需要关闭的标签列表
  const needToClose =
    direction === 'left'
      ? tabStore.tabsMenuList.slice(0, index).filter(v => v.close)
      : tabStore.tabsMenuList.slice(index + 1).filter(v => v.close)
  tabStore.closeSomeTabs(needToClose)
  router.push(currentActionRoute)
}
</script>

<style scoped lang="less">
@import 'index.less';

.contextmenu {
  position: fixed;
  z-index: 3000;
  padding: 5px 0;
  margin: 0;
  font-size: 12px;
  font-weight: 400;
  // color: var(--td-white);
  white-space: nowrap;
  list-style-type: none;
  background: var(--td-white);
  border-radius: 4px;
  box-shadow: 2px 2px 3px 0 rgb(0 0 0 / 30%);

  li {
    padding: 8px 16px;
    margin: 0;
    cursor: pointer;
    background: var(--td-white);

    &:hover {
      color: var(--td-brand-color);
    }
  }
}
</style>
