#!/bin/sh

cmd="$1"
source="$2"
mode="$3"
api_port="$(uci -q get netlog.settings.api_port)"
case "$api_port" in
	''|*[!0-9]*) api_port=8687 ;;
esac
[ "$api_port" -ge 1 ] 2>/dev/null && [ "$api_port" -le 65535 ] 2>/dev/null || api_port=8687
api_base="http://127.0.0.1:$api_port/api"
api_connect_timeout=1
api_max_time=2
api_port_hex="$(printf '%04X' "$api_port" 2>/dev/null)"

case "$source" in
	url|dns) ;;
	*) exit 1 ;;
esac

api_get() {
	local path="$1"
	api_listening || return 1
	command -v curl >/dev/null 2>&1 || return 1
	curl -fsS --connect-timeout "$api_connect_timeout" --max-time "$api_max_time" "$api_base/$path" 2>/dev/null
}

api_listening() {
	[ -n "$api_port_hex" ] || return 1
	awk -v port=":$api_port_hex" '
		NR > 1 && $4 == "0A" && index($2, port) > 0 { found = 1 }
		END { exit found ? 0 : 1 }
	' /proc/net/tcp /proc/net/tcp6 2>/dev/null
}

api_range_model() {
	api_listening || return 1
	command -v curl >/dev/null 2>&1 || return 1
	curl -fsS -G --connect-timeout "$api_connect_timeout" --max-time "$api_max_time" "$api_base/$source/range-model" \
		--data-urlencode "from=$from_key" \
		--data-urlencode "to=$to_key" \
		--data-urlencode "step=$step_min" \
		--data-urlencode "stats=$include_stats" \
		--data-urlencode "dev=$dev_filter" \
		--data-urlencode "dev_inv=$dev_invert" \
		--data-urlencode "target=$target_filter" \
		--data-urlencode "target_inv=$target_invert" \
		--data-urlencode "type=$dns_type_filter" \
		--data-urlencode "event=$dns_event_filter" \
		--data-urlencode "live_only=$live_only" \
		--data-urlencode "refresh=$refresh" 2>/dev/null
}

api_table() {
	api_listening || return 1
	command -v curl >/dev/null 2>&1 || return 1
	curl -fsS -G --connect-timeout "$api_connect_timeout" --max-time "$api_max_time" "$api_base/$source/table" \
		--data-urlencode "from=$from_key" \
		--data-urlencode "to=$to_key" \
		--data-urlencode "page=$page" \
		--data-urlencode "size=$size" \
		--data-urlencode "dev=$dev_filter" \
		--data-urlencode "dev_inv=$dev_invert" \
		--data-urlencode "target=$target_filter" \
		--data-urlencode "target_inv=$target_invert" \
		--data-urlencode "type=$dns_type_filter" \
		--data-urlencode "event=$dns_event_filter" 2>/dev/null
}

api_tail() {
	api_listening || return 1
	command -v curl >/dev/null 2>&1 || return 1
	curl -fsS -G --connect-timeout "$api_connect_timeout" --max-time "$api_max_time" "$api_base/$source/tail" \
		--data-urlencode "offset=$tail_offset" \
		--data-urlencode "max=$tail_max" 2>/dev/null
}

tail_log_files() {
	local lines="$1"
	local file
	for file in $(log_files); do
		[ -f "$file" ] && tail -n "$lines" "$file" 2>/dev/null
	done | tail -n "$lines"
}

log_files() {
	case "$source" in
		url)
			if [ "$(uci -q get netlog.settings.persist_log)" = "1" ]; then
				printf '%s\n' /overlay/netlog/url.log /tmp/netlog/url.log
			else
				printf '%s\n' /tmp/netlog/url.log
			fi
			;;
		dns)
			if [ "$(uci -q get netlog.settings.dns_persist_log)" = "1" ]; then
				printf '%s\n' /overlay/netlog/dns.log /tmp/netlog/dns.log
			else
				printf '%s\n' /tmp/netlog/dns.log
			fi
			;;
	esac
}

