<script setup>

import "@/lib/array.js"
import {onMounted, ref, watch} from "vue"
import CodeLabel from "@/components/common/CodeLabel.vue";
import TInputText from "@/components/ui/TInputText.vue";
import ValuesBox from "@/components/common/ValuesBox.vue";
import TSelect from "@/components/ui/TSelect.vue";
import TOption from "@/components/ui/TOption.vue";
import TCheckboxBinary from "@/components/ui/TCheckboxBinary.vue";

const props = defineProps(["v-cond"])

const {
	cond,
	operators,
	operator,
	operatorDescription,
	variables,
	variable,
	stringValue,
	numberValue,
	modDivValue,
	modRemValue,
	stringValues,
	versionRangeMinValue,
	versionRangeMaxValue
} = (function () {
	let cond = {
		isRequest: true,
		param: "",
		operator: window.REQUEST_COND_OPERATORS[0].op,
		value: "",
		isCaseInsensitive: false
	}
	if (props.vCond != null) {
		cond = props.vCond
	}
	return {
		cond: ref(cond),
		operators: ref(window.REQUEST_COND_OPERATORS),
		operator: ref(window.REQUEST_COND_OPERATORS[0].op),
		operatorDescription: ref(window.REQUEST_COND_OPERATORS[0].description),
		variables: ref(window.REQUEST_VARIABLES),
		variable: ref(""),

		stringValue: ref(""),
		numberValue: ref(""),

		modDivValue: ref(""),
		modRemValue: ref(""),

		stringValues: ref([]),

		versionRangeMinValue: ref(""),
		versionRangeMaxValue: ref("")
	}
})()

const changeVariable = function () {
	let v = cond.value.param
	if (v == null) {
		v = ""
	}
	cond.value.param = v + variable.value
}

const changeOperator = function () {
	operators.value.forEach(function (v) {
		if (v.op == operator.value) {
			operatorDescription.value = v.description
		}
	})

	cond.value.operator = operator.value

	// 移动光标
	let box = document.getElementById("variables-value-box")
	if (box != null) {
		setTimeout(function () {
			let input = box.getElementsByTagName("INPUT")
			if (input.length > 0) {
				input[0].focus()
			}
		}, 100)
	}
}

const changeStringValues = function (v) {
	stringValues.value = v
	cond.value.value = JSON.stringify(v)
}

watch(stringValue, function (v) {
	cond.value.value = v
})

watch(numberValue, function (v) {
	// TODO 校验数字
	cond.value.value = v
})

watch(modDivValue, function (v) {
	if (v.length == 0) {
		return
	}
	let div = parseInt(v)
	if (isNaN(div)) {
		div = 1
	}
	modDivValue.value = div
	cond.value.value = div + "," + modRemValue.value
})

watch(modRemValue, function (v) {
	if (v.length == 0) {
		return
	}
	let rem = parseInt(v)
	if (isNaN(rem)) {
		rem = 0
	}
	modRemValue.value = rem
	cond.value.value = modDivValue.value + "," + rem
})

watch(versionRangeMinValue, function (v) {
	cond.value.value = versionRangeMinValue.value + "," + versionRangeMaxValue.value
})

watch(versionRangeMaxValue, function (v) {
	cond.value.value = versionRangeMinValue.value + "," + versionRangeMaxValue.value
})

onMounted(() => {
	let cond = props.vCond
	if (cond == null) {
		return
	}
	operator.value = cond.operator

	// stringValue
	if (["regexp", "not regexp", "eq", "not", "prefix", "suffix", "contains", "not contains", "eq ip", "gt ip", "gte ip", "lt ip", "lte ip", "ip range"].$contains(cond.operator)) {
		stringValue.value = cond.value
		return
	}

	// numberValue
	if (["eq int", "eq float", "gt", "gte", "lt", "lte", "mod 10", "ip mod 10", "mod 100", "ip mod 100"].$contains(cond.operator)) {
		numberValue.value = cond.value
		return
	}

	// modValue
	if (["mod", "ip mod"].$contains(cond.operator)) {
		let pieces = cond.value.split(",")
		modDivValue.value = pieces[0]
		if (pieces.length > 1) {
			modRemValue.value = pieces[1]
		}
		return
	}

	// stringValues
	if (["in", "not in", "file ext", "mime type"].$contains(cond.operator)) {
		try {
			let arr = JSON.parse(cond.value)
			if (arr != null && (arr instanceof Array)) {
				arr.forEach(function (v) {
					stringValues.value.push(v)
				})
			}
		} catch (e) {

		}
		return
	}

	// versionValue
	if (["version range"].$contains(cond.operator)) {
		let pieces = cond.value.split(",")
		versionRangeMinValue.value = pieces[0]
		if (pieces.length > 1) {
			versionRangeMaxValue.value = pieces[1]
		}
		return
	}
})
</script>

