#!/bin/bash
### This file is covered by the GNU General Public License
### version 3 or later.
###
### Copyright (C) 2024-2026, ALT Linux Team

###################
### Main script ###
###################

# Safety first
set -o errexit
set -o noglob
set -o nounset
set -o errtrace
#
umask 0022
export TMPDIR="${TMPDIR:-/tmp}"

# Full path to this script
# shellcheck disable=SC2155
readonly scriptname="$(realpath -- "$0")"

# Executable file name
readonly progname="${scriptname##*/}"

# Supplemental sources
readonly libdir="/usr/libexec/$progname"

# Testing results
readonly TEST_PASSED=0
readonly TEST_ALLOWED=0
readonly TEST_FAILED=128
readonly TEST_SKIPPED=129
readonly TEST_BLOCKED=130
readonly TEST_RUNNING=131

# Bootstrapping
. "$libdir"/defaults.sh
[ ! -s "/etc/$progname.conf" ] ||
	. "/etc/$progname.conf"
. "$libdir"/internal.sh
. "$libdir"/version.sh
. "$libdir"/common.sh
. "$libdir"/parser.sh

# Unrewritable via settings.ini
retestno=

# Catching unexpected errors
trap 'unexpected_error "$LINENO" "${BASH_SOURCE[0]}"' ERR

# Entry point
nls_locale_setup
parse_cmdline "$@"

# User-defined settings
[ ! -s "${homedir:-$HOME}/.config/$progname.conf" ] ||
	. "${homedir:-$HOME}/.config/$progname.conf"
setup_console

# Testing methodology
helpfile="/usr/share/doc/$progname-doc-$PCTEST_VERSION/html/$progname.html"
[ -r "$helpfile" ] ||
	helpfile=
usertype=

# Default working directory
lastdir="${homedir:-$HOME}/PC-TEST"
workdir="${repodate:-$(date '+%Y-%m-%d')}"
workdir="${homedir:-$HOME}/.local/share/$progname/$workdir"

# Determining launch mode
case "$launchmode" in
"auto")	# For one day we may not think about launch modes
	if [ -L "$lastdir" ] &&
	   [ -s "$lastdir/$progname.log" ] &&
	   [ -f "$lastdir"/STATE/start.txt ] &&
	   [ "$(realpath -- "$lastdir")" = "$(realpath -- "$workdir")" ]
	then
		if [ -s "$lastdir"/STATE/STEP ]; then
			launchmode="continue"
		elif [ ! -f "$lastdir"/STATE/STEP ] &&
		     [ ! -s "$lastdir"/STATE/start.txt ] &&
		     [ ! -f "$lastdir"/STATE/finish.txt ]
		then
			launchmode=finish
		else
			launchmode=start
		fi
	else
		launchmode=start
	fi
	;;

"continue")
	if [ -L "$lastdir" ] &&
	   [ -s "$lastdir"/STATE/STEP ] &&
	   [ -s "$lastdir/$progname.log" ] &&
	   [ -f "$lastdir"/STATE/start.txt ]
	then
		workdir="$(realpath -- "$lastdir")"
	else
		usertype="continue"
		launchmode=start
	fi
	;;

"finish")
	if [ -L "$lastdir" ] &&
	   [ ! -f "$lastdir"/STATE/STEP ] &&
	   [ -s "$lastdir/$progname.log" ] &&
	   [ -f "$lastdir"/STATE/start.txt ] &&
	   [ ! -s "$lastdir"/STATE/start.txt ] &&
	   [ ! -f "$lastdir"/STATE/finish.txt ]
	then
		workdir="$(realpath -- "$lastdir")"
	else
		usertype=finish
		launchmode=start
	fi
	;;

"retest")
	if [ -L "$lastdir" ] &&
	   [ ! -d "$lastdir"/STATE ] &&
	   [ -s "$lastdir"/RESULTS ] &&
	   [ -s "$lastdir"/settings.ini ] &&
	   [ -s "$lastdir/$progname.log" ] &&
	   grep -qsE "^${retestno}\s" "/var/lib/$progname/numbers.txt"
	then
		workdir="$(realpath -- "$lastdir")"
	else
		testplan="The specified test \'%s\' cannot be retaken at this time."
		fatal F18 "$testplan" "$retestno"
	fi
	;;
esac

# Log files for each testing
logfile="$workdir/$progname.log"
xorglog="$workdir/xorg.log"

# Starting titles
en_name="Starting program"
ru_name="Запуск программы"

