dnsConfigure() {
	if [ "$deny_ad" = '1' ]; then
		hostsObj='
		"hosts": {
			"geosite:category-ads-all": "127.0.0.2"
		}, '
	fi
	if [ -n "$cnNodes" ]; then
		result="{$hostsObj"'
		"servers": [{
			"address": "'$globalDNS'",
			"port": 53,
			"domains": ["geosite:google-cn"]
		}, {
			"address": "'$cnDNS'",
			"port": '53',
			"domains": ["geosite:cn" , "domain:ikandy.fun", "full:cn.ipcelou.com"]
		}],
		"tag": "resolve"
	}'
	else
		result="{$hostsObj"'
		"servers": [{
			"address": "'$globalDNS'",
			"port": 53
		}],
		"tag": "resolve"
	}'
	fi
}

inConfigure() {
	[ "$deny_ad" = '1' -o -n "$cnNodes" ] && sniffingOpt='true' || sniffingOpt='false'
	result='{
		"tag": "socks-in",
		"port": 10800,
		"protocol": "socks",
		"settings": {
			"network": "tcp,udp",
			"udp": true
		},
		"sniffing": {
			"enabled": '$sniffingOpt',
			"destOverride": ["http","tls"]
		}
	}'
}

vnextConfigure() {
	unset result
	for ip in ${add}; do
		if [ -n "$result" ]; then
			result="${result}, "
		fi
		result="$result"'{
				"address": "'$ip'",
				"port": '$port',
				"users": [{
					"id": "'$id'",
					"alterId": '${aid:-0}',
					"security": "auto",
					"flow": "'$flow'",
					"encryption": "none"
				}]
			}'
	done
}

vnexStreamSettingsConfigure() {
	if [ "$tls" = 'xtls' ] || [ "$protocol" = 'vless' -a "$security" = 'xtls' ]; then
		tlsSettings='xtlsSettings'
		security='xtls'
	elif [ "$tls" = 'tls' -o "$security" = 'tls' ]; then
		tlsSettings='tlsSettings'
		security='tls'
	else
		security='none'
		tlsSettings='tlsSettings'
	fi
	if echo "${net}${type}" | grep -qi 'ws'; then
		result='{
			"sockopt": {
				"tcpFastOpen": '${tfoOpt:-false}',
				"tcpKeepAliveInterval": 15
			},
			"network": "ws",
			"wsSettings": {
				"path": "'${path:-/}'",
				"headers": {
					"Host": "'${host:-add}'"
				}
			},
			"security": "'$security'",
			"'$tlsSettings'": {
				"allowInsecure": true,
				"serverName": "'${sni:-$host}'"
			}
		}'
	elif echo "${net}${type}" | grep -qi 'kcp'; then
		result='{
			"network": "mkcp",
			"kcpSettings": {
				"header": {
					"type": "'${headertype:-none}'"
				}
			},
			"security": "'$security'",
			"'$tlsSettings'": {
				"allowInsecure": true,
				"serverName": "'${sni:-$host}'"
			}
		}'
	else
		result='{
			"sockopt": {
				"tcpFastOpen": '${tfoOpt:-false}',
				"tcpKeepAliveInterval": 15
			},
			"network": "tcp",
			"security": "'$security'",
			"'$tlsSettings'": {
				"allowInsecure": true,
				"serverName": "'${sni:-$host}'"
			}'
			if [ "$type" = 'http' ]; then
				result="$result"',
			"tcpSettings": {
				"header": {
					"type": "'$type'",
					"request": {
						"version": "1.1",
						"method": "GET",
						"path": ["'${path:-/}'"],
						"headers": {
							"Host": ["'${host:-$add}'"],
							"Connection": ["keep-alive"],
							"Accept-Encoding": ["gzip, deflate"],
							"Pragma": ["no-cache"],
							"User-Agent": ["QQBrowser"]
						}
					}
				}
			}'
		fi
		result="$result"'
		}'
	fi
}

outConfigure() {
	tag="$1"
	file="$2"
	unset mux
	. "${file}"
	[ "$mux" != 'true' ] && mux=false || mux=true
	if [ "$protocol" = 'freedom' ]; then
		result='{
		"protocol": "'$protocol'",
		"tag": "'$tag'"
	}'
	else
		vnextConfigure
		vnextObj="$result"
		vnexStreamSettingsConfigure
		vnexStreamSettingsObj="$result"
		result='{
		"protocol": "'$protocol'",
		"tag": "'$tag'",
		"settings": {
			"vnext": ['"$vnextObj"']
		},
		"mux": {
			"enabled": '$mux',
			"concurrency": 64
		},
		"streamSettings": '"$vnexStreamSettingsObj"'
	}'
	fi
}

