Tea.context(function () {
	this.moreOptionsVisible = false
	this.globalMessageBadge = 0
	this.isDarkMode = false

	if (typeof this.leftMenuItemIsDisabled == "undefined") {
		this.leftMenuItemIsDisabled = false
	}

	this.$delay(function () {
		if (this.$refs.focus != null) {
			this.$refs.focus.focus()
		}

		// 检查消息
		this.checkMessages()
	})

	/**
	 * 左侧子菜单
	 */
	this.showSubMenu = function (menu) {
		if (menu.alwaysActive) {
			return
		}
		if (this.teaSubMenus.menus != null && this.teaSubMenus.menus.length > 0) {
			this.teaSubMenus.menus.$each(function (k, v) {
				if (menu.id == v.id) {
					return
				}
				v.isActive = false
			})
		}
		menu.isActive = !menu.isActive
	};

	/**
	 * 检查消息
	 */
	this.checkMessages = function () {
		this.$post("/messages/badge")
			.params({})
			.success(function (resp) {
				this.globalMessageBadge = resp.data.count

				// add dot to title
				let dots = "••• "
				if (typeof document.title == "string") {
					if (resp.data.count > 0) {
						if (!document.title.startsWith(dots)) {
							document.title = dots + document.title
						}
					} else if (document.title.startsWith(dots)) {
						document.title = document.title.substring(dots.length)
					}
				}
			})
			.done(function () {
				let delay = 30000
				if (this.globalMessageBadge > 0) {
					delay = 60000
				}
				this.$delay(function () {
					this.checkMessages()
				}, delay)
			})
	}

	/**
	 * 底部伸展框
	 */
	this.showQQGroupQrcode = function () {
		teaweb.popup("/about/qq", {
			width: "21em",
			title: 'QQ群',
			height: "24em"
		})
	}
	this.switchLang = function () {
		this.$post("/settings/lang/switch")
			.success(function () {
				window.location.reload()
			})
	}
	/**
	 * 弹窗中默认成功回调
	 */
	if (window.IS_POPUP === true) {
		this.success = window.NotifyPopup
	}

	// switch language
	this.switchLang = function () {
		this.$post("/settings/lang/switch")
			.success(function () {
				window.location.reload()
			})
	}

	// switch dark mode
	document.documentElement.classList.remove("light");
	document.documentElement.classList.remove("dark");

	let darkMode = localStorage.getItem("teaDarkMode");
	if (darkMode === "dark") {
		document.documentElement.classList.add("dark");
		this.isDarkMode = true
	} else {
		document.documentElement.classList.add("light");
		this.isDarkMode = false
	}

	this.switchDarkMode = function () {
		// set localStorage
		let darkMode = localStorage.getItem("teaDarkMode");
		document.documentElement.classList.remove("light");
		document.documentElement.classList.remove("dark");

		if (darkMode === "dark") {
			localStorage.setItem("teaDarkMode", "light");
			document.documentElement.classList.add("light");
		} else {
			localStorage.setItem("teaDarkMode", "dark");
			document.documentElement.classList.add("dark");
		}
		window.location.reload();
	}

	// main menu
	this.menuVisible = false;
	this.triggerMobileMenu = function () {
		this.menuVisible = !this.menuVisible;
	}

	// 
	this.expandedMenu = window.TEA.ACTION.data.teaMenu;
	this.toggleMenu = function (menu) {
		if (this.expandedMenu === menu) {
			this.expandedMenu = null;
			window.TEA.ACTION.data.teaMenu = null;
		} else {
			this.expandedMenu = menu;
			window.TEA.ACTION.data.teaMenu = menu;
		}
		this.$forceUpdate();
	};
	this.isMenuExpanded = function (menu) {
		return this.expandedMenu === menu || window.TEA.ACTION.data.teaMenu === menu;
	};
	this.isSubMenuActive = function (menu) {
		return window.location.pathname.split('?')[0] == menu?.split('?')[0];
	}
	this.showMessages = function () {
		window.location.href = "/messages";
	}

	this.iconMap = {
		'dashboard': 'pi-gauge',
		'clone outline': 'pi-sitemap',
		'cloud': 'pi-cloud',
		'globe': 'pi-globe',
		'cubes': 'pi-map',
		'users': 'pi-users',
		'yen sign': 'pi-dollar',
		'ticket': 'pi-ticket',
		'user secret': 'pi-users',
		'history': 'pi-history',
		'setting': 'pi-cog',
		'paper plane': 'pi-send',
		'magnet': 'pi-shield',
		'puzzle piece': 'pi-th-large',
		'address book': 'pi-address-book',
		'shield': 'pi-shield',
	};

	this.iconMap2 = {
		'dashboard': 'pi-chart-bar',
		'chart area': 'pi-chart-line',
		'history': 'pi-history',
		'setting': 'pi-cog',
		'trash': 'pi-trash',
	};

	/**
	 * 切换主题
	 */
	this.themePanelVisible = false;
	this.themePanelPosition = {
		top: 0,
		left: 0,
	};
	this.showThemePanel = (ev) => {
		this.themePanelVisible = true;
		ev.stopPropagation();

		const rect = ev.target.getBoundingClientRect();
		this.themePanelPosition = {
			top: rect.top + rect.height + 5 + 15,
			left: rect.left - 95,
		};
	};

	document.addEventListener('click', (e) => {
		this.themePanelVisible = false;
	});
	document.addEventListener('scroll', (e) => {
		this.themePanelVisible = false;
	});
	window.addEventListener('resize', (e) => {
		this.themePanelVisible = false;
	});

	this.changeTheme = function (theme) {
		this.$post("/ui/theme")
			.params({ theme })
			.success(function (resp) {
				teaweb.successToast("界面风格已切换")
				this.teaTheme = resp.data.theme
				window.location.reload()
			})
	}
	this.getCssVariable = window.getCssVariable;
});

