<script lang="ts" setup>
import type { TabPaneName } from 'element-plus'
import config from '@/config/defaultSetting'
import { useMenuStore } from '@/stores/menu'

interface Tab {
  name: string
  fullPath: string
  params: object
  query: object
  title: string
}

const router = useRouter()
const route = useRoute()

const routeToTab = (route: any) => {
  return (
    route && {
      name: route.name,
      fullPath: route.fullPath || route.path,
      params: route.params,
      query: route.query,
      title: route.meta?.title
    }
  )
}

const defaultTabs = [routeToTab(router.getRoutes().find(item => item.name === config.homeRouteName))]
route.name !== config.homeRouteName && defaultTabs.push(routeToTab(route))

const tabs = useStorage<any[]>('globalTabs', defaultTabs, sessionStorage)
const activeValue = ref(route.fullPath)
const activeIndex = ref(0)

const findActiveIndex = (fullPath: string | number) => {
  return tabs.value.findIndex(item => item.fullPath === fullPath)
}

const setTab = (tab: Tab) => {
  if (tab.name === 'login' || tabs.value.find(item => item.name === tab.name)) {
    return
  }
  tabs.value.push(tab)
}
const menuStore = useMenuStore()
const activeMenu = ref({})
const findActiveMenu = (path: any) => {
  const findDeep = (list: any): boolean => {
    let flag = false
    for (let index = 0; index < list.length; index++) {
      const element = list[index]
      if (element.path === path) {
        flag = true
        break
      }
      if (element.children?.length) {
        flag = findDeep(element.children)
      }
    }
    return flag
  }
  for (let index = 0; index < menuStore.allMenuList.length; index++) {
    const element = menuStore.allMenuList[index]
    if (element.path === path) {
      activeMenu.value = element
      break
    }
    if (element.children?.length && findDeep(element.children)) {
      activeMenu.value = element
      break
    }
  }
}
const changeTab = (name: TabPaneName) => {
  activeIndex.value = findActiveIndex(name)
  const menu = tabs.value.find(item => item.fullPath === name)
  router.push(menu)

  menuStore.activeRoutePath = name
  findActiveMenu(name)
  menuStore.setActiveTopMenu(activeMenu.value)
}
const removeTab = (name: TabPaneName) => {
  const index = findActiveIndex(name)
  activeIndex.value = index < tabs.value.length - 1 ? index + 1 : index - 1
  router.push(tabs.value[activeIndex.value])
  tabs.value.splice(index, 1)
}

watch(
  () => route,
  to => {
    setTab(routeToTab(to))
    activeValue.value = to.fullPath
    activeIndex.value = findActiveIndex(to.fullPath)
  },
  {
    deep: true
  }
)

// 右键菜单相关
const contextMenuVisible = ref(false)
const left = ref(0)
const top = ref(0)
const contextMenuIndex = ref(0)
const contextMenuItem = computed(() => tabs.value[contextMenuIndex.value]) as any

const findContextMenuItemIndex = (fullPath: string) => tabs.value.findIndex(item => item.fullPath === fullPath)

const openContextMenu = (e: any) => {
  const id = e.target?.offsetParent?.id || e.target?.id
  if (id) {
    const fullPath = id.split('tab-')[1]
    contextMenuIndex.value = findContextMenuItemIndex(fullPath)
    left.value = e.clientX + 1
    top.value = e.clientY + 1
    contextMenuVisible.value = true
  }
}
const closeContextMenu = () => {
  contextMenuVisible.value = false
}

const closeAll = () => {
  router.push(tabs.value[0])
  tabs.value.splice(1)
  closeContextMenu()
}
const closeLeft = () => {
  if (activeIndex.value < contextMenuIndex.value) {
    router.push(contextMenuItem.value)
  }
  tabs.value.splice(1, contextMenuIndex.value - 1)
  closeContextMenu()
}
const closeRight = () => {
  if (activeIndex.value > contextMenuIndex.value) {
    router.push(contextMenuItem.value)
  }
  tabs.value.splice(contextMenuIndex.value + 1)
  closeContextMenu()
}

const closeOther = () => {
  router.push(contextMenuItem.value)
  if (contextMenuIndex.value) {
    tabs.value = [tabs.value[0], contextMenuItem.value]
  } else {
    tabs.value = [tabs.value[0]]
  }
  contextMenuVisible.value = false
}

watch(contextMenuVisible, val => {
  if (val) {
    document.body.addEventListener('click', closeContextMenu)
  } else {
    document.body.removeEventListener('click', closeContextMenu)
  }
})

// 刷新页面
const refresh = () => {
  router.go(0)
}
</script>

<template>
  <div class="bg-white" style="border-top: 1px solid var(--el-border-color-light)">
    <el-tabs
      v-model="activeValue"
      type="card"
      @tab-change="changeTab"
      @tab-remove="removeTab"
      @contextmenu.prevent="openContextMenu($event)"
      @dblclick="refresh"
    >
      <el-tab-pane
        v-for="item in tabs"
        :key="item.name"
        :label="item.title"
        :name="item.fullPath"
        :tab="item"
        :closable="item.name !== config.homeRouteName"
      >
      </el-tab-pane>
    </el-tabs>

    <!--自定义右键菜单html代码-->
    <ul v-show="contextMenuVisible" :style="{ left: left + 'px', top: top + 'px' }" class="context-menu">
      <li @click="closeAll">关闭所有</li>
      <li @click="closeLeft">关闭左侧</li>
      <li @click="closeRight">关闭右侧</li>
      <li @click="closeOther">关闭其他</li>
    </ul>
  </div>
</template>

<style lang="scss" scoped>
:deep(.el-tabs__header) {
  margin: 0;
  // border-top: 1px solid var(--el-border-color-light);
}
:deep(.el-tabs__nav) {
  border-top: none !important;
  border-radius: 0 !important;
}
:deep(.el-tabs__item.is-active) {
  background-color: var(--el-color-primary-light-9);
  border-bottom-color: var(--el-border-color) !important;
}
.context-menu {
  position: fixed;
  width: 100px;
  margin: 0;
  border-radius: 4px;
  background: var(--el-bg-color-overlay);
  border: 1px solid var(--el-border-color-light);
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  z-index: 3000;
  list-style-type: none;
  padding: 0;

  li {
    margin: 0;
    padding: 7px 16px;
    cursor: pointer;

    &:hover {
      background: #f2f2f2;
    }
  }
}
</style>