<template>
	<tbody>
	<tr>
		<td style="width: 8em">参数值</td>
		<td>
			<input type="hidden" name="condJSON" :value="JSON.stringify(cond)"/>
			<div>
				<div class="ui field">
					<TInputText type="text" placeholder="\${xxx}" v-model="cond.param" class="w-full"/>
				</div>
				<div class="ui field mt-2">
					<TSelect v-model="variable" @change="changeVariable">
						<TOption value="">[常用参数]</TOption>
						<TOption v-for="v in variables" :value="v.code">{{ v.code }} - {{ v.name }}</TOption>
					</TSelect>
				</div>
			</div>
			<p class="comment">其中可以使用变量，类似于
				<CodeLabel>${requestPath}</CodeLabel>
				，也可以是多个变量的组合。
			</p>
		</td>
	</tr>
	<tr>
		<td>操作符</td>
		<td>
			<div>
				<TSelect v-model="operator" @change="changeOperator">
					<TOption v-for="operator in operators" :value="operator.op">{{ operator.name }}</TOption>
				</TSelect>
				<p class="comment" v-html="operatorDescription"></p>
			</div>
		</td>
	</tr>
	<tr v-show="!['file exist', 'file not exist'].$contains(cond.operator)">
		<td>对比值</td>
		<td id="variables-value-box">
			<!-- 正则表达式 -->
			<div v-if="['regexp', 'not regexp'].$contains(cond.operator)">
				<TInputText type="text" v-model="stringValue" class="w-full"/>
				<p class="comment">要匹配的正则表达式，比如
					<CodeLabel>^/static/(.+).js</CodeLabel>
					。
				</p>
			</div>

			<!-- 数字相关 -->
			<div v-if="['eq int', 'eq float', 'gt', 'gte', 'lt', 'lte'].$contains(cond.operator)">
				<TInputText type="text" maxlength="11" size="11" style="width: 5em" v-model="numberValue"/>
				<p class="comment">要对比的数字。</p>
			</div>

			<!-- 取模 -->
			<div v-if="['mod 10'].$contains(cond.operator)">
				<TInputText type="text" maxlength="11" size="11" style="width: 5em" v-model="numberValue"/>
				<p class="comment">参数值除以10的余数，在0-9之间。</p>
			</div>
			<div v-if="['mod 100'].$contains(cond.operator)">
				<TInputText type="text" maxlength="11" size="11" style="width: 5em" v-model="numberValue"/>
				<p class="comment">参数值除以100的余数，在0-99之间。</p>
			</div>
			<div v-if="['mod', 'ip mod'].$contains(cond.operator)">
				<div class="ui fields inline">
					<div class="ui field">除：</div>
					<div class="ui field">
						<TInputText type="text" maxlength="11" size="11" style="width: 5em" v-model="modDivValue" placeholder="除数"/>
					</div>
					<div class="ui field">余：</div>
					<div class="ui field">
						<TInputText type="text" maxlength="11" size="11" style="width: 5em" v-model="modRemValue" placeholder="余数"/>
					</div>
				</div>
			</div>

			<!-- 字符串相关 -->
			<div v-if="['eq', 'not', 'prefix', 'suffix', 'contains', 'not contains'].$contains(cond.operator)">
				<TInputText type="text" v-model="stringValue" class="w-full"/>
				<p class="comment" v-if="cond.operator == 'eq'">和参数值一致的字符串。</p>
				<p class="comment" v-if="cond.operator == 'not'">和参数值不一致的字符串。</p>
				<p class="comment" v-if="cond.operator == 'prefix'">参数值的前缀。</p>
				<p class="comment" v-if="cond.operator == 'suffix'">参数值的后缀为此字符串。</p>
				<p class="comment" v-if="cond.operator == 'contains'">参数值包含此字符串。</p>
				<p class="comment" v-if="cond.operator == 'not contains'">参数值不包含此字符串。</p>
			</div>
			<div v-if="['in', 'not in', 'file ext', 'mime type'].$contains(cond.operator)">
				<ValuesBox @change="changeStringValues" :values="stringValues" size="15"></ValuesBox>
				<p class="comment" v-if="cond.operator == 'in'">添加参数值列表。</p>
				<p class="comment" v-if="cond.operator == 'not in'">添加参数值列表。</p>
				<p class="comment" v-if="cond.operator == 'file ext'">添加扩展名列表，比如
					<CodeLabel>png</CodeLabel>
					、
					<CodeLabel>html</CodeLabel>
					，不包括点。
				</p>
				<p class="comment" v-if="cond.operator == 'mime type'">添加MimeType列表，类似于
					<CodeLabel>text/html</CodeLabel>
					、
					<CodeLabel>image/*</CodeLabel>
					。
				</p>
			</div>
			<div v-if="['version range'].$contains(cond.operator)">
				<div class="ui fields inline">
					<div class="ui field">
						<TInputText type="text" v-model="versionRangeMinValue" maxlength="200" placeholder="最小版本" style="width: 10em"/>
					</div>
					<div class="ui field">-</div>
					<div class="ui field">
						<TInputText type="text" v-model="versionRangeMaxValue" maxlength="200" placeholder="最大版本" style="width: 10em"/>
					</div>
				</div>
			</div>

			<!-- IP相关 -->
			<div v-if="['eq ip', 'gt ip', 'gte ip', 'lt ip', 'lte ip', 'ip range'].$contains(cond.operator)">
				<TInputText type="text" style="width: 10em" v-model="stringValue" placeholder="x.x.x.x"/>
				<p class="comment">要对比的IP。</p>
			</div>
			<div v-if="['ip mod 10'].$contains(cond.operator)">
				<TInputText type="text" maxlength="11" size="11" style="width: 5em" v-model="numberValue"/>
				<p class="comment">参数中IP转换成整数后除以10的余数，在0-9之间。</p>
			</div>
			<div v-if="['ip mod 100'].$contains(cond.operator)">
				<TInputText type="text" maxlength="11" size="11" style="width: 5em" v-model="numberValue"/>
				<p class="comment">参数中IP转换成整数后除以100的余数，在0-99之间。</p>
			</div>
		</td>
	</tr>
	<tr v-if="['regexp', 'not regexp', 'eq', 'not', 'prefix', 'suffix', 'contains', 'not contains', 'in', 'not in'].$contains(cond.operator)">
		<td>不区分大小写</td>
		<td>
			<TCheckboxBinary name="condIsCaseInsensitive" v-model="cond.isCaseInsensitive"/>
			<p class="comment">选中后表示对比时忽略参数值的大小写。</p>
		</td>
	</tr>
	</tbody>
</template>

<style scoped>
</style>
