#!/bin/bash
# shellcheck disable=SC1091
# vim: set noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 :

ME=$(basename "$0")

. /lib/overthebox

otb_info "executing otb-action-configure"

if [ -z "$OTB_SERVICE_ID" ]; then
	otb_err "no service_id, skipping"
	exit 1
fi

if [ "$(uci -q get overthebox.me.needs_activation)" = 'true' ]; then
	otb_err "service not activated, skipping"
	exit 1
fi


config="$(otb_device_get config | jq -r .)"
if [ -z "$config" ]; then
	otb_info "failed to get configuration"
	exit 1
# // empty is used to return a empty string instead of null
elif [ -n "$(echo "$config" |jq -r '.class // empty')" ]; then
	otb_err "failed to get service $config"
	exit 1
fi

_get() {
	otb_json_get "$config" "$1"
}

_setup_glorytun() {
	local glorytun_mud_conf=$1
	local lan_ipv6_conf=$2

	tun_dev=$(echo "$glorytun_mud_conf" | jq -r '.dev')
	ipv6_peer=$(echo "$glorytun_mud_conf" | jq -r '.ipv6_peer // empty')
	ipv6_lan_status=$(uci -q get network.lan.ipv6)

	if [ -z "$tun_dev" ]; then
		otb_err "invalid tun device"
		return
	fi

	otb_debug "setting up glorytun on $tun_dev"
	otb_debug "setting up glorytun config"
	echo "$glorytun_mud_conf" | jq -r '@text "
		set glorytun.\(.dev)=mud
		set glorytun.\(.dev).enable=1
		set glorytun.\(.dev).dev=\(.dev)
		set glorytun.\(.dev).server=\(.server)
		set glorytun.\(.dev).port=\(.port)
		set glorytun.\(.dev).key=\(.key)
		set glorytun.\(.dev).mtu=\(.mtu)
		set glorytun.\(.dev).mtu_auto=\(.mtu_auto)
	"' | uci -q batch

	otb_debug "setting up glorytun network"
	echo "$glorytun_mud_conf" | jq -r '@text "
		set network.\(.dev)=interface
		set network.\(.dev).device=\(.dev)
		set network.\(.dev).proto=static
		set network.\(.dev).ipaddr=\(.ip_local)
		set network.\(.dev).netmask=255.255.255.0
		set network.\(.dev).gateway=\(.ip_peer)
		set network.\(.dev).metric=\(.metric)
		set network.\(.dev).ip4table=\(.table)
		set network.\(.dev).txqueuelen=1000
		set network.\(.dev).type=tunnel
		set network.\(.dev).multipath=off
		set network.\(.dev).generatedby='"$ME"'
	"' | uci -q batch

	if [[ $(uci get firewall.wan.network) == *"$tun_dev"* ]]; then
		otb_debug "removing $tun_dev from firewall zone"
		uci -q del_list firewall.wan.network="$tun_dev"
	fi

	otb_debug "setting up glorytun firewall"
	uci -q batch <<-EOF
		delete firewall.tun.network
		delete firewall.tunv6.network
		add_list firewall.tun.network=$tun_dev
	EOF

	if [ -n "$ipv6_peer" ]; then
		otb_debug "setting up glorytun ipv6"
		echo "$glorytun_mud_conf" | jq -r '@text "
			set network.\(.dev).ip6addr=\(.ipv6_local)'"/112"'
			set network.\(.dev).ip6gw=\(.ipv6_peer)
			set network.\(.dev).ip6table=\(.table)
			set network.\(.dev).ipv6=1
			set network.\(.dev).delegate=0
			add_list firewall.tunv6.network=\(.dev)
		"' | uci -q batch


		if [ "$ipv6_lan_status" = "0" ]; then
			otb_debug "setting up lan ipv6"
			echo "$lan_ipv6_conf" | jq -r '@text "
				set network.lan.ip6table=lan
				set network.lan.ip6addr=\(.ipv6_prefix)1/\(.ipv6_range)
				set network.lan.ip6assign=\(.ipv6_range)
				set network.lan.ipv6=1
				set network.@device[0].ipv6=1
				set dhcp.lan.ra=server
				set dhcp.lan.dhcpv6=server
				set dhcp.@dnsmasq[0].filter_aaaa=0
			"' | uci -q batch
		fi
	else
		otb_debug "checking that ipv6 is disabled"
		if [ "$(uci -q get network."$tun_dev".ipv6)" != 0 ]; then
			otb_debug "disabling ipv6 on glorytun"
			uci -q batch <<-EOF
				set network."$tun_dev".ipv6=0
				delete network."$tun_dev".ip6addr
				delete network."$tun_dev".ip6gw
				delete network."$tun_dev".ip6table
				delete network."$tun_dev".delegate
			EOF
		fi

		if [ "$ipv6_lan_status" = "1" ]; then
			otb_debug "disabling lan ipv6"
			uci -q batch <<-EOF
				delete network.lan.ip6table
				delete network.lan.ip6addr
				delete network.lan.ip6assign
				set network.lan.ipv6=0
				set network.@device[0].ipv6=0
				set dhcp.lan.ra=disabled
				set dhcp.lan.dhcpv6=disabled
				set dhcp.dnsmasq[0].filter_aaaa=1
			EOF
		fi
	fi
}

