<script setup>

import "@/lib/array.js"
import useUtils from "@/utils/utils.js"
import {ref, watch} from "vue"
import TSelect from "@/components/ui/TSelect.vue";
import TOption from "@/components/ui/TOption.vue";
import TInputText from "@/components/ui/TInputText.vue";
import TButton from "@/components/ui/TButton.vue";
import TipIcon from "@/components/common/TipIcon.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(["modelValue"])

const patternInputRef = ref()
const emits = defineEmits(["input", "update:modelValue"])

const {patterns, isAdding, addingPattern, editingIndex, patternIsInvalid, windowIsSmall} = (function () {
	let patterns = []
	if (props.modelValue != null) {
		patterns = props.modelValue
	}

	return {
		patterns: ref(patterns),
		isAdding: ref(false),

		addingPattern: ref({"type": "wildcard", "pattern": ""}),
		editingIndex: ref(-1),

		patternIsInvalid: ref(false),

		windowIsSmall: ref(window.innerWidth)
	}
})()

const add = function () {
	isAdding.value = true
	setTimeout(function () {
		patternInputRef.value.focus()
	})
}

const edit = function (index) {
	isAdding.value = true
	editingIndex.value = index
	addingPattern.value = {
		type: patterns.value[index].type,
		pattern: patterns.value[index].pattern
	}
}

const confirm = function () {
	if (requireURL(addingPattern.value.type)) {
		let pattern = addingPattern.value.pattern.trim()
		if (pattern.length == 0) {
			utils.warn("请输入URL", function () {
				patternInputRef.value.focus()
			})
			return
		}
	}
	if (editingIndex.value < 0) {
		patterns.value.push({
			type: addingPattern.value.type,
			pattern: addingPattern.value.pattern
		})
	} else {
		patterns.value[editingIndex.value].type = addingPattern.value.type
		patterns.value[editingIndex.value].pattern = addingPattern.value.pattern
	}
	notifyChange()
	cancel()
}

const remove = function (index) {
	patterns.value.$remove(index)
	cancel()
	notifyChange()
}

const cancel = function () {
	isAdding.value = false
	addingPattern.value = {"type": "wildcard", "pattern": ""}
	editingIndex.value = -1
}

const patternTypeName = function (patternType) {
	switch (patternType) {
		case "wildcard":
			return "通配符"
		case "regexp":
			return "正则"
		case "images":
			return "常见图片文件"
		case "audios":
			return "常见音频文件"
		case "videos":
			return "常见视频文件"
	}
	return ""
}

const notifyChange = function () {
	emits("input", patterns.value)
	emits("update:modelValue", patterns.value)
}

const changePattern = function () {
	patternIsInvalid.value = false
	let pattern = addingPattern.value.pattern
	switch (addingPattern.value.type) {
		case "wildcard":
			if (pattern.indexOf("?") >= 0) {
				patternIsInvalid.value = true
			}
			break
		case "regexp":
			if (pattern.indexOf("?") >= 0) {
				let pieces = pattern.split("?")
				for (let i = 0; i < pieces.length - 1; i++) {
					if (pieces[i].length == 0 || pieces[i][pieces[i].length - 1] != "\\") {
						patternIsInvalid.value = true
					}
				}
			}
			break
	}
}

const requireURL = function (patternType) {
	return patternType == "wildcard" || patternType == "regexp"
}

watch(() => addingPattern.value.type, () => {
	if (patternInputRef.value != null) {
		setTimeout(() => {
			patternInputRef.value.focus()
		})
	}
})
</script>

<template>
	<div>
		<div v-show="patterns.length > 0" class="label-group">
			<TLabel outlined="" v-for="(pattern, index) in patterns" :class="{blue: index == editingIndex, disabled: isAdding && index != editingIndex}">
				<span class="grey" style="font-weight: normal">[{{ patternTypeName(pattern.type) }}]</span>
				<span>{{ pattern.pattern }}</span> &nbsp;
				<a href="" title="修改" @click.prevent="edit(index)"><i class="pi pi-pencil tiny"></i></a> &nbsp;
				<a href="" title="删除" @click.prevent="remove(index)"><i class="pi pi-remove small"></i></a>
			</TLabel>
			<TDivider></TDivider>
		</div>
		<div v-show="isAdding" style="margin-top: 0.5em">
			<div class="ui fields inline">
				<div class="ui field">
					<TSelect v-model="addingPattern.type">
						<TOption value="wildcard">通配符</TOption>
						<TOption value="regexp">正则表达式</TOption>
						<TOption value="images">常见图片</TOption>
						<TOption value="audios">常见音频</TOption>
						<TOption value="videos">常见视频</TOption>
					</TSelect>
				</div>
				<div class="ui field" v-show="addingPattern.type == 'wildcard' || addingPattern.type ==  'regexp'">
					<TInputText type="text" :placeholder="(addingPattern.type == 'wildcard') ? '可以使用星号（*）通配符，不区分大小写' : '可以使用正则表达式，不区分大小写'" v-model="addingPattern.pattern" @input="changePattern" size="36" ref="patternInputRef" @keyup.enter="confirm()" @keypress.enter.prevent="1" spellcheck="false"/>
					<p class="comment" v-if="patternIsInvalid">
						<span class="red" style="font-weight: normal"><span v-if="addingPattern.type == 'wildcard'">通配符</span><span v-if="addingPattern.type == 'regexp'">正则表达式</span>中不能包含问号（?）及问号以后的内容。</span>
					</p>
				</div>
				<div class="ui field" style="padding-left: 0" v-show="addingPattern.type == 'wildcard' || addingPattern.type ==  'regexp'">
					<TipIcon content="通配符示例：<br/>单个路径开头：/hello/world/*<br/>单个路径结尾：*/hello/world<br/>包含某个路径：*/article/*<br/>某个域名下的所有URL：*example.com/*<br/>忽略某个扩展名：*.js" v-if="addingPattern.type == 'wildcard'"></TipIcon>
					<TipIcon content="正则表达式示例：<br/>单个路径开头：^/hello/world<br/>单个路径结尾：/hello/world$<br/>包含某个路径：/article/<br/>匹配某个数字路径：/article/(\\d+)<br/>某个域名下的所有URL：^(http|https)://example.com/" v-if="addingPattern.type == 'regexp'"></TipIcon>
				</div>
				<div class="ui field">
					<TButton secondary="" size="small" :class="{disabled:patternIsInvalid}" type="button" @click.prevent="confirm">确定</TButton> &nbsp;
					<a href="" title="取消" @click.prevent="cancel"><i class="pi pi-remove small"></i></a>
				</div>
			</div>
		</div>
		<div v-if=!isAdding style="margin-top: 0.5em">
			<PlusButton size="small" type="button" @click.prevent="add"></PlusButton>
		</div>
	</div>
</template>

<style scoped>
</style>