routeRulesConfigure() {
	if [ "$deny_ad" = '1' ]; then
	ad_rule='{
			"type": "field",
			"inboundTag": ["socks-in"],
			"domain": ["geosite:category-ads-all"],
			"outboundTag": "denyNetwork"
		}'
	fi
	if [ -n "$cnNodes" ]; then
		cn_rule='{
			"type": "field",
			"inboundTag": ["resolve"],
			"ip": ["'$cnDNS'"],
			"balancerTag": "cn-balancers"
		}, {
			"type": "field",
			"inboundTag": ["resolve"],
			"ip": ["'$globalDNS'"],
			"balancerTag": "global-balancers"
		}, {
			"type": "field",
			"inboundTag": ["socks-in"],
			"domain": ["geosite:google-cn", "full:cn.ipcelou.com"],
			"balancerTag": "global-balancers"
		}, {
			"type": "field",
			"inboundTag": ["socks-in"],
			"ip": ["geoip:cn"],
			"balancerTag": "cn-balancers"
		}, {
			"type": "field",
			"inboundTag": ["socks-in"],
			"domain": ["geosite:cn", "domain:ikandy.fun"],
			"balancerTag": "cn-balancers"
		}'
	fi
	result='{
			"type": "field",
			"inboundTag": ["socks-in"],
			"port": "53,5353",
			"outboundTag": "dns-out"
		}'
	[ -n "$ad_rule" ] && result="${result}, ${ad_rule}"
	[ -n "$cn_rule" ] && result="${result}, ${cn_rule}"
	result="${result}"', {
			"type": "field",
			"inboundTag": ["socks-in"],
			"balancerTag": "global-balancers"
		}'
}

routeBalancersConfigure() {
	if [ "$observatoryOpt" -le '3' -a "$observatoryOpt" -ge '1' ]; then
		strategyType="leastPing"
	else
		strategyType="random"
	fi
	if [ -n "$cnNodes" ]; then
		result='{
			"tag": "global-balancers",
			"selector": ["global-out"],
			"strategy": {
				"type": "'$strategyType'"
			}
		}, {
			"tag": "cn-balancers",
			"selector": ["cn-out"],
			"strategy": {
				"type": "'$strategyType'"
			}
		}'
	else
		result='{
			"tag": "global-balancers",
			"selector": ["global-out"],
			"strategy": {
				"type": "'$strategyType'"
			}
		}'
	fi
}

observatoryConfigure() {
	if [ "$observatoryOpt" = '1' ]; then
		result='
		"subjectSelector": ["global-out", "cn-out"],
		"probeURL": "http://www.google.com/generate_204",
		"probeInterval": "'${probeInterval:-30}'s"
	'
	elif [ "$observatoryOpt" = '2' ]; then
		result='
		"subjectSelector": ["global-out", "cn-out"],
		"probeURL": "http://connect.rom.miui.com/generate_204",
		"probeInterval": "'${probeInterval:-30}'s"
	'
	else
		result=''
	fi
}

domainToIPs() {
	./downloadCore.sh "$mlHost" 'MLBox' 'Usage'  #下载MLBox
	if echo "$add" | grep -v ':' |grep -q '[a-zA-Z]'; then
		dnsRetry=0
		unset ips
		while [ "${dnsRetry}" != '3' ]; do
			if [ -z "$ipVersion" ]; then
				echo "正在解析域名: $add"
				ips="`../Core/MLBox -dns=${add} -timeout=10`"
				ips=`echo "$ips" | grep -v '()' | grep -E "[1-9][0-9]{0,2}(\.[0-9]{1,3}){3}|:"`
			elif [ "$ipVersion" = 'ipv4' ]; then
				ips="`../Core/MLBox -dns="-domain=${add} -qtype=A" -timeout=10`"
				ips=`echo "$ips" | grep -v '()' | grep -E "[1-9][0-9]{0,2}(\.[0-9]{1,3}){3}"`
			elif [ "$ipVersion" = 'ips' ]; then
				ips="`../Core/MLBox -dns="-domain=${add} -qtype=AAAA" -timeout=10`"
				ips=`echo "$ips" | grep -v '()' | grep ':'`
			fi
			[ -n "$ips" ] && {
				echo "域名解析结果[$add]: [${ips//$ln/,}]"
				break
			}
			dnsRetry=$((dnsRetry+1))
			#做多解析3次
			[ "$dnsRetry" != '3' ] && echo "第$dnsRetry次重试解析域名: $add"
		done
		#解析失败则跳过
		if [ -z "$ips" ]; then
			echo "域名解析失败: [$add]"
		fi
	else
		ips=$add
	fi
	for ip in $ips; do
		echo "$ip $add" >>domainRecords.txt
	done

}

