<script setup>

import "@/lib/array.js"
import useUtils from "@/utils/utils.js"
import {ref, watch} from "vue"
import TInputText from "@/components/ui/TInputText.vue";
import CodeLabel from "@/components/common/CodeLabel.vue";
import TButton from "@/components/ui/TButton.vue";
import TTextarea from "@/components/ui/TTextarea.vue";
import TSelect from "@/components/ui/TSelect.vue";
import TOption from "@/components/ui/TOption.vue";
import TLabel from "@/components/ui/TLabel.vue";
import PlusButton from "@/components/common/PlusButton.vue";
import TDivider from "@/components/ui/TDivider.vue";

const utils = useUtils()

const props = defineProps(["v-domains", "name", "v-support-wildcard"])

const addingDomainRef = ref()
const batchDomainsRef = ref()
const emits = defineEmits(["change"])

const {
	domains,
	mode,
	batchDomains,
	isAdding,
	addingDomain,
	isEditing,
	editingIndex,
	realName,
	supportWildcard
} = (function () {
	let domains = props.vDomains
	if (domains == null) {
		domains = []
	}

	let realName = "domainsJSON"
	if (props.name != null && typeof props.name == "string") {
		realName = props.name
	}

	let supportWildcard = true
	if (typeof props.vSupportWildcard == "boolean") {
		supportWildcard = props.vSupportWildcard
	}

	return {
		domains: ref(domains),

		mode: ref("single"),
		batchDomains: ref(""),

		isAdding: ref(false),
		addingDomain: ref(""),

		isEditing: ref(false),
		editingIndex: ref(-1),

		realName: ref(realName),
		supportWildcard: ref(supportWildcard)
	}
})()

const add = function () {
	isAdding.value = true
	setTimeout(function () {
		addingDomainRef.value.focus()
	}, 100)
}

const confirm = function () {
	if (mode.value == "batch") {
		confirmBatch()
		return
	}

	// 删除其中的空格
	addingDomain.value = addingDomain.value.replace(/\s/g, "")

	if (addingDomain.value.length == 0) {
		utils.warn("请输入要添加的域名", function () {
			addingDomainRef.value.focus()
		})
		return
	}

	// 基本校验
	if (supportWildcard.value) {
		if (addingDomain.value[0] == "~") {
			let expr = addingDomain.value.substring(1)
			try {
				new RegExp(expr)
			} catch (e) {
				utils.warn("正则表达式错误：" + e.message, function () {
					addingDomainRef.value.focus()
				})
				return
			}
		}
	} else {
		if (/[*~^]/.test(addingDomain.value)) {
			utils.warn("当前只支持添加普通域名，域名中不能含有特殊符号", function () {
				addingDomainRef.value.focus()
			})
			return
		}
	}

	if (isEditing.value && editingIndex.value >= 0) {
		domains.value[editingIndex.value] = addingDomain.value
	} else {
		// 分割逗号（，）、顿号（、）
		if (addingDomain.value.match("[，、,;]")) {
			let domainList = addingDomain.value.split(new RegExp("[，、,;]"))
			domainList.forEach(function (v) {
				if (v.length > 0) {
					domains.value.push(v)
				}
			})
		} else {
			domains.value.push(addingDomain.value)
		}
	}
	cancel()
	change()
}

const confirmBatch = function () {
	let _domains = batchDomains.value.split("\n")
	let realDomains = []
	let hasProblems = false
	_domains.forEach(function (domain) {
		if (hasProblems) {
			return
		}
		if (domain.length == 0) {
			return
		}
		if (supportWildcard.value) {
			if (domain == "~") {
				let expr = domain.substring(1)
				try {
					new RegExp(expr)
				} catch (e) {
					hasProblems = true
					utils.warn("正则表达式错误：" + e.message, function () {
						batchDomainsRef.value.focus()
					})
					return
				}
			}
		} else {
			if (/[*~^]/.test(domain)) {
				hasProblems = true
				utils.warn("当前只支持添加普通域名，域名中不能含有特殊符号", function () {
					batchDomainsRef.value.focus()
				})
				return
			}
		}
		realDomains.push(domain)
	})
	if (hasProblems) {
		return
	}
	if (realDomains.length == 0) {
		utils.warn("请输入要添加的域名", function () {
			batchDomainsRef.value.focus()
		})
		return
	}

	realDomains.forEach(function (domain) {
		domains.value.push(domain)
	})
	cancel()
	change()
}

const edit = function (index) {
	addingDomain.value = domains.value[index]
	isEditing.value = true
	editingIndex.value = index
	setTimeout(function () {
		addingDomainRef.value.focus()
	}, 50)
}

const remove = function (index) {
	domains.value.$remove(index)
	change()
}

