#!/bin/sh /etc/rc.common

USE_PROCD=1

START=99
STOP=01

CONFIGURATION=dcwapd
VERBOSE=1
# NOTE: all functions write the result to the $result variable
result=

get_channelsets()
{
	# default to empty
	result=
	channelsets=$(uci show $CONFIGURATION | grep "=channel-set$")
	for channelset in $channelsets; do
		channelset=$(echo "$channelset" | sed -rn "s/$CONFIGURATION\.(.*)=.*/\1/p")
		result="$result $channelset"
	done
	if [ $VERBOSE -eq 1 ]; then
		echo "Channel Sets: $result" 2>&1 | logger
	fi
}

# $1 : the channel set name
get_channelset_enabled()
{
	# default to disabled
	result=0
	if [ -n "$1" ]; then
		result=$(uci get $CONFIGURATION."$1".enabled)
	fi
	if [ $VERBOSE -eq 1 ]; then
		echo "Channel Set \"$1\" Enabled: $result" 2>&1 | logger
	fi
}

# $1 : the channel set name
get_primary_bridge()
{
	result=
	if [ -n "$1" ]; then
		result=$(uci get $CONFIGURATION."$1".bridge)
	fi
	if [ $VERBOSE -eq 1 ]; then
		echo "Channel Set \"$1\" Primary Bridge: $result" 2>&1 | logger
	fi
}

# $1 : the channel set name
get_datachannels()
{
	# default to empty
	result=
	if [ -n "$1" ]; then
		result=$(uci get $CONFIGURATION."$1".data_channels)
	fi
	if [ $VERBOSE -eq 1 ]; then
		echo "Channel Set \"$1\" Data Channels: $result" 2>&1 | logger
	fi
}

# $1 : the wlan interface name
get_wifi_iface_num()
{
	result=
	if [ -n "$1" ];then
		#result=$(echo "$1" | sed -n "s/wlan//p")
		result=$(echo "$1" | sed -rn "s/wlan([0-9]*).*/\1/p")
	fi
}

# $1 : the bridge name
get_bridge_network_name()
{
	result=
	if [ -n "$1" ];then
		result=$(echo "$1" | sed -n "s/br-//p")
	fi
}

# $1 : the wlan interface name
set_iface_init_state()
{
	result=
	if [ -n "$1" ]; then
		iface=$1
		# need to extract the "X" from wlanX
		get_wifi_iface_num "$iface"
		iface_num=$result
		if [ -n "$iface_num" ]; then
			# get the iface network
			init_net=$(uci get wireless.@wifi-iface[$iface_num].network)
			if [ -n "$init_net" ]; then
				# if the iface network is a bridge, but doesn't start with "br-"
				#  I think we need to prepend it?
				net_type=$(uci get network."$init_net".type)
				if [ -n "$net_type" ] && [ "$net_type" = "bridge" ]; then
					prefix_ok=$(echo "$init_net" | grep "^br-")
					if [ -z "$prefix_ok" ]; then
						init_net="br-$init_net"
					fi
				fi
			fi

			# make sure that the init_net section exists
			init_net_section=$(uci get dcwapd.init_net)
			if [ "$init_net_section" != "init_net" ]; then
				# the section did not exist
				uci set dcwapd.init_net=init_net
			fi

			# save the initial network
			if [ $VERBOSE -eq 1 ]; then
				echo "Saving '$iface' initial network '$init_net'" 2>&1 | logger
			fi
			uci set $CONFIGURATION.init_net."$iface"="$init_net"
			uci commit

			# save the initial network in the result variable
			result=$init_net
		fi
	fi
}

# $1 : the wlan interface name
get_iface_init_state()
{
	result=
	if [ -n "$1" ];then
		init_net=$(uci get $CONFIGURATION.init_net."$iface")

		# if the response starts with "uci: ", it was an error not the real result
		err=$(echo "$init_net" | grep "^uci: ")
		if [ -z "$err" ]; then
			# no error, set the result
			result=$init_net

			if [ $VERBOSE -eq 1 ]; then
				echo "Got '$iface' initial network '$init_net'" 2>&1 | logger
			fi
		fi
	fi
}