_setup_shadowsocks() {
	otb_debug "setting up shadowsocks"
	jq -r '@text "
	set shadowsocks.proxy=client
	set shadowsocks.proxy.server=\(.server)
	set shadowsocks.proxy.port=\(.port)
	set shadowsocks.proxy.lport=\(.lport)
	set shadowsocks.proxy.method=\(.method)
	set shadowsocks.proxy.timeout=\(.timeout)
	set shadowsocks.proxy.reuse_port=\(.reuse_port)
	set shadowsocks.proxy.fast_open=\(.fast_open)
	set shadowsocks.proxy.disable_sni=\(.disable_sni)
	set shadowsocks.proxy.monitoring_ip=\(.monitoring_ip)
	set shadowsocks.proxy.track_interval=\(.track_interval)
	set shadowsocks.proxy.track_timeout=\(.track_timeout)
	set shadowsocks.proxy.track_retry=\(.track_retry)
	set shadowsocks.proxy.password=\(.password)
	set shadowsocks.proxy.disabled=\(.disabled)
	"'
}

_setup_log() {
	otb_debug "setting up log"
	jq -r '@text "
	set system.@system[0].log_ip=\(.host)
	set system.@system[0].log_port=\(.port)
	set system.@system[0].log_proto=\(.protocol)
	set system.@system[0].log_prefix=\(.key)
	"'
}

_setup_graph() {
	otb_debug "setting up graph"
	jq -r '@text "
	set graph.opentsdb=opentsdb
	set graph.opentsdb.url=\(.host)
	set graph.opentsdb.freq=\(.write_frequency)

	set graph.provisioning=provisioning
	set graph.provisioning.freq=\(.write_frequency)
	"'
}

config_error=$(_get "error // empty")

if [ "$config_error" ]; then
	echo "$config_error" >&2
	exit 1
fi

# Delete last conf
for conf in glorytun shadowsocks graph otb-graph; do
	true > /etc/config/"$conf"
	uci -q revert "$conf"
done

# Activate IPv6 on glorytun depending on configuration
glorytun_mud_conf=$(_get "glorytun_mud_conf")
lan_ipv6_conf=$(_get "ipv6_conf.lan_conf")

_setup_glorytun "$glorytun_mud_conf" "$lan_ipv6_conf"

_get shadow_conf | _setup_shadowsocks | uci -q batch
_get log_conf | _setup_log | uci -q batch
_get graph_conf | _setup_graph | uci -q batch

# Log changes in debug mode
readarray -t changes <<< "$(uci changes)"
for x in "${changes[@]}"; do otb_debug "c: $x" ; done

uci -q commit
