<template>
	<div class="pi-tags">
		<ul ref="tags">
			<li v-for="tag in tagList" v-bind:key="tag" :class="[isActive(tag)?'active':'',tag.meta.affix?'affix':'' ]"
				@contextmenu.prevent="openContextMenu($event, tag)">
				<router-link :to="tag">
					<el-icon v-if="tag.meta&&tag.meta.icon">
						<component :is="tag.meta.icon || 'el-icon-menu'"/>
					</el-icon>
					<span>{{ tag.meta.title }}</span>
					<el-icon v-if="!tag.meta.affix" @click.prevent.stop='closeSelectedTag(tag)'>
						<el-icon-close/>
					</el-icon>
				</router-link>
			</li>
		</ul>
	</div>

	<transition name="el-zoom-in-top">
		<ul v-if="contextMenuVisible" :style="{left:left+'px',top:top+'px'}" class="contextmenu" id="contextmenu">
			<li @click="refreshTab()">
				<el-icon>
					<el-icon-refresh/>
				</el-icon>
				{{ t('menu.refresh') }}
			</li>
			<hr>
			<li @click="closeTabs()" :class="contextMenuItem.meta.affix?'disabled':''">
				<el-icon>
					<el-icon-close/>
				</el-icon>
				{{ t('menu.closeTab') }}
			</li>
			<li @click="closeOtherTabs()">
				<el-icon>
					<el-icon-folder-delete/>
				</el-icon>
				{{ t('menu.closeOtherTabs') }}
			</li>

			<li v-if="showLeft" @click="closeLeft()">
				<el-icon>
					<el-icon-back/>
				</el-icon>
				{{ t('menu.closeLeft') }}
			</li>

			<li v-if="showRight" @click="closeRight()">
				<el-icon>
					<el-icon-right/>
				</el-icon>
				{{ t('menu.closeRight') }}
			</li>

			<li @click="closeAll()">
				<el-icon>
					<el-icon-circle-close/>
				</el-icon>
				{{ t('menu.closeAll') }}
			</li>
			<hr>
			<li @click="maximize()">
				<el-icon>
					<el-icon-full-screen/>
				</el-icon>
				{{ t('menu.maximize') }}
			</li>
			<li @click="openWindow()">
				<el-icon>
					<el-icon-copy-document/>
				</el-icon>
				{{ t('menu.openInNewWindow') }}
			</li>
		</ul>
	</transition>
</template>

<script setup>
defineOptions({
	name: 'tags'
})
import Sortable from 'sortablejs'
import {getCurrentInstance, nextTick, ref, watch, onMounted} from "vue";
import viewTagsStore from "@/store/viewTags";
import keepAliveStore from "@/store/keepAlive";
import iframeStore from "@/store/iframe";
import {useRouter, useRoute} from "vue-router";
import {getMenu} from "@/utils/route"
import {useI18n} from "vue-i18n"

const {t} = useI18n()
const viewTags = viewTagsStore()
const keepAlive = keepAliveStore()
const iframe = iframeStore()
const route = useRoute()
const router = useRouter()
const {proxy} = getCurrentInstance();
const menu = getMenu();
const dashboardRoute = treeFind(menu, node => node.path === "/dashboard");

let contextMenuVisible = ref(false)
let contextMenuItem = ref(null)
let left = ref(0)
let top = ref(0)
let tagList = viewTags.viewTags
let tipDisplayed = ref(false)
let showLeft = ref(true)
let showRight = ref(true)

if (dashboardRoute) {
	dashboardRoute.fullPath = dashboardRoute.path
	addViewTags(dashboardRoute)
	addViewTags(route)
}

onMounted(() => {
	tagDrop();
	scrollInit()
})

watch(() => route.path, (e) => {
	addViewTags(route);
	//判断标签容器是否出现滚动条
	nextTick(() => {
		const tags = proxy.$refs.tags
		if (tags && tags.scrollWidth > tags.clientWidth) {
			//确保当前标签在可视范围内
			let targetTag = tags.querySelector(".active")
			targetTag.scrollIntoView()
			//显示提示
			if (!tipDisplayed.value) {
				proxy.$msgbox({
					type: 'warning',
					center: true,
					title: '提示',
					message: '当前标签数量过多，可通过鼠标滚轴滚动标签栏。关闭标签数量可减少系统性能消耗。',
					confirmButtonText: '知道了'
				})
				tipDisplayed.value = true
			}
		}
	})
}, {deep: false})

