#!/bin/sh -f

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

UPGRADE_CMD="apt-get dist-upgrade"

CHECK_PROGRESS="/var/cache/alterator/apt-check.progress"
CHECK_STATUS="/var/cache/alterator/apt-check.status"
CHECK_SUMMARY="/var/cache/alterator/apt-check.summary"
CHECK_LOG="/var/cache/alterator/apt-check.log"
CHECK_PID=

CHECK_CMD="apt-get update"

MONITOR_DIR="/var/lib/alterator/rss/"
MONITOR_NORMAL="$MONITOR_DIR/normal/apt-upgrade.xml"
MONITOR_WARNING="$MONITOR_DIR/warning/apt-upgrade.xml"
MONITOR_CRITICAL="$MONITOR_DIR/critical/apt-upgrade.xml"

[ -d "$MONITOR_DIR" ] || mkdir -p "$MONITOR_DIR/normal" "$MONITOR_DIR/warning" "$MONITOR_DIR/critical"

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

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

check_cleanup()
{
    rm -rf "$CHECK_PROGRESS" "$CHECK_STATUS" "$CHECK_SUMMARY" 2>/dev/null
}

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

exit_handler()
{
    local rc=$?
    trap - EXIT
    [ -n "$UPGRADE_PID" ] && kill "$UPGRADE_PID" 2>/dev/null
    [ -n "$CHECK_PID" ] && kill "$CHECK_PID" 2>/dev/null
    upgrade_cleanup
    check_cleanup
    exit $rc
}

trap exit_handler HUP INT QUIT TERM EXIT

#### upgrade system

upgrade_parse()
{
    local line=
    local total=0
    local current=0

    echo "`_ "Preparing..."`" > "$UPGRADE_STATUS"
    while read -r line;do
	case "$line" in
	    #status collection
	    apt-get:finish:*)
		if [ "${line##*:}" -eq 0 ];then
		    echo "110" >"$UPGRADE_PROGRESS"
		    echo "`_ "Done..."`" > "$UPGRADE_STATUS"
		else
		    echo "-10" >"$UPGRADE_PROGRESS"
		    echo "`_ "Fatal error"`" > "$UPGRADE_STATUS"
		fi
		;;
	    apt-get:status:upgrade:*|apt-get:status:install:*)
		total=$(($total + ${line##*:}))
		;;
	    #rpm progress
	    Preparing*)
		echo "`_ "Installing packages..."`" >"$UPGRADE_STATUS"
		current=0
		;;
	    #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_upgrade()
{
    (LANG=C $UPGRADE_CMD -y --simple-output 2>"$UPGRADE_ERROR"
     rc="$?"
     [ "$rc" -eq 0 ] && rm -rf "$CHECK_SUMMARY"
     printf 'apt-get:finish:%s\n' "$rc")|
        tee "$UPGRADE_LOG"|
	upgrade_parse

    rm -rf "$UPGRADE_LOCK"
}

#### check for updates

check_parse_out()
{
    printf '\n%s:\n%s\n' \
	"$1" \
	"$2" >>"$CHECK_SUMMARY"
}

check_parse()
{
    echo "0" >"$CHECK_PROGRESS"
    while read -r line;do
	case "$line" in
	    #status collection
	    apt-get:finish:*)
		if [ "${line##*:}" -eq 0 ];then
		    echo "110" >"$CHECK_PROGRESS"
		else
		    echo "-10" >"$CHECK_PROGRESS"
		fi
		return "${line##*:}"
		;;
	    apt-get:install-list:*)
		check_parse_out "`_ "Packages to install"`" "${line##*:}"
		;;
	    apt-get:extra-list:*)
		check_parse_out "`_ "Additional packages to install"`" "${line##*:}"
		;;
	    apt-get:upgrade-list:*)
		check_parse_out "`_ "Packages to upgrade"`" "${line##*:}"
		;;
	    apt-get:remove-list:*)
		check_parse_out "`_ "Packages to REMOVE"`" "${line##*:}"
		;;
	    apt-get:replace-list:*)
		check_parse_out "`_ "Packages will be REPLACED"`" "${line##*:}" 
		;;
	    apt-get:keep-list:*)
		check_parse_out "`_ "Packages have been kept back"`" "${line##*:}" 
		;;
	esac
    done
}