initNodeFile() {
	unset globalNodes
	unset cnNodes
	rm -rf '海内节点' '全局节点' 'domainRecords.txt'
	mkdir '海内节点' '全局节点'
	i=0
	ln='
'
	[ -z "$(ls ../全局节点/*.ini 2>/dev/null)" -a -z "$(ls ../海内节点/*.ini 2>/dev/null)" ] && exec echo '无可用节点，请把需要启动的节点文件放到 全局节点 或 海内节点 文件夹再启动'
	if [ -n "$(ls ../全局节点/*.ini 2>/dev/null)" ]; then
		for file in ../全局节点/*.ini; do
			. "$file"
			[ "$add" = 'www.quick-connect.top' ] && exec echo "请删除 节点列表 里的 模板文件 再启动"
			domainToIPs
			#IP无效则跳过
			if [ -z "$ips" ] || echo "$ips" | grep -Eq '^127\.|^::1$|^\[::1\]$'; then
				continue
			fi
			globalNodes="$globalNodes ${file##*/}"
			ini=`cat "$file"`
			cat >"全局节点/${file##*/}" <<-EOF
			${ini/add=\'$add\'/add=\'$ips\'}
			EOF
			i=$((i + 1))
		done
	fi
	if [ -n "$(ls ../海内节点/*.ini 2>/dev/null)" ]; then
		for file in ../海内节点/*.ini; do
			. "$file"
			[ "$add" = 'www.quick-connect.top' ] && exec echo "请删除 节点列表 里的 模板文件 再启动"
			domainToIPs
			#IP无效则跳过
			if [ -z "$ips" ] || echo "$ips" | grep -Eq '^127\.|^::1$|^\[::1\]$'; then
				continue
			fi
			cnNodes="$cnNodes ${file##*/}"
			ini=`cat "$file"`
			cat >"海内节点/${file##*/}" <<-EOF
			${ini/add=\'$add\'/add=\'$ips\'}
			EOF
			i=$((i + 1))
		done
	fi
	if [ -z "$globalNodes" ]; then
		if [ -z "$cnNodes" ]; then
			exec echo '无可用节点，请把需要启动的节点文件放到 全局节点 或 海内节点 文件夹再启动'
		fi
		rm -rf '全局节点'
		mv -f '海内节点' '全局节点'
		globalNodes="$cnNodes"
		unset cnNodes
		[ -n "$cnDNS" ] && globalDNS="$cnDNS"
	fi
}

initNodeFile
dnsConfigure
dnsObj="$result"
inConfigure
inObj="$result"
globalSub=0
for confFile in ${globalNodes}; do
	outConfigure "global-out${globalSub}" "全局节点/${confFile}"
	if [ "$globalSub" = '0' ]; then
		outObj="$result"
	else
		outObj="$outObj, $result"
	fi
	globalSub=$((globalSub+1))
done
cnSub=0
for confFile in ${cnNodes}; do
	outConfigure "cn-out${cnSub}" "海内节点/${confFile}"
	outObj="$outObj, $result"
	cnSub=$((cnSub+1))
done
routeRulesConfigure
routeRulesObj="$result"
routeBalancersConfigure
routeBalancersObj="$result"
observatoryConfigure
observatoryObj="$result"

cat >v2ray.json <<EOF
{
	"log": {
		"loglevel": "none"
	},
	"dns": ${dnsObj},
	"inbounds": [${inObj}],
	"outbounds": [${outObj}, {
		"protocol": "dns",
		"tag": "dns-out"
	}, {
		"protocol": "freedom",
		"tag": "no-proxy"
	}, {
		"protocol": "blackhole",
		"tag": "denyNetwork"
	}],
	"routing": {
		"domainStrategy": "AsIs",
		"domainMatcher": "mph",
		"rules": [$routeRulesObj],
		"balancers": [$routeBalancersObj]
	},
	"observatory": {$observatoryObj}
}
EOF