watch(contextMenuVisible, (value) => {
	var cm = function (e) {
		let sp = document.getElementById("contextmenu");
		if (sp && !sp.contains(e.target)) {
			closeMenu()
		}
	}
	if (value) {
		document.body.addEventListener('click', e => cm(e))
	} else {
		document.body.removeEventListener('click', e => cm(e))
	}
})

//查找树
function treeFind(tree, func) {
	for (const data of tree) {
		if (func(data)) return data
		if (data.children) {
			const res = treeFind(data.children, func)
			if (res) return res
		}
	}
	return null
}

//标签拖拽排序
function tagDrop() {
	Sortable.create(proxy.$refs.tags, {
		draggable: 'li',
		animation: 300,
		onEnd(e) {
			viewTags.moveViewTags(e.oldIndex, e.newIndex)
		}
	})
}

//增加tag
function addViewTags(_route) {
	if (_route.name && !_route.meta.fullpage) {
		viewTags.pushViewTags(_route)
		keepAlive.pushKeepLive(_route.name)
	}
}

//高亮tag
function isActive(r) {
	return r.fullPath === route.fullPath
}

//关闭tag
function closeSelectedTag(tag, autoPushLatestView = true) {
	const nowTagIndex = tagList.findIndex(item => item.fullPath === tag.fullPath)
	viewTags.removeViewTags(tag)
	iframe.removeIframeList(tag)
	keepAlive.removeKeepLive(tag.name)
	if (autoPushLatestView && isActive(tag)) {
		const leftView = tagList[nowTagIndex - 1]
		if (leftView) {
			router.push(leftView)
		} else {
			router.push('/')
		}
	}
}

//tag右键
function openContextMenu(e, tag) {
	// 关闭左侧，关闭右侧处理
	showLeft.value = true
	showRight.value = true
	const index = tagList.findIndex(i => i.fullPath === tag.fullPath);
	if (index === 0) {
		showLeft.value = false
	}
	if (index + 1 === tagList.length) {
		showRight.value = false
	}
	// 后续处理
	contextMenuItem = tag;
	contextMenuVisible.value = true;
	left.value = e.clientX + 1;
	top.value = e.clientY + 1;

	//FIX 右键菜单边缘化位置处理
	nextTick(() => {
		let sp = document.getElementById("contextmenu");
		if (document.body.offsetWidth - e.clientX < sp.offsetWidth) {
			left.value = document.body.offsetWidth - sp.offsetWidth + 1;
			top.value = e.clientY + 1;
		}
	})
}

//关闭右键菜单
function closeMenu() {
	contextMenuItem = null;
	contextMenuVisible.value = false
}

//TAB 刷新
function refreshTab() {
	const nowTag = contextMenuItem;
	contextMenuVisible.value = false
	//判断是否当前路由，否的话跳转
	if (route.fullPath !== nowTag.fullPath) {
		router.push({
			path: nowTag.fullPath,
			query: nowTag.query
		})
	}
	iframe.refreshIframe(nowTag)
	setTimeout(function () {
		keepAlive.removeKeepLive(nowTag.name)
		keepAlive.setRouteShow(false)
		nextTick(() => {
			keepAlive.pushKeepLive(nowTag.name)
			keepAlive.setRouteShow(true)
		})
	}, 0);
}

//TAB 关闭
function closeTabs() {
	var nowTag = contextMenuItem;
	if (!nowTag.meta.affix) {
		closeSelectedTag(nowTag)
		contextMenuVisible.value = false
	}
}

//TAB 关闭其他
function closeOtherTabs() {
	var nowTag = contextMenuItem;
	//判断是否当前路由，否的话跳转
	if (route.fullPath !== nowTag.fullPath) {
		router.push({
			path: nowTag.fullPath,
			query: nowTag.query
		})
	}
	var tags = [...tagList];
	tags.forEach(tag => {
		if (tag.meta && tag.meta.affix || nowTag.fullPath === tag.fullPath) {
			return true
		} else {
			closeSelectedTag(tag, false)
		}
	})
	contextMenuVisible.value = false
}