window.NotifySuccess = function (message, url, params) {
	if (typeof (url) == "string" && url.length > 0) {
		if (url[0] != "/") {
			url = Tea.url(url, params);
		}
	}
	return function () {
		teaweb.success(message, function () {
			window.location = url;
		});
	};
};

window.NotifyReloadSuccess = function (message) {
	return function () {
		teaweb.success(message, function () {
			window.location.reload()
		})
	}
}

window.NotifyDelete = function (message, url, params) {
	teaweb.confirm(message, function () {
		Tea.Vue.$post(url)
			.params(params)
			.refresh();
	});
};

window.NotifyPopup = function (resp) {
	window.parent.teaweb.popupFinish(resp);
};

window.ChangePageSize = function (size) {
	let url = window.location.toString();
	if (url.indexOf("pageSize") > 0) {
		url = url.replace(/pageSize=\d+/g, "pageSize=" + size);
	} else {
		if (url.indexOf("?") > 0) {
			url += "&pageSize=" + size;
		} else {
			url += "?pageSize=" + size;
		}
	}
	window.location = url;
};

// utils
window.getCssVariable = (variableName, selector)=>{
	// 如果嵌套变量仍然是一个变量（以 "var(" 开头），则继续解析
	function getFinalVariableValue(variable) {
		if (variable.startsWith('var(')) {
			// 提取变量名，例如从 "var(--color-theme-3)" 提取 "--color-theme-3"
			const innerVariableName = variable.match(/var\((--[\w-]+)\)/)[1];
			const innerVariableValue = getComputedStyle(root).getPropertyValue(innerVariableName).trim();

			// 递归解析，直到得到最终值
			return getFinalVariableValue(innerVariableValue);
		} else {
			// 如果不是变量，直接返回值
			return variable;
		}
	}
	if (selector) {
		const nestedVariable = getComputedStyle(document.querySelector(selector)).getPropertyValue(variableName).trim();
		return getFinalVariableValue(nestedVariable);
	}else{
		return getFinalVariableValue(getComputedStyle(document.documentElement).getPropertyValue(variableName).trim());
	}
}

Vue.use(PrimeVue)
Vue.component('p-calendar', calendar)
Vue.component('p-radiobutton', radiobutton)
Vue.component('p-checkbox', checkbox)
Vue.component('p-switch', inputswitch)
//  注册antd 1.7.8
Vue.use(antd)

Vue.component("file-upload", {
	props: ['id', 'name', 'accept', 'multiple'],
	template: `
	<div class="b-file-upload-container">
		<input :id="id" type="file" :name="name" :accept="accept" :multiple="multiple" @change="$emit('change', $event)" />
		<button class="b-file-upload">
			<span class="p-button-icon p-button-icon-left pi pi-plus" data-pc-section="icon"></span>
			<span>选择文件</span>
		</button>
	</div>
	`,
});

