#!/bin/sh
# The notice page's writer (ADR 0108 §2.6, PLAN WP A-3): `write <state> <reason|->`, called by the state hook after the kill switch
# has followed the state, writes the ONE page notice/serve answers every request with. Static: no script, no external reference
# (the device that reads it has no internet), no plan number (docs/plans.md owns those). The text is the English of the ADR 0108
# state vocabulary; the sentences repeat docs/errors.md's catalog titles, and the reason code is shown as small print for support.
# The page lists every LAN address the router has, because a static page cannot know which one the device came in by.
# Written into the run directory (tmpfs) by a rename, so a reader never sees half a page and nothing touches flash.
# NOTICE_DIR, NOTICE_TEMPLATE and NOTICE_ADDRS exist for the offline test; the hook runs with an empty environment.
st=${1:-}
rs=${2:--}
case $st in
	connecting | connected | reconnecting | waiting_network | stopped_local | stopped_refused | cannot_start) ;;
	*) echo "forestvpn notice: unknown state '$st'" >&2; exit 2 ;;
esac
echo "$rs" | grep -Eq '^(-|[a-z][a-z0-9_.]{0,63})$' || { echo "forestvpn notice: bad reason" >&2; exit 2; }

DIR=$(dirname "$0")
NOTICE_DIR=${NOTICE_DIR:-/var/run/forestvpn/notice}
NOTICE_TEMPLATE=${NOTICE_TEMPLATE:-/www-notice/page.html}
[ -f "$NOTICE_TEMPLATE" ] || { echo "forestvpn notice: no template $NOTICE_TEMPLATE" >&2; exit 1; }

PAUSED="Your internet is paused for your protection."
STRICT="The router is set to block the internet while ForestVPN is off."
case $st in
	connecting) title="ForestVPN is starting"; lead="$PAUSED It comes back by itself once ForestVPN is connected." ;;
	reconnecting) title="ForestVPN is reconnecting"; lead="$PAUSED It comes back by itself once ForestVPN is connected." ;;
	waiting_network) title="The router has no internet"; lead="Check the modem and the cable. ForestVPN connects by itself when the line is back. $PAUSED" ;;
	stopped_local) title="Protection is paused"; lead="ForestVPN is paused on this router. Your internet is not going through ForestVPN." ;;
	stopped_refused) title="ForestVPN can't connect"; lead="$STRICT" ;;
	cannot_start) title="ForestVPN is not running"; lead="$STRICT" ;;
	connected) title="ForestVPN is on"; lead="Your internet goes through ForestVPN. There is nothing to do here." ;;
esac
# a reason that changes what the person should do
case $st:$rs in
	reconnecting:session.quota_exceeded | connecting:session.quota_exceeded)
		title="This session used its whole allowance"
		lead="$PAUSED ForestVPN waits for you: open the router's ForestVPN page and press Reconnect." ;;
	stopped_refused:cp.quota_exceeded) title="Daily connection limit reached"; lead="ForestVPN will connect again when one of your daily connections is back. $STRICT" ;;
	stopped_refused:cp.data_cap_reached) title="Data allowance used up"; lead="ForestVPN will connect again when your allowance resets. $STRICT" ;;
	stopped_refused:cp.client_too_old) title="ForestVPN needs an update"; lead="This version of ForestVPN is too old to connect. Update it on the router. $STRICT" ;;
esac

# the router's LAN addresses: only dotted quads reach the page
addrs=${NOTICE_ADDRS-$("$DIR/serve" --listen 2> /dev/null | tr ' ' '\n' | sed 's/:[0-9]*$//')}
links=""
for a in $addrs; do
	echo "$a" | grep -Eq '^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}$' || continue
	links="$links${links:+ or }<a href=\"http://$a/\">$a</a>"
done
if [ -n "$links" ]; then router="To change settings or pause protection, open the router at $links and go to ForestVPN."
else router="To change settings or pause protection, open the router's settings page and go to ForestVPN."; fi
[ "$rs" = - ] && code="" || code="Code: $rs."

mkdir -p "$NOTICE_DIR" || exit 1
tmp=$NOTICE_DIR/.index.$$
# fill the template; the values have no backslash and no ampersand awk would treat specially (checked above and by the offline test)
awk -v state="$st" -v title="$title" -v lead="$lead" -v router="$router" -v code="$code" '
	function put(s, k, v,   i) { while ((i = index(s, k)) > 0) s = substr(s, 1, i - 1) v substr(s, i + length(k)); return s }
	{ $0 = put($0, "@STATE@", state); $0 = put($0, "@TITLE@", title); $0 = put($0, "@LEAD@", lead); $0 = put($0, "@ROUTER@", router); $0 = put($0, "@CODE@", code); print }
' "$NOTICE_TEMPLATE" > "$tmp" && chmod 0644 "$tmp" && mv "$tmp" "$NOTICE_DIR/index.html" || { rm -f "$tmp"; exit 1; }
