<script setup>

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

const props = defineProps(["v-reverse-proxy-ref", "v-reverse-proxy-config", "v-is-location", "v-is-group", "v-family"])

const {reverseProxyRef, reverseProxyConfig, advancedVisible, family, forwardHeaders} = (function () {
	let reverseProxyRef = props.vReverseProxyRef
	if (reverseProxyRef == null) {
		reverseProxyRef = {
			isPrior: false,
			isOn: false,
			reverseProxyId: 0
		}
	}

	let reverseProxyConfig = props.vReverseProxyConfig
	if (reverseProxyConfig == null) {
		reverseProxyConfig = {
			requestPath: "",
			stripPrefix: "",
			requestURI: "",
			requestHost: "",
			requestHostType: 0,
			requestHostExcludingPort: false,
			addHeaders: [],
			connTimeout: {count: 0, unit: "second"},
			readTimeout: {count: 0, unit: "second"},
			idleTimeout: {count: 0, unit: "second"},
			maxConns: 0,
			maxIdleConns: 0,
			followRedirects: false,
			retry50X: false,
			retry40X: false
		}
	}
	if (reverseProxyConfig.addHeaders == null) {
		reverseProxyConfig.addHeaders = []
	}
	if (reverseProxyConfig.connTimeout == null) {
		reverseProxyConfig.connTimeout = {count: 0, unit: "second"}
	}
	if (reverseProxyConfig.readTimeout == null) {
		reverseProxyConfig.readTimeout = {count: 0, unit: "second"}
	}
	if (reverseProxyConfig.idleTimeout == null) {
		reverseProxyConfig.idleTimeout = {count: 0, unit: "second"}
	}

	if (reverseProxyConfig.proxyProtocol == null) {
		reverseProxyConfig.proxyProtocol = {
			isOn: false,
			version: 1
		}
	}

	let forwardHeaders = [
		{
			name: "X-Real-IP",
			isChecked: false
		},
		{
			name: "X-Forwarded-For",
			isChecked: false
		},
		{
			name: "X-Forwarded-By",
			isChecked: false
		},
		{
			name: "X-Forwarded-Host",
			isChecked: false
		},
		{
			name: "X-Forwarded-Proto",
			isChecked: false
		}
	]
	forwardHeaders.forEach(function (v) {
		v.isChecked = reverseProxyConfig.addHeaders.$contains(v.name)
	})

	return {
		reverseProxyRef: ref(reverseProxyRef),
		reverseProxyConfig: ref(reverseProxyConfig),
		advancedVisible: ref(false),
		family: ref(props.vFamily),
		forwardHeaders: ref(forwardHeaders)
	}
})()

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

const changeAdvancedVisible = function (v) {
	advancedVisible.value = v
}

const changeAddHeader = function () {
	reverseProxyConfig.value.addHeaders = forwardHeaders.value.filter(function (v) {
		return v.isChecked
	}).map(function (v) {
		return v.name
	})
}

watch(() => reverseProxyConfig.value.requestHostType, function (v) {
	let requestHostType = parseInt(v)
	if (isNaN(requestHostType)) {
		requestHostType = 0
	}
	reverseProxyConfig.value.requestHostType = requestHostType
})

watch(() => reverseProxyConfig.value.proxyProtocol.version, function (v) {
	let version = parseInt(v)
	if (isNaN(version)) {
		version = 1
	}
	reverseProxyConfig.value.proxyProtocol.version = version
})


</script>

