#!/bin/sh

. /usr/share/alterator/build/backend3.sh

template_dir="/var/www/html/fbi/aptgroups"
apt_profile="/etc/alterator/apt.d/install3"
group_prefix="installer-group-"

UPGRADE_PROGRESS="/var/cache/alterator/aptgroups.progress"
UPGRADE_STATUS="/var/cache/alterator/aptgroups.status"
UPGRADE_ERROR="/var/cache/alterator/aptgroups.error"
UPGRADE_LOG="/var/cache/alterator/aptgroups.log"
UPGRADE_LOCK="/var/cache/alterator/aptgroups.lock"
UPGRADE_PID=

_() {
	LANG=${in_language%%;*}.utf8 gettext "alterator-aptgroups" "$1"
}

upgrade_cleanup() {
	rm -rf "$UPGRADE_PROGRESS" "$UPGRADE_STATUS" "$UPGRADE_LOCK" 2>/dev/null
}

read_value() {
	[ -f "$1" ] && head -n1 "$1"
}

#### upgrade system
upgrade_parse() {
	local line=
	local total=0
	local current=0
	local mode=install

	echo "`_ "Preparing..."`" > "$UPGRADE_STATUS"
	while read -r line;do
		case "$line" in
			#status collection
			apt-get:finish:*)
				if [ "${line##*:}" -eq 0 ];then
					echo "100" >"$UPGRADE_PROGRESS"
					sleep 2
					echo "`_ "Done..."`" > "$UPGRADE_STATUS"
				else
					echo "-10" >"$UPGRADE_PROGRESS"
					echo "`_ "Fatal error"`" > "$UPGRADE_STATUS"
				fi
			;;
			apt-get:status:upgrade:*|apt-get:status:install:*|apt-get:status:remove:*)
				total=$(($total + ${line##*:}))
				if [ -z "${line##apt-get:status:remove:*}" -a "${line##*:}" -gt 0 ]; then
					mode=remove
				fi
			;;
			#rpm progress
			Preparing*)
				current=0
				echo 0 > "$UPGRADE_PROGRESS"
				case "$mode" in
					install) echo "`_ "Installing packages..."`" ;;
					remove)
						echo 50 > "$UPGRADE_PROGRESS"
						echo "`_ "Removing packages..."`"   ;;
				esac >"$UPGRADE_STATUS"
			;;
			#download
			Get:[0-9]*)
				echo "`_ "Acquiring packages..."`">"$UPGRADE_STATUS"
				echo $(( ($current * 100) / $total )) >"$UPGRADE_PROGRESS"
				current=$(( $current + 1 ))
			;;
			*)
			#rpm progress
				if echo "$line"|egrep -qs "^([^[:blank:]#]+)[[:space:]]*#.+";then
					echo $(( ($current * 100) / $total )) > "$UPGRADE_PROGRESS"
					current=$(( $current + 1 ))
				fi
			;;
		esac
	done
}

apt_command() {
	(LANG=C $@ 2>"$UPGRADE_ERROR"
	 rc="$?"
	 printf 'apt-get:finish:%s\n' "$rc")|
    	    tee "$UPGRADE_LOG"|
	    upgrade_parse

	rm -rf "$UPGRADE_LOCK"
}

#######################################################################
# Html helpers

template() {
	local tmpl="$template_dir/$1"
	shift
	[ -s "$tmpl" ] || return 0
	sed -n -e "1,/@$1@/{ s/@$1@//; p }" "$tmpl"
	eval "$*"
	sed -n -e "/@$1@/,\${ s/@$1@//; p }" "$tmpl"
}

html_quote() {
	sed -r \
		-e 's,&,\&amp;,g' \
		-e 's,",\&quot;,g' \
		-e 's,>,\&gt;,g;' \
		-e 's,<,\&lt;,g;' $*
}

html_tag() {
	sed "1 s,.*,<$1>&,
	     $ s,.*,&</${1%% *}>,"
}

#######################################################################
error() {
	printf '(error "%s")' "$*"
}

getprofile() {
	sed -e 's/[()]//g' -e '/^[[:space:]]*$/d' -- "$apt_profile"
}

workdir=
exit_handler() {
	local rc=$?
	trap - EXIT
	[ ! -d "$workdir" ] || rm -rf -- "$workdir"
	[ -n "$UPGRADE_PID" ] && kill "$UPGRADE_PID" 2>/dev/null
	upgrade_cleanup
	exit $rc
}

### List
uilist() {
	local c=
	! rpmquery -- "$1" >/dev/null 2>&1 || c=' checked="yes"'

	{
	    printf '<input type="checkbox" name="%s" %s/>' "$i" "$c"	| html_tag "td"
	    printf '%s\n' "$3" | html_quote				| html_tag "td"
	}								| html_tag "tr"
}

names() {
	printf '%s %s\n' "$i" "$1"
}