clear_log_files() {
	case "$source" in
		url)
			rm -f /tmp/netlog/url.log /tmp/netlog/url-chart.tsv /tmp/netlog/url-stats.tsv \
				/overlay/netlog/url.log /overlay/netlog/url-chart.tsv /overlay/netlog/url-stats.tsv
			printf 'clear' >/dev/urllogger_queue 2>/dev/null || true
			;;
		dns)
			rm -f /tmp/netlog/dns.log /tmp/netlog/dns-chart.tsv /tmp/netlog/dns-stats.tsv \
				/overlay/netlog/dns.log /overlay/netlog/dns-chart.tsv /overlay/netlog/dns-stats.tsv
			rm -rf /tmp/netlog/dns-capture
			;;
	esac
}

date_range() {
	api_get "$source/date-range" || {
		printf 'api-unavailable\n'
		exit 0
	}
}

norm_common_range_args() {
	from_key="$3"
	to_key="$4"
	step_min="${5:-60}"
	dev_filter="${6:-}"
	dev_invert="${7:-0}"
	target_filter="${8:-}"
	target_invert="${9:-0}"
	dns_type_filter="${10:-}"
	dns_event_filter="${11:-}"
	live_only="${12:-0}"
	refresh="${13:-0}"
	[ "$dev_filter" = "-" ] && dev_filter=""
	[ "$target_filter" = "-" ] && target_filter=""
	[ "$dns_type_filter" = "-" ] && dns_type_filter=""
	[ "$dns_event_filter" = "-" ] && dns_event_filter=""
	[ "$live_only" = "1" ] || live_only=0
	[ "$refresh" = "1" ] || refresh=0
	case "$from_key$to_key$step_min" in ''|*[!0-9]*) exit 1 ;; esac
	[ "$step_min" -gt 0 ] || step_min=60
}

case "$cmd" in
	clear)
		clear_log_files
		;;
	date-range)
		date_range
		;;
log)
	if [ "$mode" = "tail" ]; then
		lines="${4:-500}"
		case "$lines" in ''|*[!0-9]*) lines=500 ;; esac
		tail_log_files "$lines"
	elif [ "$mode" = "raw" ]; then
		cat $(log_files) 2>/dev/null
	elif api_get "$source/log"; then
		exit 0
	else
		cat $(log_files) 2>/dev/null
	fi
		;;
	tail)
		tail_offset="${3:--1}"
		tail_max="${4:-65536}"
		[ "$tail_offset" = "state" ] && tail_offset="-1"
		case "$tail_offset" in -[0-9]*|[0-9]*) ;;
			*) tail_offset="-1" ;;
		esac
		case "$tail_max" in ''|*[!0-9]*) tail_max=65536 ;; esac
		api_tail || tail_log_files 500
		;;
	table)
		from_key="$3"
		to_key="$4"
		page="${5:-1}"
		size="${6:-50}"
		dev_filter="${7:-}"
		dev_invert="${8:-0}"
		target_filter="${9:-}"
		target_invert="${10:-0}"
		dns_type_filter="${11:-}"
		dns_event_filter="${12:-}"
		[ "$dev_filter" = "-" ] && dev_filter=""
		[ "$target_filter" = "-" ] && target_filter=""
		[ "$dns_type_filter" = "-" ] && dns_type_filter=""
		[ "$dns_event_filter" = "-" ] && dns_event_filter=""
		case "$from_key$to_key$page$size" in ''|*[!0-9]*) exit 1 ;; esac
		[ "$page" -lt 1 ] && page=1
		[ "$size" -lt 1 ] && size=50
		[ "$size" -gt 500 ] && size=500
		api_table || exit 1
		;;
	stats)
		api_get "$source/stats" || exit 1
		;;
	chart-model|range-model)
		include_stats=0
		[ "$cmd" = "range-model" ] && include_stats=1
		norm_common_range_args "$@"
		api_range_model || exit 1
		;;
	*)
		exit 1
		;;
esac
