#!/bin/sh
#
# slitaz-installer - dialog frontend to tazinst, the SliTaz installer.
#
# Steps, values and checks all come from the tazinst frontend protocol
# (doc/protocol.txt): this script only displays them, so a setting added
# to tazinst shows up here without any change.
#
# (C) 2007-2026 SliTaz - GNU General Public License v3.
#
# Authors : Christophe Lincoln <pankso@slitaz.org>
#           Dominique Corbex <domcox@slitaz.org>
#

. /lib/libtaz.sh
export TEXTDOMAIN='slitaz-installer'

VERSION="4.0"
DIALOG="${DIALOG:-dialog}"
TAZINST="${TAZINST:-tazinst}"
BACKTITLE="SliTaz GNU/Linux installer"
TAB="$(printf '\t')"

#--------------
# msgs section
#--------------

SUMMARY_MSG="$(_ "Installation settings summary and last chance to \
cancel or restart all installation steps.")\n
\Z2$(_ 'Go and install SliTaz?')\Zn\n"

END_OF_INSTALL_MSG="\n$(_ "Installation is now finished, you can exit \
the installer or reboot on your new SliTaz GNU/Linux operating system.")"

EMPTY_MENU_MSG="\n$(_ 'Sorry, no device, nor file found or available.')"

#-----------------
# tazinst section
#-----------------

# run tazinst on our install file
tz()
{
	"$TAZINST" "$@" "$INSTALL_FILE"
}

# read the description of the settings, again after each change:
# the active steps and value types follow the values
describe()
{
	DESC="$(tz describe)"
}

# print a field of the description of a setting
field()
{
	printf "%s\n" "$DESC" | awk -F"$TAB" -v key="$1" -v n="$2" '$1 == key {print $n}'
}

# active steps, in order
steps()
{
	printf "%s\n" "$DESC" | awk -F"$TAB" '$4 == 1 {print $1}'
	echo "summary"
}

# title of a step: its number and label
step_title()
{
	steps | awk -v key="$1" -v label="$2" -v t_step="$(gettext 'Step %d/%d')" '
		$0 == key { n = NR }
		END { printf " " t_step ": %s ", n, NR, label }'
}

# print the step after (up) or before (back) a step
move()
{
	steps | awk -v key="$1" -v way="$2" '
		{ step[NR] = $0; if ($0 == key) n = NR }
		END {
			if (way == "up") n++
			else if (n > 1) n--
			print step[n ? n : 1]
		}'
}

#----------------
# dialog section
#----------------

# run dialog and print its answer
dlg()
{
	"$DIALOG" --clear --colors --backtitle "$BACKTITLE" "$@" 3>&1 1>&2 2>&3
}

clear_screen()
{
	printf '\033[H\033[2J'
}

msgbox()
{
	dlg --title " $1 " --msgbox "\n$2" 14 70
}

# explanation of a step, from tazinst: help, then warning in red
step_text()
{
	local warning="$(field $1 8)"
	printf "\n%s\n" "$(field $1 7)"
	[ -n "$warning" ] && printf "\n\\Z1%s\\Zn\n" "$warning"
}

# pick a value in the options of a setting
# '-' stands for an empty value, '+' for a file name to type
ask_menu()
{
	local key="$1" type="$2" label="$3" value="$4" text title line tag answer found
	text="$(step_text "$key")"
	title="$(step_title "$key" "$label")"
	set --
	while IFS= read -r line; do
		[ -n "$line" ] || continue
		tag="${line%%$TAB*}"
		[ "$tag" = "$value" ] && found="yes"
		set -- "$@" "${tag:--}" "${line#*$TAB}"
	done <<EOT
$(tz options "$key")
EOT
	# keep a file typed before, tazinst only finds the usual places
	if [ "$type" = "file" ]; then
		[ -n "$value" ] && [ -z "$found" ] && set -- "$value" "$value" "$@"
		set -- "$@" "+" "$(_ 'Other file...')"
	fi
	if [ "$#" = 0 ]; then
		msgbox "$label" "$EMPTY_MENU_MSG"
		return 1
	fi
	answer="$(dlg --title "$title" \
		--ok-label "$(_ 'Next')" --cancel-label "$(_ 'Back')" \
		--default-item "${value:--}" --no-tags \
		--menu "$text" 20 76 8 "$@")" || return 1
	case "$answer" in
		-) answer="" ;;
		+) answer="$(dlg --title "$title" \
			--ok-label "$(_ 'Next')" --cancel-label "$(_ 'Back')" \
			--inputbox "$text" 16 70 "$value")" || return 1 ;;
	esac
	printf "%s" "$answer"
}

# ask for a setting: 0 go on, 1 go back, 2 ask again
ask_step()
{
	local key="$1" type label value title answer check status msg
	type="$(field $key 2)"
	value="$(field $key 5)"
	label="$(field $key 6)"
	title="$(step_title "$key" "$label")"
	case "$type" in
		choice|partition|file|bool)
			answer="$(ask_menu "$key" "$type" "$label" "$value")" || return 1 ;;
		text)
			answer="$(dlg --title "$title" \
				--ok-label "$(_ 'Next')" --cancel-label "$(_ 'Back')" \
				--inputbox "$(step_text $key)" 18 70 "$value")" || return 1 ;;
		password)
			answer="$(dlg --title "$title" --insecure \
				--ok-label "$(_ 'Next')" --cancel-label "$(_ 'Back')" \
				--passwordbox "$(step_text $key)" 18 70 "$value")" || return 1 ;;
		*)
			return 0 ;;
	esac
	tz set "$key" "$answer" > /dev/null 2>&1
	check="$(tz --machine check "$key")"
	status="$(printf "%s" "$check" | cut -f2)"
	msg="$(printf "%s" "$check" | cut -f3)"
	case "$status" in
		error)
			msgbox "$label" "$msg"
			return 2 ;;
		warning)
			msgbox "$label" "$msg" ;;
	esac
	return 0
}

