<script setup>
import PopupLayout from "@/layouts/PopupLayout.vue";
import ctxRef from "@/utils/ctx_ref.js";
import Context from "./createRulePopup.js"
import SubmitButton from "@/components/form/SubmitButton.vue";
import TInputText from "@/components/ui/TInputText.vue";
import TSelect from "@/components/ui/TSelect.vue";
import PostForm from "@/components/form/PostForm.vue";
import TOption from "@/components/ui/TOption.vue";
import TTextarea from "@/components/ui/TTextarea.vue";
import CodeLabel from "@/components/common/CodeLabel.vue";
import ComboBox from "@/components/common/ComboBox.vue";
import TCheckboxBinary from "@/components/ui/TCheckboxBinary.vue";
import HTTPCondGeneralHeaderLength from "@/components/server/HTTPCondGeneralHeaderLength.vue";
import HTTPFirewallCheckpointRefererBlock from "@/components/server/HTTPFirewallCheckpointRefererBlock.vue";
import HTTPFirewallCheckpointCC from "@/components/server/HTTPFirewallCheckpointCC.vue";
import {ref} from "vue";
import HTTPFirewallParamFiltersBox from "@/components/server/HTTPFirewallParamFiltersBox.vue";
import TLabel from "@/components/ui/TLabel.vue";
import DefinitionTable from "@/components/common/DefinitionTable.vue";
import MoreOptionsIndicator from "@/components/common/MoreOptionsIndicator.vue";

const regexpTestBody = ref()
const countryComboBox = ref()
const provinceComboBox = ref()
const cityComboBox = ref()
const ispComboBox = ref()
const ctx = ctxRef(new Context(), {
	refs: {regexpTestBody, countryComboBox, provinceComboBox, cityComboBox, ispComboBox}
})

</script>