run_check()
{
    ( echo "`_ "Getting indexes..."`">"$CHECK_STATUS" &&
      LANG=C $CHECK_CMD --simple-output 2>"$UPGRADE_ERROR" &&
      echo "`_ "Calculating updates..."`">"$CHECK_STATUS" &&
      LANG=C $UPGRADE_CMD --simple-output --dry-run 2>>"$UPGRADE_ERROR"
      printf "apt-get:finish:%s\n" "$?")|
        tee "$CHECK_LOG"|
        check_parse
}

apt_check()
{
      run_check

      if [ "$?" -eq 0 ]; then
          [ -f "$CHECK_SUMMARY" ] || echo "`_ "no updates available"`" >"$CHECK_SUMMARY"
      fi

    rm -rf "$UPGRADE_LOCK"
}

#### monitoring

rss_title()
{
    printf '<title>%s:%s</title>\n' "$(LANG=C date +'%F %R')"  "$1"
}

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

rss_description()
{
    echo '<description>'
    rss_quote $*
    echo '</description>'
}

monitor_cleanup1()
{
    rm -rf "$MONITOR_NORMAL" "$MONITOR_CRITICAL" 2>/dev/null
    rss_title "checking for updates" > "$MONITOR_WARNING"
    echo "checking for updates"| rss_description >> "$MONITOR_WARNING"
}

monitor_cleanup2()
{
    rm -rf "$MONITOR_WARNING" 2>/dev/null
}

apt_monitor()
{ 
    monitor_cleanup1 #setup temporary message
    run_check
    local rc="$?"
    monitor_cleanup2 #report is ready, full cleanup
     
    if [ "$rc" -eq "0" ];then
	if [ -f "$CHECK_SUMMARY" ] ;then
	    rss_title "updates are available" >"$MONITOR_WARNING"
	    rss_description "$CHECK_SUMMARY" >>"$MONITOR_WARNING"
	else
	    rss_title "no updates available" >"$MONITOR_NORMAL"
	    echo "no updates available" | rss_description >> "$MONITOR_NORMAL"
	fi
    else
	rss_title "update error" >"$MONITOR_CRITICAL"
	rss_description "$UPGRADE_ERROR" >> "$MONITOR_CRITICAL"
    fi
}

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

#initial actions
upgrade_cleanup
check_cleanup

on_message()
{
	case "$in_action" in
		monitor)
		    while ! mkdir -- "$UPGRADE_LOCK" >/dev/null 2>&1; do sleep 1;done
		    apt_monitor
		    echo '()'
		    ;;
		write)
		    echo '('
		    if [ -n "$in_upgrade" ]; then
			if [ -d "$UPGRADE_LOCK" ]; then
			    printf 'error "%s"' "`_ "upgrade or check already in progress"`"
			else
			    upgrade_cleanup
		    	    mkdir -p "$UPGRADE_LOCK"
			    apt_upgrade &
			    UPGRADE_PID="$!"
			fi
		    elif [ -n "$in_check" ]; then
			if [ -d "$UPGRADE_LOCK" ]; then
			    printf 'error "%s"' "`_ "upgrade or check already in progress"`"
			else
			    check_cleanup
		    	    mkdir -p "$UPGRADE_LOCK"
			    echo "`_ "Preparing..."`" > "$CHECK_STATUS"
			    apt_check &
			    CHECK_PID="$!"
			fi
		    fi
		    echo ')'
		    ;;
		read)
		    echo '('
		    if [ "$in__objects" = "/" ];then
			if [ -f "$CHECK_SUMMARY" ]; then
			    printf ' summary "%s"' "$(cat "$CHECK_SUMMARY")"
			else
			    printf ' summary "%s"' "`_ "no information available"`"
			fi
		    elif [ "$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" = "check-status" ];then
			printf ' status "%s"' "$(read_value "$CHECK_STATUS")"
		    elif [ "$in__objects" = "upgrade-error" ];then
			printf ' error-message "%s"' "$(cat "$UPGRADE_ERROR")"
		    fi
		    echo ')'
		    ;;
		*)
		    echo '#f'
		    ;;
	esac
}

message_loop