<template>
	<div>
		<input type="hidden" name="reverseProxyRefJSON" :value="JSON.stringify(reverseProxyRef)"/>
		<input type="hidden" name="reverseProxyJSON" :value="JSON.stringify(reverseProxyConfig)"/>
		<DefinitionTable>
			<PriorCheckbox :v-config="reverseProxyRef" v-if="vIsLocation || vIsGroup"></PriorCheckbox>
			<tbody v-show="(!vIsLocation && !vIsGroup) || reverseProxyRef.isPrior">
			<tr>
				<td class="title">启用源站</td>
				<td>
					<TCheckboxBinary v-model="reverseProxyRef.isOn"/>
					<p class="comment">选中后，所有源站设置才会生效。</p>
				</td>
			</tr>
			<tr v-show="family == null || family == 'http'">
				<td>回源主机名<em>（Host）</em></td>
				<td>
					<TRadio :value="0" v-model="reverseProxyConfig.requestHostType">跟随CDN域名</TRadio> &nbsp;
					<TRadio :value="1" v-model="reverseProxyConfig.requestHostType">跟随源站</TRadio> &nbsp;
					<TRadio :value="2" v-model="reverseProxyConfig.requestHostType">自定义</TRadio>
					<div v-show="reverseProxyConfig.requestHostType == 2" style="margin-top: 0.8em">
						<TInputText type="text" placeholder="比如example.com" v-model="reverseProxyConfig.requestHost" class="w-full"/>
					</div>
					<p class="comment">请求源站时的主机名（Host），用于修改源站接收到的域名
						<span v-if="reverseProxyConfig.requestHostType == 0">，"跟随CDN域名"是指源站接收到的域名和当前CDN访问域名保持一致</span>
						<span v-if="reverseProxyConfig.requestHostType == 1">，"跟随源站"是指源站接收到的域名仍然是填写的源站地址中的信息，不随代理服务域名改变而改变</span>
						<span v-if="reverseProxyConfig.requestHostType == 2">，自定义Host内容中支持请求变量</span>。</p>
				</td>
			</tr>
			<tr v-show="family == null || family == 'http'">
				<td>回源主机名移除端口</td>
				<td>
					<TCheckboxBinary v-model="reverseProxyConfig.requestHostExcludingPort"></TCheckboxBinary>
					<p class="comment">选中后表示移除回源主机名中的端口部分。</p>
				</td>
			</tr>
			</tbody>
			<MoreOptionsTbody @change="changeAdvancedVisible" v-if="isOn()"></MoreOptionsTbody>
			<tbody v-show="isOn() && advancedVisible">
			<tr v-show="family == null || family == 'http'">
				<td>回源跟随</td>
				<td>
					<TCheckboxBinary v-model="reverseProxyConfig.followRedirects"></TCheckboxBinary>
					<p class="comment">选中后，自动读取源站跳转后的网页内容。</p>
				</td>
			</tr>
			<tr v-show="family == null || family == 'http'">
				<td>自动添加报头</td>
				<td>
					<div>
						<div style="width: 14em; float: left; margin-bottom: 1em" v-for="header in forwardHeaders" :key="header.name">
							<TCheckboxBinary v-model="header.isChecked" @input="changeAddHeader">{{ header.name }}</TCheckboxBinary>
						</div>
						<div style="clear: both"></div>
					</div>
					<p class="comment">选中后，会自动向源站请求添加这些报头，以便于源站获取客户端信息。</p>
				</td>
			</tr>
			<tr v-show="family == null || family == 'http'">
				<td>请求URI<em>（RequestURI）</em></td>
				<td>
					<TInputText type="text" placeholder="${requestURI}" v-model="reverseProxyConfig.requestURI" class="w-full"/>
					<p class="comment">${requestURI}为完整的请求URI，可以使用类似于"${requestURI}?arg1=value1&arg2=value2"的形式添加你的参数。</p>
				</td>
			</tr>
			<tr v-show="family == null || family == 'http'">
				<td>去除URL前缀<em>（StripPrefix）</em></td>
				<td>
					<TInputText type="text" v-model="reverseProxyConfig.stripPrefix" placeholder="/PREFIX" class="w-full"/>
					<p class="comment">可以把请求的路径部分前缀去除后再查找文件，比如把
						<CodeLabel>/web/app/index.html</CodeLabel>
						去除前缀
						<CodeLabel>/web</CodeLabel>
						后就变成
						<CodeLabel>/app/index.html</CodeLabel>
						。
					</p>
				</td>
			</tr>
			<tr v-if="family == null || family == 'http'">
				<td>自动刷新缓存区<em>（AutoFlush）</em></td>
				<td>
					<TCheckboxBinary v-model="reverseProxyConfig.autoFlush"/>
					<p class="comment">开启后将自动刷新缓冲区数据到客户端，在类似于SSE（server-sent events）等场景下很有用。</p>
				</td>
			</tr>
			<tr v-show="family == null || family == 'http'">
				<td>自动重试50X</td>
				<td>
					<TCheckboxBinary v-model="reverseProxyConfig.retry50X"></TCheckboxBinary>
					<p class="comment">选中后，表示当源站返回状态码为50X（比如502、504等）时，自动重试其他源站。</p>
				</td>
			</tr>
			<tr v-show="family == null || family == 'http'">
				<td>自动重试40X</td>
				<td>
					<TCheckboxBinary v-model="reverseProxyConfig.retry40X"></TCheckboxBinary>
					<p class="comment">选中后，表示当源站返回状态码为40X（403或404）时，自动重试其他源站。</p>
				</td>
			</tr>
			<tr v-show="family != 'unix'">
				<td>PROXY Protocol</td>
				<td>
					<TCheckboxBinary name="proxyProtocolIsOn" v-model="reverseProxyConfig.proxyProtocol.isOn"></TCheckboxBinary>
					<p class="comment">选中后表示启用PROXY Protocol，每次连接源站时都会在头部写入客户端地址信息。</p>
				</td>
			</tr>
			<tr v-show="family != 'unix' && reverseProxyConfig.proxyProtocol.isOn">
				<td>PROXY Protocol版本</td>
				<td>
					<TSelect name="proxyProtocolVersion" v-model="reverseProxyConfig.proxyProtocol.version">
						<TOption value="1">1</TOption>
						<TOption value="2">2</TOption>
					</TSelect>
					<p class="comment" v-if="reverseProxyConfig.proxyProtocol.version == 1">发送类似于
						<CodeLabel>PROXY TCP4 192.168.1.1 192.168.1.10 32567 443</CodeLabel>
						的头部信息。
					</p>
					<p class="comment" v-if="reverseProxyConfig.proxyProtocol.version == 2">发送二进制格式的头部信息。</p>
				</td>
			</tr>
			</tbody>
		</DefinitionTable>
	</div>
</template>

<style scoped>
</style>