# plan of the install, in words (gettext keeps the %s for awk)
summary_text()
{
	local mode="$(tz get mode)"
	tz plan | awk -F"$TAB" \
		-v root="$(tz get root_uuid)" \
		-v mode="$(tz options mode | awk -F"$TAB" -v m="$mode" '$1 == m {print $2}')" \
		-v t_mode="$(gettext 'Mode: %s')" \
		-v t_media="$(gettext 'From media: %s')" \
		-v t_disk="$(gettext 'To the disk: %s')" \
		-v t_format="$(gettext '(Formatting as %s)')" \
		-v t_noformat="$(gettext '(No formatting)')" \
		-v t_home="$(gettext 'Separate /home is: %s')" \
		-v t_nohomeformat="$(gettext '(No /home formatting)')" \
		-v t_hostname="$(gettext 'Hostname: %s')" \
		-v t_user="$(gettext 'User login: %s')" \
		-v t_boot="$(gettext 'Bootloader: installed')" \
		-v t_noboot="$(gettext 'No bootloader installed')" \
		-v t_winboot="$(gettext ', with Windows dual-boot')" '
		$1 == "mode" { printf "\n" t_mode "\n", mode }
		$1 == "source" {
			printf t_media, $2
			if ($3 != "") printf " (%s)", $3
			printf "\n" }
		$1 == "format" && $2 == root { printf t_disk " " t_format "\n", $2, $3 }
		$1 == "format" && $2 != root { homeformat = $3 }
		$1 == "clean" || $1 == "upgrade" { printf t_disk " " t_noformat "\n", $2 }
		$1 == "home" {
			printf t_home " ", $2
			if (homeformat != "") printf t_format "\n", homeformat
			else print t_nohomeformat }
		$1 == "hostname" { printf t_hostname "\n", $2 }
		$1 == "user" { printf t_user "\n", $2 }
		$1 == "bootloader" { boot = 1; printf "%s (%s: %s)", t_boot, $2, $3 }
		$1 == "winboot" { printf "%s", t_winboot }
		END { if (boot) print ""; else print t_noboot }'
}

# check all settings and go to the first wrong one
check_all()
{
	local wrong="$(tz --machine check "" | awk -F"$TAB" '$2 == "error"' | sed q)"
	[ -n "$wrong" ] || return 0
	msgbox "$(field ${wrong%%$TAB*} 6)" "$(printf "%s" "$wrong" | cut -f3)"
	STEP="${wrong%%$TAB*}"
	return 1
}

# summary and last chance to cancel: 0 install, 1 go back
summary()
{
	check_all || return 1
	dlg --title "$(step_title summary "$(_ 'Summary')")" \
		--yes-label "$(_ 'Install')" --no-label "$(_ 'Cancel')" \
		--extra-button --extra-label "$(_ 'Back')" \
		--yesno "$SUMMARY_MSG$(summary_text)" 20 76
	case "$?" in
		0) return 0 ;;
		1) clear_screen; _ 'SliTaz install cancelled.'; exit 1 ;;
		*) STEP="$(move summary back)"; return 1 ;;
	esac
}

# run the install with a progress gauge
install()
{
	local errors="$(mktemp)"
	tz --machine execute | awk -F"$TAB" -v errors="$errors" '
		$1 == "progress" { pct = $2; step = $3
			printf "XXX\n%d\n%s\nXXX\n", pct, step; fflush() }
		$1 == "info" {
			printf "XXX\n%d\n%s\n\n%s\nXXX\n", pct, step, $2; fflush() }
		$1 == "error" { print $3 > errors }' | \
	"$DIALOG" --backtitle "$BACKTITLE" --title " $(_ 'SliTaz Installer') " \
		--gauge "$(_ 'Installing...')" 12 76 0
	if [ -s "$errors" ]; then
		msgbox "$(_ 'Process not completed')" \
			"$(cat "$errors")\n\n$(_ 'Log file: %s' '/var/log/tazinst.log')"
		rm -f "$errors"
		return 1
	fi
	rm -f "$errors"
	dlg --title " $(_ 'Installation complete') " \
		--yes-label "$(_ 'Exit')" --no-label "$(_ 'Reboot')" \
		--yesno "$END_OF_INSTALL_MSG" 12 70
	[ "$?" = 1 ] && { reboot || reboot -f; }
	return 0
}

#--------------
# main section
#--------------

case "$1" in
	-h|--help|usage)
		_ 'Usage: %s [install file]' "$(basename $0)"
		exit 0 ;;
esac

check_root "$@"

# a given install file is kept, the default one holds passwords
if [ -n "$1" ]; then
	INSTALL_FILE="$1"
	[ -s "$INSTALL_FILE" ] || tz new > /dev/null
else
	INSTALL_FILE="/tmp/slitaz-installer.rc"
	trap 'rm -f "$INSTALL_FILE"' EXIT
	trap 'exit 130' INT TERM
	rm -f "$INSTALL_FILE"
	tz new > /dev/null
fi
if ! describe 2> /dev/null || [ -z "$DESC" ]; then
	_ 'This installer needs tazinst 4.0 or later.'
	exit 2
fi

# after a failed install, back to the summary with all settings kept
STEP="$(steps | sed q)"
while true; do
	if [ "$STEP" = "summary" ]; then
		summary && install && break
		describe
		continue
	fi
	ask_step "$STEP"
	way="$?"
	describe
	case "$way" in
		0) STEP="$(move $STEP up)" ;;
		1) STEP="$(move $STEP back)" ;;
	esac
done

clear_screen
