<script setup>

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

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

const requestHeaderInputRef = ref()
const variableInputRef = ref()
const {config, options} = (function () {
	let config = props.vRemoteAddrConfig
	if (config == null) {
		config = {
			isPrior: false,
			isOn: false,
			value: "${rawRemoteAddr}",
			type: "default",

			requestHeaderName: ""
		}
	}

	// type
	if (config.type == null || config.type.length == 0) {
		config.type = "default"
		switch (config.value) {
			case "${rawRemoteAddr}":
				config.type = "default"
				break
			case "${remoteAddrValue}":
				config.type = "default"
				break
			case "${remoteAddr}":
				config.type = "proxy"
				break
			default:
				if (config.value != null && config.value.length > 0) {
					config.type = "variable"
				}
		}
	}

	// value
	if (config.value == null || config.value.length == 0) {
		config.value = "${rawRemoteAddr}"
	}

	return {
		config: ref(config),
		options: ref([
			{
				name: "直接获取",
				description: "用户直接访问边缘节点，即 \"用户 --> 边缘节点\" 模式，这时候系统会试图从直接的连接中读取到客户端IP地址。",
				value: "${rawRemoteAddr}",
				type: "default"
			},
			{
				name: "从上级代理中获取",
				description: "用户和边缘节点之间有别的代理服务转发，即 \"用户 --> [第三方代理服务] --> 边缘节点\"，这时候只能从上级代理中获取传递的IP地址；上级代理传递的请求报头中必须包含 X-Forwarded-For 或 X-Real-IP 信息。",
				value: "${remoteAddr}",
				type: "proxy"
			},
			{
				name: "从请求报头中读取",
				description: "从自定义请求报头读取客户端IP。",
				value: "",
				type: "requestHeader"
			},
			{
				name: "[自定义变量]",
				description: "通过自定义变量来获取客户端真实的IP地址。",
				value: "",
				type: "variable"
			}
		])
	}
})()

const isOn = function () {
	return ((!props.vIsLocation && !props.vIsGroup) || config.value.isPrior) && config.value.isOn
}

const changeOptionType = function () {
	switch (config.value.type) {
		case "default":
			config.value.value = "${rawRemoteAddr}"
			break
		case "proxy":
			config.value.value = "${remoteAddr}"
			break
		case "requestHeader":
			config.value.value = ""
			if (config.value.requestHeaderName != null && config.value.requestHeaderName.length > 0) {
				config.value.value = "${header." + config.value.requestHeaderName + "}"
			}

			setTimeout(function () {
				requestHeaderInputRef.value.focus()
			})
			break
		case "variable":
			config.value.value = "${rawRemoteAddr}"

			setTimeout(function () {
				variableInputRef.value.focus()
			})

			break
	}
}

watch(() => config.value.requestHeaderName, function (value) {
	if (config.value.type == "requestHeader") {
		config.value.value = "${header." + value.trim() + "}"
	}
})


</script>

<template>
	<div>
		<input type="hidden" name="remoteAddrJSON" :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">启用访客IP设置</td>
				<td>
					<TCheckboxBinary value="1" v-model="config.isOn"/>
					<p class="comment">选中后，表示使用自定义的请求变量获取客户端IP。</p>
				</td>
			</tr>
			</tbody>
			<tbody v-show="isOn()">
			<tr>
				<td>获取IP方式 *</td>
				<td>
					<TSelect v-model="config.type" @change="changeOptionType">
						<TOption v-for="option in options" :value="option.type">{{ option.name }}</TOption>
					</TSelect>
					<template v-for="option in options">
						<p class="comment" v-if="option.type == config.type && option.description.length > 0">{{ option.description }}</p>
					</template>
				</td>
			</tr>

			<!-- read from request header -->
			<tr v-show="config.type == 'requestHeader'">
				<td>请求报头 *</td>
				<td>
					<TInputText type="text" name="requestHeaderName" v-model="config.requestHeaderName" maxlength="100" ref="requestHeaderInputRef" class="w-full"/>
					<p class="comment">请输入包含有客户端IP的请求报头，需要注意大小写，常见的有
						<CodeLabel>X-Forwarded-For</CodeLabel>
						、
						<CodeLabel>X-Real-IP</CodeLabel>
						、
						<CodeLabel>X-Client-IP</CodeLabel>
						等。
					</p>
				</td>
			</tr>

			<!-- read from variable -->
			<tr v-show="config.type == 'variable'">
				<td>读取IP变量值 *</td>
				<td>
					<TInputText type="text" name="value" v-model="config.value" maxlength="100" ref="variableInputRef" class="w-full"/>
					<p class="comment">通过此变量获取用户的IP地址。具体可用的请求变量列表可参考官方网站文档；比如通过报头传递IP的情形，可以使用
						<CodeLabel>${header.你的自定义报头}</CodeLabel>
						（类似于
						<CodeLabel>${header.X-Forwarded-For}</CodeLabel>
						，需要注意大小写规范）。
					</p>
				</td>
			</tr>
			</tbody>
		</DefinitionTable>
	</div>
</template>

<style scoped>
</style>
