#!/bin/sh
# Apply /etc/default/console without a reboot.
# Usage: console-mode apply

set -eu

DEFAULTS=/etc/default/console
CONSOLE=cruft
CONSOLE_TTYS="1 2 3 4 5 6"
CONSOLE_FONT=default
CRUFT_FONT=
YAFT_FONT=

if [ -f "$DEFAULTS" ]; then
	# shellcheck disable=SC1090
	. "$DEFAULTS"
fi

usage() {
	echo "Usage: $0 apply" >&2
	echo "  Reads $DEFAULTS (CONSOLE=cruft|kernel, CONSOLE_FONT=...)." >&2
	echo "  Font changes take effect on logout (systemd restarts the VT's cruft)." >&2
	exit 1
}

[ "${1:-}" = "apply" ] || usage

case "$CONSOLE" in
yaft) CONSOLE=cruft ;;
esac

case "$CONSOLE" in
cruft|kernel) ;;
*)
	echo "console-mode: unknown CONSOLE='$CONSOLE'" >&2
	exit 1
	;;
esac

# shellcheck disable=SC2086
set -- $CONSOLE_TTYS
boot_tty=${1:-1}

resolve_font() {
	if [ -n "${CRUFT_FONT:-}" ]; then
		return 0
	fi
	if [ -n "${YAFT_FONT:-}" ]; then
		CRUFT_FONT=$YAFT_FONT
		return 0
	fi
	case "${CONSOLE_FONT:-default}" in
	default|console|"") CRUFT_FONT=/usr/share/cruft/console.cruftfont ;;
	miniwi) CRUFT_FONT=/usr/share/cruft/miniwi.cruftfont ;;
	unifont) CRUFT_FONT=/usr/share/cruft/unifont.cruftfont ;;
	*)
		echo "console-mode: unknown CONSOLE_FONT='$CONSOLE_FONT' (default|miniwi|unifont)" >&2
		exit 1
		;;
	esac
}

vt_unit() {
	# Boot VT is cruft@ttyN; on-demand VTs are autovt@ttyN (→ cruft@).
	n=$1
	if [ "$n" = "$boot_tty" ]; then
		echo "cruft@tty${n}.service"
	else
		echo "autovt@tty${n}.service"
	fi
}

# What is currently running on the managed TTYs?
running_cruft=0
running_getty=0
for n in $CONSOLE_TTYS; do
	u=$(vt_unit "$n")
	if systemctl is-active --quiet "$u" 2>/dev/null || \
	   systemctl is-active --quiet "cruft@tty${n}.service" 2>/dev/null; then
		running_cruft=1
	fi
	if systemctl is-active --quiet "getty@tty${n}.service" 2>/dev/null; then
		running_getty=1
	fi
done

need_backend_switch=0
if [ "$CONSOLE" = "cruft" ] && [ "$running_getty" -eq 1 ]; then
	need_backend_switch=1
fi
if [ "$CONSOLE" = "kernel" ] && [ "$running_cruft" -eq 1 ]; then
	need_backend_switch=1
fi
# Fresh boot / nothing up yet: start the requested backend.
if [ "$running_cruft" -eq 0 ] && [ "$running_getty" -eq 0 ]; then
	need_backend_switch=1
fi

if [ "$CONSOLE" = "cruft" ]; then
	resolve_font
	if [ ! -r "$CRUFT_FONT" ]; then
		echo "console-mode: font not installed or unreadable: $CRUFT_FONT" >&2
		echo "console-mode: install miniwi-console / unifont-console, or fix CONSOLE_FONT" >&2
		exit 1
	fi
fi

# Regenerate generator drop-in (CRUFT_FONT / TERM) and unit wants.
systemctl daemon-reload

failed=0

if [ "$need_backend_switch" -eq 1 ]; then
	# Switching cruft ↔ kernel (or first bring-up).
	for n in $CONSOLE_TTYS; do
		systemctl stop "cruft@tty${n}.service" "autovt@tty${n}.service" \
			"yaft@tty${n}.service" "getty@tty${n}.service" 2>/dev/null || true
	done
	if [ "$CONSOLE" = "cruft" ]; then
		# Only the boot VT — others start on first Alt-Fn via logind/autovt@.
		if ! systemctl start "cruft@tty${boot_tty}.service"; then
			echo "console-mode: failed to start cruft@tty${boot_tty}" >&2
			systemctl --no-pager -l status "cruft@tty${boot_tty}.service" 2>&1 | tail -n 20 >&2 || true
			failed=1
		fi
	else
		for n in $CONSOLE_TTYS; do
			if ! systemctl start "getty@tty${n}.service"; then
				echo "console-mode: failed to start getty@tty${n}" >&2
				failed=1
			fi
		done
	fi
	echo "console-mode: switched backend to CONSOLE=$CONSOLE"
else
	echo "console-mode: updated config (daemon-reload); not restarting active VTs"
fi

if [ "$CONSOLE" = "cruft" ]; then
	env_line=$(systemctl show -p Environment "cruft@tty${boot_tty}.service" 2>/dev/null || true)
	echo "console-mode: CONSOLE_FONT=${CONSOLE_FONT:-default} → $CRUFT_FONT"
	echo "console-mode: tty${boot_tty} $env_line"
	echo "console-mode: boot VT=tty${boot_tty}; tty2+ start on first switch (autovt@ → cruft@)"
	if [ "$need_backend_switch" -eq 0 ]; then
		echo "console-mode: log out and back in on a VT to load the new font there"
		echo "console-mode: (logout ends agetty → cruft exits → systemd restarts with CRUFT_FONT)"
	fi
	for n in $CONSOLE_TTYS; do
		u=$(vt_unit "$n")
		state=$(systemctl is-active "$u" 2>/dev/null || echo inactive)
		# Legacy name if someone still has an old wants symlink.
		if [ "$state" = "inactive" ] || [ "$state" = "unknown" ]; then
			alt=$(systemctl is-active "cruft@tty${n}.service" 2>/dev/null || true)
			if [ "$alt" = "active" ]; then
				u="cruft@tty${n}.service"
				state=active
			fi
		fi
		echo "console-mode: $u is-active=$state"
	done
else
	echo "console-mode: CONSOLE=kernel on tty$(echo $CONSOLE_TTYS | tr ' ' ',')"
fi

exit "$failed"