# New testing
if [ "$launchmode" = start ]; then
	testplan="${L001-The launch mode \'%s\' has been changed, testing will begin again!}"
	[ -z "$usertype" ] ||
		printf "${CLR_WARN}${testplan}${CLR_NORM}\n" "$usertype"
	testplan="${L002-Before testing, the system and kernel will be updated!}"
	stepname="${L003-Press Ctrl-C to abort or any other key to continue...}"

	if [ -n "$dist_upgrade" ] || [ -n "$update_kernel" ]; then
		printf "${CLR_ERR}${testplan}${CLR_NORM}"
		if [ -z "$batchmode" ]; then
			printf "\n$stepname"
			read -rs -n1 testplan ||:
		fi
		printf "\n\n"
	fi

	rm -rf -- "$workdir" "$lastdir"
	mkdir -p -- "$workdir"/STATE
	ln -snf -- "$workdir" "$lastdir"
	cp -Lf "/var/lib/$progname/start.txt" "$workdir"/STATE/
	head -n1 "/var/lib/$progname/start.txt" |
		cut -f2 >"$workdir"/STATE/STEP
	: >"$workdir"/STATE/RESULTS
	cmd_title "$progname $*" |
		tee -- "$logfile"
	: >"$xorglog"
	draw_title_line "$TEST_PASSED" 5 "$(nls_title)" |
		tee -a -- "$logfile"
	[ "$EUID" = 0 ] ||
		rundir="${XDG_RUNTIME_DIR-}"
	copy_desktop_file
	write_config
elif [ "$launchmode" = retest ]; then
	stepname="$(sed -n -E "s/^${retestno}\s+//p" \
			/var/lib/"$progname"/numbers.txt)"
	testplan="The specified test \'%s\' cannot be retaken at this time."

	. "$workdir"/settings.ini

	[ -n "$stepname" ] ||
		fatal F18 "$testplan" "$retestno"
	[ -s "$libdir/steps/$stepname.sh" ] ||
		fatal F19 "Step script \'%s.sh\' not found." "$stepname"
	mkdir -p -- "$workdir"/STATE
	: >"$workdir"/STATE/start.txt
	cat "/var/lib/$progname/start.txt" "/var/lib/$progname/finish.txt" |
		grep -sE "\s${stepname}$" >"$workdir"/STATE/finish.txt
	printf "%s\n" "$stepname" >"$workdir"/STATE/STEP
	printf "%s\n" "$retestno" >"$workdir"/STATE/NUMBER
	mv -f -- "$workdir"/settings.ini "$workdir"/STATE/
	mv -f -- "$workdir"/RESULTS "$workdir"/STATE/
	cmd_title "$progname $*" |
		tee -a -- "$logfile"
	[ -f "$xorglog" ] ||
		: >"$xorglog"
	draw_title_line "$TEST_PASSED" "$retestno" "$(nls_title)" |
		tee -a -- "$logfile"
	copy_desktop_file

	eval "${stepname}_reset_results() {
		: Do nothing by default
	}"

	. "$libdir/steps/$stepname.sh"

	cd -- "$workdir"/
	${stepname}_reset_results
fi

# Overriding system settings first time
if [ "$launchmode" != start ]; then
	[ ! -s "$workdir"/STATE/settings.ini ] ||
		. "$workdir"/STATE/settings.ini
	nls_config messages
fi

# Second part of testing
if [ "$launchmode" = finish ]; then
	cp -Lf "/var/lib/$progname/finish.txt" "$workdir"/STATE/
	head -n1 "/var/lib/$progname/finish.txt" |
		cut -f2 >"$workdir"/STATE/STEP
	cmd_title "$progname $*" |
		tee -a -- "$logfile"
	copy_desktop_file
fi

# Showing passed steps results and the message about resuming
if [ "$EUID" != 0 ] || [ -z "$username" ]; then
	if [ "$launchmode" != start ]; then
		cd -- "$workdir"/
		show_results
		en_name="Resumption of testing"
		ru_name="Возобновление тестирования"
		[ ! -r "$workdir"/STATE/NUMBER ] && number=5 ||
			number="$(head -n1 -- "$workdir"/STATE/NUMBER).1"
		draw_title_line "$TEST_PASSED" "$number" "$(nls_title)" |
			tee -a -- "$logfile"
	fi

	# Within Xorg or Wayland session only
	if [ -n "${DISPLAY-}${WAYLAND_DISPLAY-}" ]
	then
		# Stopping automatic updates
		( killall -TERM DiscoverNotifier ||:
		  killall -TERM apt-indicator-checker ||:
		  killall -TERM apt-indicator ||:
		  killall -TERM discover ||:
		) &>/dev/null

		# Enabling showing OSD in MATE
		if [ "${XDG_CURRENT_DESKTOP-}" = MATE ]; then
			usertype=org.mate.SettingsDaemon.plugins.media-keys
			spawn gsettings set "$usertype" enable-osd true ||:
		fi
	fi
