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

{
	START=90
	STOP=10
	USE_PROCD=1
}

# Clearing reset_exceeded (UCI/ubus) only matters for exceedance_scope=persistent
# -- month_only has no persistent marker of its own, so the daemon is also
# told (via OMR_QUOTA_RESET_BASELINE) to record a fresh usage baseline on this
# launch, which is what actually un-exceeds a month_only quota. state_id is
# the identity string this section's daemon instance is launched with --
# the interface name itself for "interface" sections, "global_<id>" for
# "global" sections -- since that's the key its state files are written under.
_reset_baseline_if_requested() {
	local state_id="$1" reset_exceeded="$2" uci_section="$3"
	if [ "$reset_exceeded" = "1" ]; then
		rm -f "/etc/omr-quota/state/${state_id}.exceeded"
		uci -q set "omr-quota.${uci_section}.reset_exceeded=0"
		uci -q commit omr-quota
		printf '1'
	else
		printf '0'
	fi
}

_track_vnstat() {
	local iface
	for iface in "$@"; do
		uci -q get vnstat.@vnstat[-1].interface | grep -Fqx -- "$iface" || {
			uci -q batch <<-EOF
				add_list vnstat.@vnstat[-1].interface=$iface
			EOF
		}
	done
}

_launch_quota() {
	local txquota rxquota ttquota interval enabled interface
	local exceedance_action throttle_dl throttle_ul exceedance_scope reset_exceeded reset_baseline
	local down_interfaces begindate enddate method percent calculation_interval block_lan
	uci_validate_section omr-quota "interface" "$1" \
		'txquota:uinteger'  \
		'rxquota:uinteger'  \
		'ttquota:uinteger'  \
		'interval:uinteger:30' \
		'enabled:bool:0' \
		'down_interfaces:string' \
		'begindate:string' \
		'enddate:string' \
		'method:uinteger:0' \
		'percent:uinteger:80' \
		'calculation_interval:uinteger:120' \
		'block_lan:bool:0' \
		'exceedance_action:string:cut' \
		'throttle_dl:uinteger:1' \
		'throttle_ul:uinteger:1' \
		'exceedance_scope:string:month_only' \
		'reset_exceeded:bool:0'
	interface=$1

	[ -z "$interface" ] && return
	[ -z "$txquota" ] && [ -z "$rxquota" ] && [ -z "$ttquota" ] && return
	[ "$enabled" = "0" ] && return
	[ -z "$down_interfaces" ] && down_interfaces="$interface"

	reset_baseline=$(_reset_baseline_if_requested "$interface" "$reset_exceeded" "$interface")

	_track_vnstat "$interface"

	procd_open_instance
	procd_set_param command /bin/omr-quota "$interface"
	procd_append_param env "OMR_QUOTA_TX=$txquota"
	procd_append_param env "OMR_QUOTA_RX=$rxquota"
	procd_append_param env "OMR_QUOTA_TT=$ttquota"
	procd_append_param env "OMR_QUOTA_INTERVAL=$interval"
	procd_append_param env "OMR_QUOTA_DOWN_INTERFACES=$down_interfaces"
	procd_append_param env "OMR_QUOTA_BEGINDATE=$begindate"
	procd_append_param env "OMR_QUOTA_ENDDATE=$enddate"
	procd_append_param env "OMR_QUOTA_METHOD=$method"
	procd_append_param env "OMR_QUOTA_PERCENT=$percent"
	procd_append_param env "OMR_QUOTA_CALCULATION_INTERVAL=$calculation_interval"
	procd_append_param env "OMR_QUOTA_BLOCK_LAN=$block_lan"
	procd_append_param env "OMR_QUOTA_ACTION=$exceedance_action"
	procd_append_param env "OMR_QUOTA_THROTTLE_DL=$throttle_dl"
	procd_append_param env "OMR_QUOTA_THROTTLE_UL=$throttle_ul"
	procd_append_param env "OMR_QUOTA_SCOPE=$exceedance_scope"
	procd_append_param env "OMR_QUOTA_RESET_BASELINE=$reset_baseline"
	procd_set_param respawn 0 10 0
	procd_set_param stderr 1
	procd_close_instance
}

