<script setup>

import {ref, watch} from "vue"
import TCheckboxBinary from "@/components/ui/TCheckboxBinary.vue";
import PriorCheckbox from "@/components/common/PriorCheckbox.vue";
import MoreOptionsIndicator from "@/components/common/MoreOptionsIndicator.vue";
import TInputText from "@/components/ui/TInputText.vue";
import TInputGroup from "@/components/ui/TInputGroup.vue";
import TInputGroupAddon from "@/components/ui/TInputGroupAddon.vue";
import URLPatternsBox from "@/components/common/URLPatternsBox.vue";
import DefinitionTable from "@/components/common/DefinitionTable.vue";
import TSelect from "@/components/ui/TSelect.vue";
import TOption from "@/components/ui/TOption.vue";

const props = defineProps(["v-cc-config", "v-is-location", "v-is-group", "defaultThresholds"])

const maxRequestsStringAtThresholdIndex = function (config, index) {
	if (config.thresholds == null) {
		return ""
	}
	if (index < config.thresholds.length) {
		let s = config.thresholds[index].maxRequests.toString()
		if (s == "0") {
			s = ""
		}
		return s
	}
	return ""
}

const {
	config,
	moreOptionsVisible,
	minQPSPerIP,
	useCustomThresholds,
	thresholdMaxRequests0,
	thresholdMaxRequests1,
	thresholdMaxRequests2
} = (function () {
	let config = props.vCcConfig
	if (config == null) {
		config = {
			isPrior: false,
			isOn: false,
			enableFingerprint: true,
			enableGET302: true,
			onlyURLPatterns: [],
			exceptURLPatterns: [],
			useDefaultThresholds: true,
			ignoreCommonFiles: true,
			thresholdMethod: "default",
			level: "low"
		}
	}

	if (config.thresholds == null || config.thresholds.length == 0) {
		config.thresholds = [
			{
				maxRequests: 0
			},
			{
				maxRequests: 0
			},
			{
				maxRequests: 0
			}
		]
	}

	if (typeof config.enableFingerprint != "boolean") {
		config.enableFingerprint = true
	}
	if (typeof config.enableGET302 != "boolean") {
		config.enableGET302 = true
	}

	if (config.onlyURLPatterns == null) {
		config.onlyURLPatterns = []
	}
	if (config.exceptURLPatterns == null) {
		config.exceptURLPatterns = []
	}

	// threshold method
	if (!config.thresholdMethod) {
		if (!config.useDefaultThresholds) {
			config.thresholdMethod = "custom"
		} else {
			config.thresholdMethod = "auto"
		}
	}

	// level
	if (!config.level) {
		config.level = "low"
	}

	return {
		config: ref(config),
		moreOptionsVisible: ref(false),
		minQPSPerIP: ref(config.minQPSPerIP),
		useCustomThresholds: ref(!config.useDefaultThresholds),

		thresholdMaxRequests0: ref(maxRequestsStringAtThresholdIndex(config, 0)),
		thresholdMaxRequests1: ref(maxRequestsStringAtThresholdIndex(config, 1)),
		thresholdMaxRequests2: ref(maxRequestsStringAtThresholdIndex(config, 2))
	}
})()

const setThresholdMaxRequests = function (index, v) {
	let maxRequests = parseInt(v)
	if (isNaN(maxRequests) || maxRequests < 0) {
		maxRequests = 0
	}
	if (index < config.value.thresholds.length) {
		config.value.thresholds[index].maxRequests = maxRequests
	}
}

const showMoreOptions = function () {
	moreOptionsVisible.value = !moreOptionsVisible.value
}

watch(minQPSPerIP, function (v) {
	let qps = parseInt(v.toString())
	if (isNaN(qps) || qps < 0) {
		qps = 0
	}
	config.value.minQPSPerIP = qps
})

watch(thresholdMaxRequests0, function (v) {
	setThresholdMaxRequests(0, v)
})

watch(thresholdMaxRequests1, function (v) {
	setThresholdMaxRequests(1, v)
})

watch(thresholdMaxRequests2, function (v) {
	setThresholdMaxRequests(2, v)
})

watch(useCustomThresholds, function (b) {
	config.value.useDefaultThresholds = !b
})

</script>