// 关闭左侧
function closeLeft() {
	const nowTag = contextMenuItem;
	//判断是否当前路由，否的话跳转
	if (route.fullPath !== nowTag.fullPath) {
		router.push({
			path: nowTag.fullPath,
			query: nowTag.query
		})
	}
	const tags = [...tagList];
	let flag = true;
	tags.forEach(tag => {
		if (nowTag.fullPath === tag.fullPath) {
			flag = false
		}
		if ((tag.meta && tag.meta.affix) || !flag) {
			return true
		} else {
			closeSelectedTag(tag, false)
		}
	})
	contextMenuVisible.value = false
}

// 关闭右侧
function closeRight() {
	const nowTag = contextMenuItem;
	//判断是否当前路由，否的话跳转
	if (route.fullPath !== nowTag.fullPath) {
		router.push({
			path: nowTag.fullPath,
			query: nowTag.query
		})
	}
	const tags = [...tagList];
	let flag = false;
	tags.forEach(tag => {
		if (nowTag.fullPath === tag.fullPath) {
			flag = true
		}
		if ((tag.meta && tag.meta.affix) || !flag || nowTag.fullPath === tag.fullPath) {
			return true
		} else {
			closeSelectedTag(tag, false)
		}
	})
	contextMenuVisible.value = false
}

// 关闭所有
function closeAll() {
	const tags = [...tagList];
	tags.forEach(tag => {
		if (tag.meta && tag.meta.affix) {
			return true
		} else {
			closeSelectedTag(tag, false)
		}
	})
	// 跳转到后台首页
	router.push({
		path: dashboardRoute.fullPath,
		query: dashboardRoute.query
	})
	contextMenuVisible.value = false
}

//TAB 最大化
function maximize() {
	var nowTag = contextMenuItem;
	contextMenuVisible.value = false
	//判断是否当前路由，否的话跳转
	if (route.fullPath != nowTag.fullPath) {
		router.push({
			path: nowTag.fullPath,
			query: nowTag.query
		})
	}
	document.getElementById('app').classList.add('main-maximize')
}

//新窗口打开
function openWindow() {
	var nowTag = contextMenuItem
	var url = nowTag.fullPath ? '#' + nowTag.fullPath : '/'
	if (!nowTag.meta.affix) {
		closeSelectedTag(nowTag)
	}
	window.open(url);
	contextMenuVisible.value = false
}

//横向滚动
function scrollInit() {
	const scrollDiv = proxy.$refs.tags;
	scrollDiv.addEventListener('mousewheel', handler, false) || scrollDiv.addEventListener("DOMMouseScroll", handler, false)

	function handler(event) {
		const detail = event.wheelDelta || event.detail;
		//火狐上滚键值-3 下滚键值3，其他内核上滚键值120 下滚键值-120
		const moveForwardStep = 1;
		const moveBackStep = -1;
		let step = 0;
		if (detail == 3 || detail < 0 && detail != -3) {
			step = moveForwardStep * 50;
		} else {
			step = moveBackStep * 50;
		}
		scrollDiv.scrollLeft += step;
	}
}

</script>

<style>
.contextmenu {
	position: fixed;
	width: 200px;
	margin: 0;
	border-radius: 0px;
	background: var(--el-bg-color-overlay);
	border: 1px solid var(--el-border-color-light);
	box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);
	z-index: 3000;
	list-style-type: none;
	padding: 10px 0;
}

.contextmenu hr {
	margin: 5px 0;
	border: none;
	height: 1px;
	font-size: 0px;
	background-color: var(--el-border-color-light);
}

.contextmenu li {
	display: flex;
	align-items: center;
	margin: 0;
	cursor: pointer;
	line-height: 30px;
	padding: 0 17px;
	color: #606266;
}

.contextmenu li i {
	font-size: 14px;
	margin-right: 10px;
}

.contextmenu li:hover {
	background-color: #ecf5ff;
	color: #66b1ff;
}

.contextmenu li.disabled {
	cursor: not-allowed;
	color: #bbb;
	background: transparent;
}

.tags-tip {
	padding: 5px;
}

.tags-tip p {
	margin-bottom: 10px;
}

.dark .contextmenu li {
	color: var(--el-text-color-primary);
}

</style>