<template>
	<PopupLayout>

		<header v-if="!ctx.isUpdating">添加规则</header>
		<header v-if="ctx.isUpdating">修改规则</header>

		<PostForm action="$" @success="ctx.success">
			<input type="hidden" name="ruleId" :value="ctx.rule.id"/>
			<input type="hidden" name="optionsJSON" v-if="ctx.checkpoint != null && ctx.checkpoint.options != null" :value="JSON.stringify(ctx.checkpoint.options)"/>
			<DefinitionTable>
				<tbody>
				<tr>
					<td class="title">参数 *</td>
					<td>
						<TSelect name="prefix" @change="ctx.changeCheckpoint()" v-model="ctx.rule.checkpointPrefix" scrollHeight="30rem" filter>
							<TOption value="">[选择参数]</TOption>
							<!-- TODO 实现optgroup -->
							<!-- TODO 将这里的参数分为多个Tab以便于更好地选择 -->
							<optgroup label="特殊参数"></optgroup>
							<template v-for="cp in ctx.checkpoints">
								<TOption v-if="cp.isComposed" :value="cp.prefix">{{ cp.name }}（{{ cp.prefix }}）</TOption>
							</template>
							<!-- TODO 实现optgroup -->
							<optgroup label="通用参数"></optgroup>
							<template v-for="cp in ctx.checkpoints">
								<TOption v-if="!cp.isComposed" :value="cp.prefix">{{ cp.name }}（{{ cp.prefix }}）</TOption>
							</template>
						</TSelect>
						<p class="comment" v-if="ctx.checkpoint != null">
							<TLabel outlined="">${<em style="font-style: normal;">{{ ctx.checkpoint.prefix }}</em>}
							</TLabel>
							<span> &nbsp;{{ ctx.checkpoint.description }}</span>
						</p>
					</td>
				</tr>

				<!-- 参数名 -->
				<tr v-if="ctx.checkpoint != null && ctx.checkpoint.hasParams">
					<td>参数名</td>
					<td>
						<TSelect name="param" v-model="ctx.rule.checkpointParam" v-if="ctx.checkpoint.params != null">
							<TOption v-for="o in ctx.checkpoint.params" :value="o.value">{{ o.name }}</TOption>
						</TSelect>
						<TInputText type="text" name="param" maxlength="100" class="w-full" v-model="ctx.rule.checkpointParam" v-if="ctx.checkpoint.params == null"/>
					</td>
				</tr>
				</tbody>

				<!-- 组合规则的选项 -->
				<tbody v-if="ctx.checkpoint != null && ctx.checkpoint.isComposed">
				<tr>
					<td colspan="2">配置选项</td>
				</tr>
				<tr>
					<td colspan="2" class="options-table-box">
						<!-- 通用header -->
						<HTTPCondGeneralHeaderLength v-if="ctx.checkpoint.prefix == 'requestGeneralHeaderLength' || ctx.checkpoint.prefix == 'responseGeneralHeaderLength'" :v-checkpoint="ctx.checkpoint"></HTTPCondGeneralHeaderLength>

						<!-- 防盗链 -->
						<HTTPFirewallCheckpointRefererBlock v-if="ctx.checkpoint.prefix == 'refererBlock'" :v-checkpoint="ctx.checkpoint"></HTTPFirewallCheckpointRefererBlock>

						<!-- CC -->
						<HTTPFirewallCheckpointCC v-if="ctx.checkpoint.prefix == 'cc'" :v-checkpoint="ctx.checkpoint"></HTTPFirewallCheckpointCC>
					</td>
				</tr>
				</tbody>

				<!-- 选项 -->
				<tbody v-if="ctx.checkpoint != null && !ctx.checkpoint.isComposed && ctx.checkpoint.options != null && ctx.checkpoint.options.length > 0">
				<tr v-for="option in ctx.checkpoint.options">
					<td>{{ option.name }}</td>
					<td>
						<div class="ui fields inline" v-if="option.type == 'field'">
							<div class="ui field">
								<TInputText type="text" name="" :placeholder="option.placeholder" :maxlength="(option.maxLength > 0)?option.maxLength:1024" :size="option.size" v-model="option.value"/>
							</div>
							<div class="ui field">
								{{ option.rightLabel }}
							</div>
						</div>
						<div class="ui fields inline" v-if="option.type == 'options'">
							<div class="ui field">
								<TSelect :style="'width:' + option.size + 'em'" name="" v-model="option.value">
									<TOption v-for="opt in option.options" :value="opt.value">{{ opt.name }}</TOption>
								</TSelect>
							</div>
							<div class="ui field">
								{{ option.rightLabel }}
							</div>
						</div>
						<p class="comment" v-if="option.comment != null && option.comment.length > 0">{{ option.comment }}</p>
					</td>
				</tr>
				</tbody>

				<tbody v-show="ctx.checkpoint != null && !ctx.checkpoint.isComposed">
				<tr>
					<td>操作符 *</td>
					<td>
						<TSelect name="operator" v-model="ctx.rule.operator" @change="ctx.changeOperator()" filter>
							<TOption v-for="op in ctx.operators" :value="op.code">{{ op.name }}（{{ op.code }}）</TOption>
						</TSelect>
						<p class="comment" v-if="ctx.operator != null" v-html="ctx.operator.description"></p>
					</td>
				</tr>
				<tr v-show="ctx.operator != null && ctx.operator.dataType != 'none'">
					<td>
						<span v-if="ctx.operator != null && ctx.operator.dataType == 'regexp'">匹配正则表达式</span>
						<span v-else-if="ctx.operator != null && ctx.operator.dataType == 'wildcard'">匹配单个通配符</span>
						<span v-else-if="ctx.operator != null && ctx.operator.dataType == 'number'">对比数字</span>
						<span v-else-if="ctx.operator != null && ctx.operator.dataType == 'string'">对比单个字符串</span>
						<span v-else-if="ctx.operator != null && ctx.operator.dataType == 'strings'">对比一组字符串</span>
						<span v-else-if="ctx.operator != null && ctx.operator.dataType == 'string|number'">对比单个字符串或数字</span>
						<span v-else-if="ctx.operator != null && ctx.operator.dataType == 'version'">对比单个版本号</span>
						<span v-else-if="ctx.operator != null && ctx.operator.dataType == 'versionRange'">对比版本号范围</span>
						<span v-else-if="ctx.operator != null && ctx.operator.dataType == 'ip'">对比单个IP</span>
						<span v-else-if="ctx.operator != null && ctx.operator.dataType == 'ips'">一组对比IP</span>
						<span v-else>对比值</span>
					</td>
					<td>
						<!-- 二进制数据 -->
						<div v-if="ctx.rule.operator == 'contains binary'">
							<TTextarea rows="3" maxlength="4096" name="value" v-model="ctx.rule.value" class="w-full"></TTextarea>
							<p class="comment">将二进制进行Base64Encode后放在这里，比如
								<CodeLabel>Hello</CodeLabel>
								对应
								<CodeLabel>SGVsbG8=</CodeLabel>
								。
							</p>
						</div>
						<div v-else-if="ctx.rule.operator == 'not contains binary'">
							<TTextarea rows="3" maxlength="4096" name="value" v-model="ctx.rule.value" class="w-full"></TTextarea>
							<p class="comment">将二进制进行Base64Encode后放在这里，比如
								<CodeLabel>Hello</CodeLabel>
								对应
								<CodeLabel>SGVsbG8=</CodeLabel>
								。
							</p>
						</div>

						<!-- bool数据 -->
						<div v-else-if="ctx.checkpoint != null && ctx.checkpoint.dataType == 'bool'">
							<TSelect name="value" v-model="ctx.rule.value" @change="ctx.changeRuleValue">
								<TOption value="">[请选择]</TOption>
								<TOption value="1">是(1)</TOption>
								<TOption value="0">否(0)</TOption>
							</TSelect>
						</div>

						<!-- wildcard -->
						<div v-else-if="ctx.operator != null && ctx.operator.dataType == 'wildcard'">
							<TTextarea rows="3" maxlength="4096" name="value" v-model="ctx.rule.value" @input="ctx.changeRuleValue" class="w-full"></TTextarea>
							<p class="comment">输入包含通配符的字符串，比如
								<CodeLabel>Chrome/*</CodeLabel>
								、
								<CodeLabel>192.168.*.*</CodeLabel>
								。
							</p>
						</div>

						<!-- number -->
						<div v-else-if="ctx.operator != null && ctx.operator.dataType == 'number'">
							<TInputText type="number" name="value" v-model="ctx.rule.value" @input="ctx.changeRuleValue" style="width: 10em" maxlength="30" placeholder="对比数字" step="any"/>
							<p class="comment">输入和参数对比的数字，比如
								<CodeLabel>123</CodeLabel>
								、
								<CodeLabel>123.456</CodeLabel>
								。
							</p>
						</div>

						<!-- string|number -->
						<div v-else-if="ctx.operator != null && ctx.operator.dataType == 'string|number'">
							<TInputText type="text" name="value" v-model="ctx.rule.value" @input="ctx.changeRuleValue" style="width: 16em" maxlength="30" placeholder="对比字符串或数字"/>
							<p class="comment">输入和参数对比的字符串或数字，比如
								<CodeLabel>123</CodeLabel>
								、
								<CodeLabel>abc</CodeLabel>
								。
							</p>
						</div>

						<!-- version -->
						<div v-else-if="ctx.operator != null && ctx.operator.dataType == 'version'">
							<TInputText type="text" name="value" v-model="ctx.rule.value" @input="ctx.changeRuleValue" style="width: 10em" maxlength="100" class="w-full" placeholder="对比版本号"/>
							<p class="comment">输入和参数对比的版本号，比如
								<CodeLabel>1.2.7</CodeLabel>
								。
							</p>
						</div>

						<!-- versionRange -->
						<div v-else-if="ctx.operator != null && ctx.operator.dataType == 'versionRange'">
							<TInputText type="text" name="value" v-model="ctx.rule.value" @input="ctx.changeRuleValue" style="width: 10em" maxlength="100" class="w-full" placeholder="版本号范围"/>
							<p class="comment">输入和参数对比的版本号范围，比如
								<CodeLabel>1.2.7,1.3.7</CodeLabel>
								。
							</p>
						</div>

						<!-- IP -->
						<div v-else-if="ctx.operator != null && ctx.operator.dataType == 'ip'">
							<TInputText type="text" name="value" v-model="ctx.rule.value" @input="ctx.changeRuleValue" style="width: 16em" maxlength="100" class="w-full" placeholder="对比IP"/>
							<p class="comment">输入和参数对比的IP，比如
								<CodeLabel>192.168.2.100</CodeLabel>
								。
							</p>
						</div>

						<!-- 其余数据 -->
						<div v-else>
							<TTextarea rows="3" maxlength="4096" name="value" v-model="ctx.rule.value" @input="ctx.changeRuleValue" class="w-full"></TTextarea>
							<p class="comment" v-if="ctx.operator != null && ctx.operator.dataType == 'strings'">每行一个数据。</p>
							<p class="comment" v-if="ctx.operator != null && ctx.operator.dataType == 'regexp'">正则表达式中对于要匹配的内容中的特殊字符需要转义处理（即在字符前面加入反斜杠\），比如
								<CodeLabel>.?*+()[]{}^$\</CodeLabel>
								等符号要变成
								<CodeLabel>\.\?\*\+\(\)\[\]\{\}\^\$\\</CodeLabel>
								。
							</p>
						</div>
						<p class="comment" v-if="ctx.operator != null && ctx.operator.dataType == 'regexp' && ctx.rule.value.match(/\n/)">
							<span class="red">警告：发现你填写的正则表达式中包含了换行符，如果你的意图是每行都表示不同的选项，那么请使用竖杠（<CodeLabel>|</CodeLabel>）符号代替换行符，比如把<CodeLabel>a换行b换行c换行</CodeLabel>改成<CodeLabel>a|b|c</CodeLabel>，<a href="" @click.prevent="ctx.convertValueLine">[帮我转换]</a>。</span>
						</p>

						<!-- 特殊规则 -->
						<div style="margin-top: 1em">
							<!-- geo country name -->
							<div v-if="ctx.checkpoint != null && ctx.checkpoint.prefix == 'geoCountryName'">
								<ComboBox title="已添加" width="14em" data-url="/ui/countryOptions" data-key="countries" placeholder="点这里选择国家/地区" @change="ctx.selectGeoCountryName" ref="countryComboBox" key="combo-box-country"></ComboBox>
							</div>

							<!-- geo province name -->
							<div v-if="ctx.checkpoint != null && ctx.checkpoint.prefix == 'geoProvinceName'">
								<ComboBox title="已添加" data-url="/ui/provinceOptions" data-key="provinces" placeholder="点这里选择省份名称" @change="ctx.selectGeoProvinceName" ref="provinceComboBox" key="combo-box-province"></ComboBox>
							</div>

							<!-- geo city name -->
							<div v-if="ctx.checkpoint != null && ctx.checkpoint.prefix == 'geoCityName'">
								<ComboBox title="已添加" data-url="/ui/cityOptions" data-key="cities" placeholder="点这里选择城市名称" @change="ctx.selectGeoCityName" ref="cityComboBox" key="combo-box-city"></ComboBox>
							</div>

							<!-- ISP Name -->
							<div v-if="ctx.checkpoint != null && ctx.checkpoint.prefix == 'ispName'">
								<ComboBox title="已添加" data-url="/ui/providerOptions" data-key="providers" placeholder="点这里选择ISP名称" @change="ctx.selectISPName" ref="ispComboBox" key="combo-box-isp"></ComboBox>
							</div>
						</div>
					</td>
				</tr>
				<tr v-if="ctx.operator != null && ctx.operator.dataType == 'regexp'">
					<td>正则表达式测试</td>
					<td>
						<a href="" v-if="!ctx.regexpTestIsOn" @click.prevent="ctx.changeRegexpTestIsOn">[输入测试字符串]</a>
						<div v-if="ctx.regexpTestIsOn">
							<TTextarea placeholder="输入要测试的内容" rows="3" v-model="ctx.regexpTestBody" ref="regexpTestBody" @input="ctx.changeRegexpTestBody" class="w-full"></TTextarea>
							<p class="comment">
								<span v-if="ctx.regexpTestResult.isOk" class="green">{{ ctx.regexpTestResult.message }}</span>
								<span v-if="!ctx.regexpTestResult.isOk" class="red">{{ ctx.regexpTestResult.message }}</span>

								&nbsp; <a href="" @click.prevent="ctx.changeRegexpTestIsOn">[结束测试]</a>
							</p>
						</div>
					</td>
				</tr>
				<tr v-if="(ctx.checkpoint == null || ctx.checkpoint.dataType != 'bool') && ctx.operator != null && ctx.operator.case != 'none'">
					<td>不区分大小写</td>
					<td>
						<TCheckboxBinary name="case" value="1" v-model="ctx.rule.isCaseInsensitive" @change="ctx.changeCaseInsensitive"/>
						<p class="comment">开启后忽略英文字母大小写。</p>
					</td>
				</tr>

				<tr>
					<td colspan="2">
						<MoreOptionsIndicator></MoreOptionsIndicator>
					</td>
				</tr>

				<!-- 参数过滤器 -->
				<tr v-if="ctx.moreOptionsVisible && ctx.checkpoint != null && !ctx.checkpoint.isComposed">
					<td>编解码</td>
					<td>
						<HTTPFirewallParamFiltersBox :v-filters="ctx.rule.paramFilters"></HTTPFirewallParamFiltersBox>
					</td>
				</tr>
				<tr v-show="ctx.moreOptionsVisible">
					<td>备注</td>
					<td>
						<TInputText type="text" name="description" v-model="ctx.rule.description" class="w-full"/>
					</td>
				</tr>
				</tbody>
			</DefinitionTable>

			<SubmitButton></SubmitButton>
		</PostForm>
	</PopupLayout>
</template>

<style lang="postcss" scoped>

</style>