<template>
	<div>
		<input type="hidden" name="ccJSON" :value="JSON.stringify(config)"/>
		<DefinitionTable>
			<PriorCheckbox :v-config="config" v-if="vIsLocation || vIsGroup"></PriorCheckbox>
			<tbody v-show="((!vIsLocation && !vIsGroup) || config.isPrior)">
			<tr>
				<td class="title">启用CC无感防护</td>
				<td>
					<TCheckboxBinary v-model="config.isOn">{{ config.isOn ? '开启' : '关闭' }}</TCheckboxBinary>
					<p class="comment">
						启用后，自动检测并拦截CC攻击。
					</p>
				</td>
			</tr>
			<tr v-show="config.isOn">
				<td>阈值设置</td>
				<td>
					<TSelect v-model="config.thresholdMethod" style="width: 118px">
						<TOption value="default">默认</TOption>
						<TOption value="auto">自动</TOption>
						<TOption value="custom">自定义</TOption>
					</TSelect>
					<p class="comment" v-if="config.thresholdMethod == 'default'">
						使用系统默认的阈值设置。
						<span v-if="defaultThresholds && defaultThresholds.length > 0">
							当前系统默认阈值设置：单IP<span v-for="(threshold, index) in defaultThresholds">
								每 {{ threshold.periodSeconds }} 秒 最多 {{ threshold.maxRequests }} 请求<span v-if="index < defaultThresholds.length - 1">；</span>
							</span>。
						</span>
					</p>
					<p class="comment" v-if="config.thresholdMethod == 'auto'">系统根据网站访问量自动动态设置阈值。</p>
					<p class="comment" v-if="config.thresholdMethod == 'custom'">手动自定义阈值。</p>
				</td>
			</tr>
			<tr v-show="config.isOn && config.thresholdMethod == 'custom'">
				<td class="color-border">自定义拦截阈值设置</td>
				<td>
					<div>
						<TInputGroup>
							<TInputGroupAddon>
								<span>单IP每5秒最多</span>
							</TInputGroupAddon>
							<TInputText type="text" style="width: 6em" maxlength="6" v-model="thresholdMaxRequests0"/>
							<TInputGroupAddon>
								<span>请求</span>
							</TInputGroupAddon>
						</TInputGroup>
					</div>

					<div style="margin-top: 1em">
						<TInputGroup>
							<TInputGroupAddon>
								<span>单IP每60秒最多</span>
							</TInputGroupAddon>
							<TInputText type="text" style="width: 6em" maxlength="6" v-model="thresholdMaxRequests1"/>
							<TInputGroupAddon>
								<span>请求</span>
							</TInputGroupAddon>
						</TInputGroup>
					</div>
					<div style="margin-top: 1em">
						<TInputGroup>
							<TInputGroupAddon>
								<span>单IP每300秒最多</span>
							</TInputGroupAddon>
							<TInputText type="text" style="width: 6em" maxlength="6" v-model="thresholdMaxRequests2"/>
							<TInputGroupAddon>
								<span>请求</span>
							</TInputGroupAddon>
						</TInputGroup>
					</div>
				</td>
			</tr>
			<tr v-show="config.isOn">
				<td>拦截强度</td>
				<td>
					<TSelect v-model="config.level" style="width: 118px">
						<TOption value="low">低</TOption>
						<TOption value="middle">中</TOption>
						<TOption value="high">高</TOption>
					</TSelect>
					<p class="comment">级别越高<span v-if="config.thresholdMethod == 'auto'">，CC检测越灵敏</span>，被拦截的IP封禁时间<span v-if="config.thresholdMethod == 'auto'">也会</span>越长。
					</p>
				</td>
			</tr>
			</tbody>
			<tbody v-show="config.isOn">
			<tr>
				<td colspan="2" style="height: 30px; padding-top: 4px; padding-bottom: 4px;">
					<MoreOptionsIndicator @change="showMoreOptions"></MoreOptionsIndicator>
				</td>
			</tr>
			</tbody>
			<tbody v-show="moreOptionsVisible && config.isOn">
			<tr>
				<td>例外URL</td>
				<td>
					<URLPatternsBox v-model="config.exceptURLPatterns"></URLPatternsBox>
					<p class="comment">如果填写了例外URL，表示这些URL跳过CC防护不做处理。</p>
				</td>
			</tr>
			<tr>
				<td>限制URL</td>
				<td>
					<URLPatternsBox v-model="config.onlyURLPatterns"></URLPatternsBox>
					<p class="comment">如果填写了限制URL，表示只对这些URL进行CC防护处理；如果不填则表示支持所有的URL。</p>
				</td>
			</tr>
			<tr>
				<td>忽略常用文件</td>
				<td>
					<TCheckboxBinary v-model="config.ignoreCommonFiles">{{ config.ignoreCommonFiles ? '忽略' : '不忽略' }}</TCheckboxBinary>
					<p class="comment">忽略js、css、jpg等常在网页里被引用的文件名，即对这些文件的访问不加入计数，可以减少误判几率。但如果单独访问这些文件，比如在浏览器里直接打开，也会加入计数。</p>
				</td>
			</tr>
			<tr>
				<td>检查请求来源指纹</td>
				<td>
					<TCheckboxBinary v-model="config.enableFingerprint">{{ config.enableFingerprint ? '开启' : '关闭' }}</TCheckboxBinary>
					<p class="comment">在接收到HTTPS请求时尝试检查请求来源的指纹，用来检测代理服务和爬虫攻击；如果你在网站前面放置了别的反向代理服务，请取消此选项。</p>
				</td>
			</tr>
			<tr>
				<td>启用GET302校验</td>
				<td>
					<TCheckboxBinary v-model="config.enableGET302">{{ config.enableGET302 ? '开启' : '关闭' }}</TCheckboxBinary>
					<p class="comment">选中后，表示自动通过GET302方法来校验客户端。</p>
				</td>
			</tr>
			<tr>
				<td>单IP最低QPS</td>
				<td>
					<TInputGroup>
						<TInputText type="text" name="minQPSPerIP" maxlength="6" style="width: 118px" v-model="minQPSPerIP"/>
						<TInputGroupAddon>
							<span>请求数/秒</span>
						</TInputGroupAddon>
					</TInputGroup>
					<p class="comment">当某个IP在1分钟内平均QPS达到此值时，才会开始检测；如果设置为0，表示任何访问都会检测。（注意这里设置的是检测开启阈值，不是拦截阈值，拦截阈值请选择表单上方的“阈值设置“--“自定义”）</p>
				</td>
			</tr>
			</tbody>
		</DefinitionTable>
	</div>
</template>

<style scoped>
.comment {
	margin-bottom: 0;
	color: rgba(101, 112, 128, 1);
	font-weight: 400;
	font-size: 14px;
	line-height: 14px;
    font-family: Source Han Sans SC;
}
:deep(.p-inputgroupaddon) {
	color: rgba(101, 112, 128, 1);
	font-weight: 400;
	font-size: 12px;
	line-height: 14px;
}
</style>