Vue.component("b-empty", {
	props: {
		large: {
			type: Boolean,
			default: false,
		},
	},
	template: `
		<div>
			<div class="b-empty" v-if="!large">
				<slot></slot>
			</div>
			<div class="b-empty-large" v-else>
				<i class="pi pi-exclamation-triangle b-empty-large-icon"></i>
				<div class="b-empty-large-message">
					<slot></slot>
				</div>
			</div>
		</div>
	`,
});

// TODO: b-collapse
Vue.component("b-collapse", {
	props: ['title', 'links'],
	template: `
		<div class="b-collapse-container">
			<div class="title">{{title}}：</div>
			<div class="links">
				<a v-for="link in links" :href="link.href" class="link">{{link.text}}</a>
			</div>
		</div>
	`,
});

Vue.component('b-settings-header', {
	props: {
		actionText: String,
		subTitle: String,
		href: String,
	},
	template: `
		<h3 class="b-settings-header">
			<span class="title"><slot></slot></span>
			<div class="sub-title" v-if="subTitle">{{subTitle}}</div>
			<a class="action" v-if="actionText && href" :href="href">
				{{actionText}}
			</a>
			<a class="action" v-if="actionText && !href" @click.prevent="$emit('action')">
				{{actionText}}
			</a>
		</h3>
	`,
});

// TODO: b-breadcrumb
Vue.component('b-breadcrumb', {
	props: ['url', 'current'],
	template: `
		<div class="b-breadcrumb">
			<span class="back-container">
				<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4"><path data-v-a6e9e3fd="" stroke-linecap="round" stroke-linejoin="round" d="m2.25 12 8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25"></path></svg>
				<a :href="url">
					<slot></slot>
				</a>
			</span>
			<i class="pi pi-angle-right arrow-right" style="opacity: .6"></i>
			<span class="current-name" style="opacity: .6">
				{{current}}
			</span>
		</div>
	`,
});
// TODO: b-page-header
Vue.component('b-page-header', {
	props: ['backUrl', 'subTitle'],
	template: `
		<div class="b-page-head">
			<div class="title-container">
				<a :href="backUrl" class="back-btn">
					<i class="pi pi-arrow-left"></i>
				</a>

				<span class="name">
					<slot></slot>

					<span v-if="subTitle">({{subTitle}})</span>
				</span>
			</div>
		</div>
	`,
});

Vue.component('b-add-button', {
	template: `
		<button class="b-add-button" type="button" @click.prevent="$emit('click')">
			<i class="pi pi-plus"></i>
		</button>
	`,
});