summary() {
	printf '%s %s\n' "$1" "$3"
}

installed() {
	! rpmquery -- "$1" >/dev/null 2>&1 || printf ' %s ' "$i"
}

listgroups() {
	local line i=0
	getprofile |
	while read line; do
		eval "$1" $line
		i=$(($i + 1))
	done
}

to_names() {
	local i name args=" $* "
	listgroups names |
	while read i name; do
		[ -n "${args##* $i *}" ] || printf %s\\n "$name"
	done
}

to_summary() {
	local i name args=" $* "
	listgroups summary |
	while read name summary; do
		[ -n "${args##* $name *}" ] || printf %s\\n "$summary"
	done
}

### Remove
removegroups() {
	local r pattern=

	rpmquery -a "$group_prefix*" |
		xargs -r rpmquery --qf='[%{REQUIRENAME}\t%{NAME}\n]' -- > installed-groups

	for r in "$@"; do
		pattern="${pattern:+$pattern\\|}$r"
	done

	grep    "[[:space:]]\\($pattern\\)\$" installed-groups |
		cut -f1 |
		sort -uo installed-pkgs

	deplist="$(grep -v "[[:space:]]\\($pattern\\)\$" installed-groups |
		cut -f1 |
		sort -u |
		join -v2 - installed-pkgs |
		grep -v '^rpmlib(')" #"

	apt_command apt-get -y --simple-output --force-yes remove $* $deplist
}

### Install
show_conflicts() {
	[ -n "${args##* $1 *}" ] || [ "$5" = "none" ] || printf '%s %s\n' "$1" "$5"
}


conflictlist() {
	local args=" $* "
	getprofile |
	while read line; do
		eval show_conflicts $line
	done
}

skipspace() {
	printf %s\\n "$*"
}

checkconflicts() {
	local conflicts p
	local install=" $(skipspace $1) "
	local remove=" $(skipspace $2) "
	
	conflictlist "$install" > conflicts

	while read pkg conflicts; do
		for c in $conflicts; do
			[ -n "${remove##* $c *}" ] || continue
	
			if [ -z "${install##* $c *}" ] || rpmquery -- "$c" >/dev/null 2>&1; then
				pkg="$(to_summary "$pkg")"
				c="$(to_summary "$c")"
				error "'$pkg' conflicts with '$c'"
				return 1
			fi
		done
	done < conflicts
}

installgroups() {
	apt_command apt-get -y --simple-output --force-yes install "$@"
}

trap exit_handler HUP INT QUIT TERM EXIT
workdir="$(mktemp -dt "${0##*/}.XXXXXXXXX")"
cd "$workdir"

upgrade_cleanup
groups_num="$(getprofile |wc -l)"
groups_num=$(($groups_num - 1))

installed="$(listgroups installed)"

on_message()
{
	case "$in_action" in
	    	constraints|list)
			echo '()'
			;;
		write)
			if [ -d "$UPGRADE_LOCK" ]; then
				error "`_ "install or remove already in progress"`"
				return 0
			fi

			local i need_remove= need_install=
			installed="$(listgroups installed)"

			for i in `seq 0 $groups_num`; do
				if eval "[ -n \"\$in_$i\" ]"; then
					[ -z "${installed##* $i *}" ] ||
						need_install="$need_install $i"
				else
					[ -n "${installed##* $i *}" ] ||
						need_remove="$need_remove $i"
				fi
			done

			need_remove="$(to_names $need_remove)"
			need_install="$(to_names $need_install)"

			checkconflicts "$need_install" "$need_remove" ||
				return 0

			{
				if [ -n "$need_remove" -o -n "$need_install" ]; then
					upgrade_cleanup
					mkdir -p "$UPGRADE_LOCK"

					if [ -n "$need_remove" ]; then
						echo "### remove: $need_remove" >&2
						removegroups $need_remove
					fi
				
					upgrade_cleanup
					if [ -n "$need_install" ]; then
						echo "### install: $need_install" >&2
						installgroups $need_install
					fi
				
					echo "110" >"$UPGRADE_PROGRESS"
				fi

			} &

			[ -z "$need_remove" -a -z "$need_install" ] ||
				UPGRADE_PID="$!"

			echo '()'
			;;
		read)
			echo '('
			if [ "$in__objects" = "upgrade-status" -o "$in__objects" = "upgrade-status2" ];then
				local progress="$(read_value "$UPGRADE_PROGRESS")"
				[ -n "$progress" ] ||
					progress=0
		    		printf ' progress "%s"' "$progress"
				printf ' status "%s"' "$(read_value "$UPGRADE_STATUS")"

			elif [ "$in__objects" = "upgrade-error" ];then
				printf ' error-message "%s"' "$(cat "$UPGRADE_ERROR")"

			fi
			echo ')'
			;;
		*)
			echo '#f'
			;;
	esac
}

message_loop