# A global quota has no single interface of its own -- it combines several
# WANs and, when exceeded, cuts/throttles all of them (see omr-quota's
# target_interfaces). Its daemon identity is "global_<uci section id>" so its
# state files never collide with a same-named "interface" section, and so the
# id stays valid for anonymous sections whose uci id is not a real ifname.
_launch_global_quota() {
	local txquota rxquota ttquota interval enabled interfaces
	local exceedance_action throttle_dl throttle_ul exceedance_scope reset_exceeded reset_baseline
	local down_interfaces begindate enddate method percent calculation_interval block_lan
	local state_id
	uci_validate_section omr-quota "global" "$1" \
		'interfaces:string' \
		'txquota:uinteger'  \
		'rxquota:uinteger'  \
		'ttquota:uinteger'  \
		'interval:uinteger:30' \
		'enabled:bool:0' \
		'down_interfaces:string' \
		'begindate:string' \
		'enddate:string' \
		'method:uinteger:0' \
		'percent:uinteger:80' \
		'calculation_interval:uinteger:120' \
		'block_lan:bool:0' \
		'exceedance_action:string:cut' \
		'throttle_dl:uinteger:1' \
		'throttle_ul:uinteger:1' \
		'exceedance_scope:string:month_only' \
		'reset_exceeded:bool:0'

	[ -z "$interfaces" ] && return
	[ -z "$txquota" ] && [ -z "$rxquota" ] && [ -z "$ttquota" ] && return
	[ "$enabled" = "0" ] && return
	[ -z "$down_interfaces" ] && down_interfaces="$interfaces"

	state_id="global_$1"
	reset_baseline=$(_reset_baseline_if_requested "$state_id" "$reset_exceeded" "$1")

	_track_vnstat $interfaces

	procd_open_instance
	procd_set_param command /bin/omr-quota "$state_id"
	procd_append_param env "OMR_QUOTA_TX=$txquota"
	procd_append_param env "OMR_QUOTA_RX=$rxquota"
	procd_append_param env "OMR_QUOTA_TT=$ttquota"
	procd_append_param env "OMR_QUOTA_INTERVAL=$interval"
	procd_append_param env "OMR_QUOTA_INTERFACES=$interfaces"
	procd_append_param env "OMR_QUOTA_DOWN_INTERFACES=$down_interfaces"
	procd_append_param env "OMR_QUOTA_BEGINDATE=$begindate"
	procd_append_param env "OMR_QUOTA_ENDDATE=$enddate"
	procd_append_param env "OMR_QUOTA_METHOD=$method"
	procd_append_param env "OMR_QUOTA_PERCENT=$percent"
	procd_append_param env "OMR_QUOTA_CALCULATION_INTERVAL=$calculation_interval"
	procd_append_param env "OMR_QUOTA_BLOCK_LAN=$block_lan"
	procd_append_param env "OMR_QUOTA_ACTION=$exceedance_action"
	procd_append_param env "OMR_QUOTA_THROTTLE_DL=$throttle_dl"
	procd_append_param env "OMR_QUOTA_THROTTLE_UL=$throttle_ul"
	procd_append_param env "OMR_QUOTA_SCOPE=$exceedance_scope"
	procd_append_param env "OMR_QUOTA_RESET_BASELINE=$reset_baseline"
	procd_set_param respawn 0 10 0
	procd_set_param stderr 1
	procd_close_instance
}

start_service() {
	config_load omr-quota
	config_foreach _launch_quota interface
	config_foreach _launch_global_quota global
}

service_triggers() {
	procd_add_reload_trigger omr-quota network
}

reload_service() {
	stop
	start
}