# $1 : the name of the data channel name to bring up
datachannel_up()
{
	if [ -n "$1" ]; then
		bridge=$(uci get $CONFIGURATION."$1".bridge)
		interfaces=$(uci get $CONFIGURATION."$1".interfaces)
		if [ $VERBOSE -eq 1 ]; then
			echo "Creating Data Channel Bridge: $bridge" 2>&1 | logger
		fi

		get_bridge_network_name "$bridge"
		netname=$result
		if [ -n "$netname" ]; then
			uci set network."$netname"=interface
			uci set network."$netname".type=bridge
			uci set network."$netname".proto=static
			uci set network."$netname".bridge_empty='1'
		fi

		# create the bridge
		uci commit
		/etc/init.d/network reload

		for iface in $interfaces; do
			# if iface is in a bridge, the bridge name should be stored in result
			set_iface_init_state "$iface"
			init_bridge=$result

			# update uci with the new bridge info
			get_wifi_iface_num "$iface"
			iface_num=$result
			if [ -n "$iface_num" ]; then
				uci set wireless.@wifi-iface[$iface_num].network="$netname"
			fi

			# manually put the interface into the data bridge
			# if iface is in a bridge, remove it before adding it to the data bridge
			if [ -n "$init_bridge" ]; then
				brctl delif "$init_bridge" "$iface" 2>&1 | logger
			fi
			brctl addif "$bridge" "$iface" 2>&1 | logger
		done

		# commit uci changes and reload the network
		uci commit
		/etc/init.d/network reload
		#/etc/init.d/network restart
		# while [ 1 ]; do
		# 	ifconfig "$bridge" > /dev/null 2>&1
		# 	if [ $? == 0 ]; then
		# 		break;
		# 	fi
		# 	sleep 1
		# done
	fi
}

# $1 : the name of the data channel to bring down
datachannel_down()
{
	if [ -n "$1" ]; then
		bridge=$(uci get $CONFIGURATION."$1".bridge)
		interfaces=$(uci get $CONFIGURATION."$1".interfaces)
		for iface in $interfaces; do
			if [ $VERBOSE -eq 1 ]; then
				echo "Deconfiguring Data Channel Interface: $iface" 2>&1 | logger
			fi

			# manually remove the interface from the data bridge
			brctl delif "$bridge" "$iface" 2>&1 | logger

			get_iface_init_state "$iface"
			init_bridge=$result
			if [ -n "$init_bridge" ]; then
				# manually move the interface back to the original bridge
				brctl addif "$init_bridge" "$iface" 2>&1 | logger

				# update uci with the new bridge and interface configuration
				get_wifi_iface_num "$iface"
				iface_num=$result
				get_bridge_network_name "$init_bridge"
				netname=$result
				if [ -n "$iface_num" ] && [ -n "$netname" ]; then
					uci set wireless.@wifi-iface[$iface_num].network="$netname"
				fi
			fi
		done
		if [ $VERBOSE -eq 1 ]; then
			echo "Deconfiguring Data Channel Bridge: $bridge" 2>&1 | logger
		fi

		# delete the bridge from uci
		get_bridge_network_name "$bridge"
		netname=$result
		if [ -n "$netname" ]; then
			uci delete network."$netname"
		fi

		# commit uci changes and reload the network
		uci commit
		/etc/init.d/network reload
		#`/etc/init.d/network restart`
	fi
}

start_service() {
	config_load "$CONFIGURATION"
	local enabled

	config_get enabled general enabled
	if [ "$enabled" != "1" ]; then
		echo "dcwapd is disabled in UCI"
		return 1
	fi

	get_channelsets
	# get the list of channel sets
	channelsets=$result

	for channelset in $channelsets; do
	if [ -n "$channelset" ]; then
		get_channelset_enabled "$channelset"
		enabled=$result
		if [ "$enabled" = "1" ]; then
			# the channel set is enabled

			# get the list of data channels used by the channel set
			get_datachannels "$channelset"
			datachannels=$result
			for datachannel in $datachannels; do
				datachannel_up "$datachannel"
			done
		fi
	fi
	done

	procd_open_instance
	procd_set_param file /etc/config/dcwapd
	procd_set_param command dcwapd
	procd_set_param stdout 1
	procd_set_param stderr 1
	procd_close_instance
}

stop_service() {
	get_channelsets
	# get the list of channel sets
	channelsets=$result

	for channelset in $channelsets; do
	if [ -n "$channelset" ]; then
# we don't care if it is enabled, tear it down
#		get_channelset_enabled $channelset
#		enabled=$result
#		if [ $enabled = "1" ]; then
#			# the channel set is enabled

			# get the list of data channels used by the channel set
			get_datachannels "$channelset"
			datachannels=$result
			for datachannel in $datachannels; do
				datachannel_down "$datachannel"
			done
#		fi
	fi
	done

	sleep 1
}

service_triggers()
{
	procd_add_reload_trigger dcwapd
}

reload_service() {
	stop
	start
}