fi

# Main loop
while :; do
	cd -- "$workdir"/
	rm -f REBOOT.txt
	testplan=finish.txt
	[ -f "STATE/$testplan" ] ||
		testplan=start.txt
	[ ! -s STATE/settings.ini ] ||
		. STATE/settings.ini
	[ -s STATE/STEP ] ||
		break
	stepname="$(head -n1 STATE/STEP)"
	[ -n "$stepname" ] && [ -s "$libdir/steps/$stepname.sh" ] ||
		fatal F19 "Step script \'%s.sh\' not found." "$stepname"
	usertype="$(grep -sE "\s${stepname}$" "STATE/$testplan" |cut -f1)"
	[ -n "$usertype" ] ||
		break
	status="$TEST_ALLOWED"

	pre() {
		# Passing a step is allowed by default
		return $TEST_ALLOWED
	}

	if [ "$usertype" = root ] && [ "$EUID" != 0 ]; then
		restart_as_root || exit 1

		. "$libdir/steps/$stepname.sh"
	elif [ "$usertype" = user ] && [ "$EUID" = 0 ]; then
		status="$TEST_BLOCKED"
		rm -f STATE/STATUS

		. "$libdir/steps/$stepname.sh"
	else
		. "$libdir/steps/$stepname.sh"

		printf "%s\n" "${number-5}" >STATE/NUMBER
		rm -f STATE/STATUS
		pre || status="$?"

		if [ "$status" = "$TEST_ALLOWED" ]; then
			if [ "$EUID" = 0 ] && [ -n "$username" ]; then
				rm -rf TMP-ROOT
				mkdir TMP-ROOT
				cd TMP-ROOT/
			fi
			show_test_title
			testcase || status="$?"
		fi

		cd -- "$workdir"/

		if [ "$EUID" = 0 ] && [ -n "$username" ]; then
			if [ -d ./TMP-ROOT ]; then
				chown -R -- "$username":"$username" ./TMP-ROOT
				(set +f; mv -f ./TMP-ROOT/* ./ ||:) 2>/dev/null
				rm -rf ./TMP-ROOT
			fi

			# Sometimes we get a very strange fault at this point
			#
			if [ -d ./STATE ]; then
				printf "%s\n" "$status" >./STATE/STATUS ||:
				chown -- "$username":"$username" \
					  ./STATE/STATUS ./STATE/NUMBER ||:
			fi 2>/dev/null

			exit 0
		fi
	fi

	have_next_step || break
done

# Removing the 'REBOOT' flag
rm -f -- "$workdir"/REBOOT.txt

# Removing the desktop file
remove_desktop_file

# Showing last message
if [ "$testplan" = start.txt ]; then
	status="${L004-The first part of testing is complete!}"
	printf "\n${CLR_OK}${status}${CLR_NORM}\n"
	status="Perform manual testing according to section 10 of the methodology."
	printf "${L005-$status}\n"
	status="${L006-Don\'t forget to run \'@BOLD@\' after testing!}"
	printf "$(bold "$status")\n" "$progname --finish"
else
	stepname="$progname-${workdir##*/}.tar"
	status="${L007-Testing is complete!}"
	printf "\n${CLR_OK}${status}${CLR_NORM}\n"
	status="${L008-Creating the archive \'@BOLD@\'...}"
	printf "$(bold "$status")\n" "$stepname"

	# Creating an archive
	mv -f STATE/RESULTS STATE/settings.ini ./ && rm -rf STATE
	cd .. && tar -cf "$HOME/$stepname" "${workdir##*/}"

	# Moving archive to the server
	if [ -d "/mnt/$progname" ]; then
		testplan="/mnt/$progname/$compname-${workdir##*/}.tar"
		if cp -Lf -- "$HOME/$stepname" "$testplan" 2>/dev/null; then
			status="${L009-Now this archive has been moved to}"
			printf "${status}: \'${CLR_WARN}%s${CLR_NORM}\'.\n" "$testplan"
			rm -f -- "$HOME/$stepname"
		fi
	fi
fi

pause_before_exit