// id, onchange, options
Vue.component('b-select', {
	// props: ['name', 'options', 'value'],
	props: {
		id: String,
		name: String,
		value: [String, Number],
		options: Array, // {label, value}[]
		style: String,
		appendTo: {
			type: String,
			default: 'app'
		},
		autoWidth: {
			type: Boolean,
			default: false,
		},
	},
	data() {
		return {
			currentHoverIndex: -1,
			opened: false,
		};
	},
	outsideClickListener: null,
	resizeListener: null,
	scrollHandler: null,
	methods: {
		handleItemClick(option) {
			this.$emit('input', option.value);
			this.$emit('change', option.value);
			this.opened = false;
		},
		handleOpen() {
			this.opened = !this.opened;
		},
		documentClickHandle(e) {
			if (this.opened) {
				const target = e.target;
				if (target.closest('.b-select-container') && target.closest('.b-select-container').querySelector('.b-select-dropdown')) {
					return;
				}
				this.opened = false;
			}
		},
		onOverlayEnter() {
			this.$refs.overlay.style.zIndex = String(domhandler.generateZIndex());
			this.appendContainer();
			this.alignOverlay();
			this.bindOutsideClickListener();
			this.bindScrollListener();
			this.bindResizeListener();
			this.$emit('show');
		},
		onOverlayLeave() {
				this.unbindOutsideClickListener();
				this.unbindScrollListener();
				this.unbindResizeListener();
				this.$emit('hide');
		},
		show() {
			this.$emit('before-show');
			this.opened = true;
		},
		hide() {
			this.$emit('before-hide');
			this.opened = false;
		},
		bindOutsideClickListener() {
			if (!this.outsideClickListener) {
					this.outsideClickListener = (event) => {
							if (this.opened && this.isOutsideClicked(event)) {
									this.hide();
							}
					};
					document.addEventListener('click', this.outsideClickListener);
			}
		},
		unbindOutsideClickListener() {
			if (this.outsideClickListener) {
					document.removeEventListener('click', this.outsideClickListener);
					this.outsideClickListener = null;
			}
		},
		bindScrollListener() {
				if (!this.scrollHandler) {
						this.scrollHandler = new connectedoverlayscrollhandler(this.$el, () => {
								if (this.opened) {
										this.hide();
								}
						});
				}
				this.scrollHandler.bindScrollListener();
		},
		unbindScrollListener() {
				if (this.scrollHandler) {
						this.scrollHandler.unbindScrollListener();
				}
		},
		appendContainer() {
			if (this.appendTo) {
					if (this.appendTo === 'body'|| !document.getElementById(this.appendTo))
							document.body.appendChild(this.$refs.overlay);
					else
							document.getElementById(this.appendTo).appendChild(this.$refs.overlay);
			}
		},
		bindResizeListener() {
			if (!this.resizeListener) {
					this.resizeListener = () => {
							if (this.opened && !domhandler.isAndroid()) {
									this.hide();
							}
					};
					window.addEventListener('resize', this.resizeListener);
			}
		},
		unbindResizeListener() {
				if (this.resizeListener) {
						window.removeEventListener('resize', this.resizeListener);
						this.resizeListener = null;
				}
		},
		isOutsideClicked(event) {
				return !(this.$refs.container.isSameNode(event.target) || this.$refs.container.contains(event.target) || (this.$refs.overlay && this.$refs.overlay.contains(event.target)));
		},
		restoreAppend() {
				if (this.$refs.overlay && this.appendTo) {
						if (this.appendTo === 'body'|| !document.getElementById(this.appendTo))
								document.body.removeChild(this.$refs.overlay);
						else
								document.getElementById(this.appendTo).removeChild(this.$refs.overlay);
				}
		},
		alignOverlay() {
			if (this.appendTo) {
					domhandler.absolutePosition(this.$refs.overlay, this.$refs.container);
					this.$refs.overlay.style.minWidth = domhandler.getOuterWidth(this.$refs.container) + 'px';
			}
			else {
					domhandler.relativePosition(this.$refs.overlay, this.$refs.container);
			}
		},
	},
	mounted() {
		document.addEventListener('click', this.documentClickHandle);
	},
	beforeDestroy() {
		this.restoreAppend();
		this.unbindOutsideClickListener();
		this.unbindResizeListener();

		if (this.scrollHandler) {
				this.scrollHandler.destroy();
				this.scrollHandler = null;
		}
		document.removeEventListener('click', this.documentClickHandle);
	},
	template: `
		<div class="b-select-container" ref="container" :class="{
			'auto-width': autoWidth
		}" :style="style">
			<input type="hidden" :id="id" :name="name" :value="value" />
			<div class="b-select" @click.prevent.stop="handleOpen">
				<span>{{options.find(option=>option.value==value)?.label}}</span>
				<svg width="14" height="14" viewBox="0 0 14 14" stroke="none" xmlns="http://www.w3.org/2000/svg" class="p-icon p-select-dropdown-icon" aria-hidden="true" data-pc-section="dropdownicon"><path d="M7.01744 10.398C6.91269 10.3985 6.8089 10.378 6.71215 10.3379C6.61541 10.2977 6.52766 10.2386 6.45405 10.1641L1.13907 4.84913C1.03306 4.69404 0.985221 4.5065 1.00399 4.31958C1.02276 4.13266 1.10693 3.95838 1.24166 3.82747C1.37639 3.69655 1.55301 3.61742 1.74039 3.60402C1.92777 3.59062 2.11386 3.64382 2.26584 3.75424L7.01744 8.47394L11.769 3.75424C11.9189 3.65709 12.097 3.61306 12.2748 3.62921C12.4527 3.64535 12.6199 3.72073 12.7498 3.84328C12.8797 3.96582 12.9647 4.12842 12.9912 4.30502C13.0177 4.48162 12.9841 4.662 12.8958 4.81724L7.58083 10.1322C7.50996 10.2125 7.42344 10.2775 7.32656 10.3232C7.22968 10.3689 7.12449 10.3944 7.01744 10.398Z" fill="currentColor"></path></svg>
			</div>
			<transition @enter="onOverlayEnter" @leave="onOverlayLeave">
				<div ref="overlay" class="b-select-dropdown" v-if="opened">
					<template v-for="option, index in options">
						<div v-if="option.type==='header'" class="b-select-dropdown-header">
							{{option.label}}
						</div>
						<div v-else
							class="b-select-dropdown-item"
							:class="{
								current: option.value == value,
								hover: currentHoverIndex == index
							}"
							@click="handleItemClick(option)"
							@mouseenter="currentHoverIndex=index"
							@mouseleave="currentHoverIndex=-1"
						>
							{{option.label}}
						</div>
					</template>
				</div>
			</transition>
		</div>
	`,
});