const cancel = function () {
	isAdding.value = false
	mode.value = "single"
	batchDomains.value = ""
	isEditing.value = false
	editingIndex.value = -1
	addingDomain.value = ""
}

const change = function () {
	emits("change", domains.value)
}

watch(() => props.vSupportWildcard, function (v) {
	if (typeof v == "boolean") {
		supportWildcard.value = v
	}
})

watch(mode, function (mode) {
	setTimeout(function () {
		if (mode == "single") {
			if (addingDomainRef.value != null) {
				addingDomainRef.value.focus()
			}
		} else if (mode == "batch") {
			if (batchDomainsRef.value != null) {
				batchDomainsRef.value.focus()
			}
		}
	}, 100)
})

</script>

<template>
	<div class="domains-box">
		<input type="hidden" :name="realName" :value="JSON.stringify(domains)"/>
		<div v-if="domains.length > 0" class="label-group">
			<TLabel outlined="" v-for="(domain, index) in domains" :class="{blue: index == editingIndex}">
				<span v-if="domain.length > 0 && domain[0] == '~'" class="grey" style="font-style: normal">[正则]</span>
				<span v-if="domain.length > 0 && domain[0] == '.'" class="grey" style="font-style: normal">[后缀]</span>
				<span v-if="domain.length > 0 && domain[0] == '*'" class="grey" style="font-style: normal">[泛域名]</span>
				{{ domain }}
				<span v-if="!isAdding && !isEditing">
				&nbsp; <a href="" title="修改" @click.prevent="edit(index)"><i class="icon pencil small"></i></a>
				&nbsp; <a href="" title="删除" @click.prevent="remove(index)"><i class="icon remove small"></i></a>
			</span>
				<span v-if="isAdding || isEditing">
				&nbsp; <a class="disabled"><i class="icon pencil small"></i></a>
				&nbsp; <a class="disabled"><i class="icon remove small"></i></a>
			</span>
			</TLabel>
		</div>
		<div v-if="isAdding || isEditing">
			<div class="ui fields inline mt-2" style="align-items: start;">
				<div class="ui field" v-if="isAdding">
					<TSelect v-model="mode" style="width: 80px!important">
						<TOption value="single">单个</TOption>
						<TOption value="batch">批量</TOption>
					</TSelect>
				</div>
				<div class="ui field">
					<div v-show="mode == 'single'">
						<TInputText type="text" v-model="addingDomain" @keyup.enter="confirm()" @keypress.enter.prevent="1" @keydown.esc="cancel()" ref="addingDomainRef" :placeholder="supportWildcard ? 'example.com、*.example.com' : 'example.com、www.example.com'" size="30" maxlength="100" class="w-full"/>
					</div>
					<div v-show="mode == 'batch'">
						<TTextarea cols="30" v-model="batchDomains" :placeholder="'example1.com\nexample2.com\n每行一个域名'" ref="batchDomainsRef" class="w-full" rows="5"></TTextarea>
					</div>
				</div>
				<div class="ui field">
					<TButton class="btn-confirm" secondary="" type="button" @click.prevent="confirm">确定</TButton>
					&nbsp;&nbsp;&nbsp; <a href="" title="取消" @click.prevent="cancel"><i class="icon remove small"></i></a>
				</div>
			</div>
			<p class="comment" v-if="supportWildcard">支持普通域名（
				<CodeLabel>example.com</CodeLabel>
				）、泛域名（
				<CodeLabel>*.example.com</CodeLabel>
				）<span v-if="vSupportWildcard == undefined">、域名后缀（以点号开头，如<CodeLabel>.example.com</CodeLabel>）和正则表达式（以波浪号开头，如<CodeLabel>~.*.example.com</CodeLabel>）</span>；如果域名后有端口，请加上端口号。
			</p>
			<p class="comment" v-if="!supportWildcard">只支持普通域名（
				<CodeLabel>example.com</CodeLabel>
				、
				<CodeLabel>www.example.com</CodeLabel>
				）。
			</p>
			<TDivider></TDivider>
		</div>
		<div style="margin-top: 0.5em" v-if="!isAdding">
			<PlusButton size="small" @click.prevent="add"></PlusButton>
		</div>
	</div>
</template>

<style scoped>
:deep(.domains-box) {
	font-family: Source Han Sans SC;
}
:deep(.btn-confirm) {
	color: rgba(101, 112, 128, 1);
	height: 38px;
	line-height: 38px;
	border-radius: 4px;
	background-color: rgba(238, 242, 250, 1);
	font-weight: 400;
	font-size: 14px;
	padding: 0 14px;
}
:deep(.p-chip) {
	color: rgba(101, 112, 128, 1);
}
:deep(.p-select-label) {
	padding-right: 0;
}
.comment {
	font-weight: 400;
	font-size: 12px;
}
</style>
