#!/bin/sh
# shellcheck shell=dash
# shellcheck disable=SC1091
# vim: set ft=sh noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 :

# Constants
MAX_SPEED=300
OTB_DATA_DIR="/var/otb-data"

. /lib/functions/network.sh
. /lib/overthebox

_log() {
	logger -p daemon.info -t "$(basename "${0}")" "$@"
}

_err() {
	logger -p daemon.err -t "$(basename "${0}")" "$@"
}

update_itf_physicalLayer() {
	local interface="$1"
	local download="$2"
	local upload="$3"
	local jitter="$4"

	download=$(printf "%.0f" "$download")
	upload=$(printf "%.0f" "$upload")
	jitter=$(printf "%.0f" "$jitter")

	proto=$(uci -q get "network.${interface}.proto")

	l1layer=$(uci -q get "network.${interface}.physicallayer")

	# physical layer already set skipping
	if [ -n "$l1layer" ]; then
		_log "Interface $interface physical layer already set to $l1layer, skipping"
		return
	fi

	# Proto is modemmanager layer is 4G
	if [ "$proto" = "modemmanager" ]; then
		uci set network."${interface}".physicallayer='4g'
		uci commit
		_log "Interface $interface use proto modemmanager, physical layer set to 4g"
		return
	fi

	# With high jitter assuming 4G
	# Maybe we need a pattern to auto-detect satelite connexion
	if [ "$jitter" -ge 2 ]; then
		uci set network."${interface}".physicallayer='4g'
		uci commit
		_log "Interface $interface has high jitter, physical layer set to 4g"
		return
	fi

	# Low jitter speed inferior to 20Mbps, layer is ADSL
	if [ "$download" -lt 20 ]; then
		uci set network."${interface}".physicallayer='adsl'
		uci commit
		_log "Interface $interface, physical layer set to adsl"
		return
	fi

	# Low jitter speed inferior to 100Mbps, layer is VDSL
	if [ "$download" -lt 100 ]; then
		uci set network."${interface}".physicallayer='vdsl'
		uci commit
		_log "Interface $interface, physical layer set to vdsl"
		return
	fi

	# Low jitter High speed, layer is ethernet
	uci set network."${interface}".physicallayer='ethernet'
	uci commit
	_log "Interface $interface, physical layer set to ethernet"
}

update_sqm_config() {
	local interface="$1"
	local download="$2"
	local upload="$3"

	# Do not set SQM if WAN is fiber (high speed)
	download=$(printf "%.0f" "$download")
	upload=$(printf "%.0f" "$upload")
	if [ "$download" -ge $MAX_SPEED ] || [ "$upload" -ge $MAX_SPEED ]; then
		_log "Interface speed exceeds ${MAX_SPEED}Mbps, no SQM needed on $interface"
		return
	fi

	# Calculate 90% of speed in kbps
	download_kbps=$((download * 900))
	upload_kbps=$((upload * 900))

	# Retrieve interface's device name
	proto=$(uci -q get "network.${interface}.proto")
	if [ "$proto" = "modemmanager" ];
	then
		device="wwan0" # LTE virtual device
	else
		device=$(uci -q get "network.${interface}.device")
	fi

	# Get physical layer
	l1layer=$(uci -q get "network.${interface}.physicallayer")

	# Configure SQM
	uci set sqm."${interface}"='queue'
	uci set sqm."${interface}".enabled=1
	uci set sqm."${interface}".interface="$device"
	uci set sqm."${interface}".qdisc='cake'
	uci set sqm."${interface}".download="$download_kbps"
	uci set sqm."${interface}".upload="$upload_kbps"
	uci set sqm."${interface}".script='piece_of_cake.qos'

	if [ "$l1layer" = "vdsl" ]; then
		uci set sqm."${interface}".linklayer='ethernet'
		uci set sqm."${interface}".overhead='34'
	elif [ "$l1layer" = "adsl" ]; then
		uci set sqm."${interface}".linklayer='atm'
		uci set sqm."${interface}".overhead='44'
	fi

	uci commit

	_log "Updated SQM configuration for $interface"
}

# Stop SQM before main loop
/etc/init.d/sqm stop

# Main loop
for interface in "$@"; do
	# Interface must be OK
	connectivity_file="$OTB_DATA_DIR/$interface/connectivity"
	[ -f "$connectivity_file" ] || continue
	[ "$(cat "$connectivity_file")" = "OK" ] || continue

	# Retrieve interface speeds
	network_get_ipaddr SOURCE_IP "$interface"
	speedtest_json "$SOURCE_IP"

	download=$(echo "$SPEEDTEST" | jq -r ".[0].download")
	upload=$(echo "$SPEEDTEST" | jq -r ".[0].upload")
	jitter=$(echo "$SPEEDTEST" | jq -r ".[0].jitter")

	# Check if speeds are well captured
	if [ -z "$download" ] || [ -z "$upload" ] || [ -z "$jitter" ]; then
		_err "Speedtest for $interface failed"
	else
		_log "Speedtest for $interface - Download: $download, Upload: $upload, Jitter: $jitter"

		update_itf_physicalLayer "$interface" "$download" "$upload" "$jitter"
		update_sqm_config "$interface" "$download" "$upload"
	fi
done

# Restart SQM service to apply changes
/etc/init.d/sqm start
/etc/init.d/glorytun restart