Vue.component('b-button', {
	props: {
		type: {
			type: String,
			default: 'button',
		},
	},
	template: `
		<button :type="type" class="b-button" @click="$emit('click')">
			<slot></slot>
		</button>
	`,
});

// TODO: b-notice
Vue.component('b-notice', {
	template: `
		<div class="b-notice">
			<slot></slot>
		</div>
	`,
});

Vue.component('b-steps', {
	props: {
		steps: Array, // {label, key}[]
		current: String,
	},
	template: `
		<div class="b-steps">
			<template v-for="step, index in steps">
				<div class="step" :class="{
					current: step.key == current,
				}">
					<div class="number">
						{{index+1}}
					</div>
					<div class="label">
						{{step.label}}
					</div>
				</div>
				<div class="line" v-if="index < steps.length - 1"></div>
			</template>
		</div>
	`,
});

// TODO: b-status-card
// status card
Vue.component('b-status-card', {
	props: {
		title: String,
	},
	template: `
		<div class="b-status-card">
			<div class="card-title" v-if="title">{{title}}</div>
			<div class="card-container">
				<slot></slot>
			</div>
		</div>
	`,
});
Vue.component('b-status-card-item', {
	props: {
		label: String,
		subLabel: String,
		span: String,
		comment: {
			type: Array,
			default: () => [],
		}
	},
	template: `
		<div class="b-status-card-item" :class="{
			'item-span-2': span == '2',
			'item-span-3': span == '3',
			'item-full': span == 'full',
		}">
			<div class="label" v-if="label">
				{{label}}
				<span class="sub-label" v-if="subLabel">{{subLabel}}</span>
			</div>
			<div class="value">
				<slot></slot>
			</div>
			<div class="comment" v-for="line in comment">
				<span v-html="line"></span>
			</div>
		</div>
	`,
});

// message
Vue.component('b-message', {
	props: {
		type: {
			type: String,
			default: 'info', // info warning error
		},
		closeable: {
			type: Boolean,
			default: false,
		},
		action: {
			type: Object, // {text, href}
		},
		code: String,
	},
	data() {
		return {
			visible: true,
		};
	},
	methods: {
		close() {
			this.visible = false;
			// $emit('close');
		},
	},
	template: `
		<div class="b-message" :code="code" :class="[type]" v-if="visible">
			<i v-if="type==='warning' || type==='error'" class="p-message-icon pi pi-exclamation-triangle"></i>
			<i v-else class="p-message-icon pi pi-info-circle"></i>
			<div class="b-message-content">
				<slot></slot>
			</div>
			<a v-if="closeable" href="javascript:;" class="p-message-close pi pi-times" @click="close">
		</div>
	`,
});

// label
Vue.component('b-label-group', {
	template: `
		<div v-if="$slots.default" class="b-label-group">
			<slot></slot>
		</div>
	`,
});
Vue.component('b-label', {
	props: {
		color: {
			type: String, // grey red olive
			default: 'default',
		},
		size: {
			type: String, // small tiny
			default: 'default',
		},
		href: String,
		title: String,
		text: String,
	},
	template: `
		<a
			v-if="href"
			:href="href"
			class="b-label"
			:title="title"
			:class="['color-'+color, 'size-'+size]"
		>
			<span><slot>{{text}}</slot></span>
		</a>
		<div
			v-else
			class="b-label"
			:class="['color-'+color, 'size-'+size]"
			:title="title"
		>
			<span><slot>{{text}}</slot></span>
		</div>
	`,
});