#!/bin/sh

. /usr/share/libubox/jshn.sh

WAN_DIRECT_FILE=/tmp/nowanifconfig
WAN_CONFIG_LOCKFILE=/tmp/nowanifconfig.lock
WAN_IF_STATUS=/tmp/ifstatus$$
IPV4_STATIC_ROUTE_SCRIPT=/etc/necpf/ip4static_route.sh

ifup_all=
setup_wifi=

wan_lock() {
	exec 1000> "$WAN_CONFIG_LOCKFILE"
	flock -n 1000 &> /dev/null
	if [ "$?" != "0" ]; then
		# already locked
		return 1
	fi
	if [ -e ${WAN_DIRECT_FILE} ]; then
		wan_unlock
		return 1
	fi
	return 0
}

wan_unlock() {
	flock -u 1000

	return $?
}

wait_ifupdown_done() {
	local n=30
	local pending=0
	local up=0
	local errors

	while [ $n -gt 0 ];
	do
		sleep 1
		ubus call network.interface.$1 status > ${WAN_IF_STATUS}
		eval "$(jshn -R ${WAN_IF_STATUS} )"
		rm -f ${WAN_IF_STATUS}
		json_get_var pending pending
		json_is_a errors array && return 1

		if [ "$pending" = "0" ]; then
			if [ "$mode" = "up" ]; then
				"$IPV4_STATIC_ROUTE_SCRIPT" wan
			fi
			return 0
		fi

		n=$((n - 1))
	done
}

is_if_wan() { local interface="$1"

	if [ "$interface" = "wan" -o "$interface" = "wan6" ]; then
		return 0
	else
		return 1
	fi
}

if_call() {
	local interface="$1"
	local err

	if is_if_wan "$interface" ; then
		 wan_lock || return 0
	fi

	for mode in $modes; do
		ubus call network.interface $mode "{ \"interface\" : \"$interface\" }"
	done

	if is_if_wan "$interface" ; then
		wait_ifupdown_done $interface
		err=$?
		wan_unlock
		return $err
	fi
}

case "$0" in
	*ifdown) modes=down;;
	*ifup)
		modes="down up"
		setup_wifi=1
	;;
	*) echo "Invalid command: $0";;
esac

while :; do
	case "$1" in
		-a)
			ifup_all=1
			shift
		;;
		-w)
			setup_wifi=
			shift
		;;
		*)
			break
		;;
	esac
done

[ "$modes" = "down up" ] && ubus call network reload
if [ -n "$ifup_all" ]; then
	for interface in `ubus -S list 'network.interface.*'`; do
		if_call "${interface##network.interface.}"
	done
	[ -n "$setup_wifi" ] && /sbin/wifi up
	exit
else
	ubus -S list "network.interface.$1" > /dev/null || {
		echo "Interface $1 not found"
		exit
	}
	if_call "$1"
fi

if [ -n "$setup_wifi" ] && grep -sq config /etc/config/wireless; then
	. /lib/functions.sh

	find_related_radios() {
		local wdev wnet
		config_get wdev "$1" device
		config_get wnet "$1" network

		if [ -n "$wdev" ]; then
			for wnet in $wnet; do
				if [ "$wnet" = "$network" ]; then
					append radio_devs "$wdev" "$N"
				fi
			done
		fi
	}

	network="$1"
	config_load wireless
	config_foreach find_related_radios wifi-iface

	for dev in $(echo "$radio_devs" | sort -u); do
		/sbin/wifi up "$dev"
	done
fi
