#!/bin/sh

local tempfile=/tmp/remote-upgrade.img
local D2='\([0-9]\{2\}\)'
local D4='\([0-9]\{4\}\)'
local NL='
'

find_architecture()
{
	local ifs="$IFS"; IFS="-"
	set -- $(opkg list_installed kernel)
	IFS="$ifs"

	echo "$3"
}

find_image()
{
	case "$1" in
		atheros)
			echo "openwrt-atheros-combined.squashfs.img"
		;;
		ar71xx)
			echo "openwrt-ar71xx-combined.squashfs.img"
		;;
		brcm)
			echo "openwrt-brcm-2.4-squashfs.trx"
		;;
	esac
}

check_image()
{
	local file; for file in /lib/upgrade/*.sh; do . $file; done
	if platform_check_image "$1" >/dev/null 2>/dev/null; then
		return 0
	fi
	return 1
}

find_remote_checksum()
{
	wget -qO- ${1%/*}/md5sums 2>/dev/null | \
		sed -ne '/'$2'/ { s/ .*//p }'
}

find_local_checksum()
{
	set -- $(md5sum "$tempfile")
	echo $1
}

find_remote_info()
{
	wget -qO- "${1%/*}/VERSION.txt" 2>/dev/null
}

find_remote_version()
{
	find_remote_info "$1" | \
		sed -ne "s!.*$D4/$D2/$D2 $D2:$D2.*!\\1\\2\\3\\4\\5!p;t"
}

find_local_version()
{
	if [ -f /rom/etc/banner ]; then
		sed -ne "s!.*$D4/$D2/$D2 $D2:$D2.*!\\1\\2\\3\\4\\5!p;t" \
			/rom/etc/banner
	else
		date +"%Y%m%d%H%M" -r /bin/sh
	fi
}

stop_service()
{
	[ -x /etc/init.d/$1 ] && {
		echo -n "Stopping service $1 ... "
		/etc/init.d/$1 stop >/dev/null 2>/dev/null
		echo "done"
	}
}

do_wait()
{
	if [ ${1:-0} -gt 0 ]; then
		echo -n "${2:-Waiting} "
		for i in $(seq 1 $1); do
			printf "%-2dseconds" $(($1-$i))
			sleep 1
			echo -en "\b\b\b\b\b\b\b\b\b"
		done
		echo "${NL}"
	fi
}

version_compare()
{
	local v1="$1"
	local v2="$2"

	while [ -n "$v1" -o -n "$v2" ]; do
		if [ -z "${v2:0:4}" -o "${v1:0:4}" -gt "${v2:0:4}" ]; then
			return 1
		elif [ -z "${v1:0:4}" -o "${v1:0:4}" -lt "${v2:0:4}" ]; then
			return 2
		fi

		v1="${v1:4}"
		v2="${v2:4}"
	done

	return 0
}

usage()
{
	cat <<EOT

Usage:
  remote-update -h
  remote-update [-u <update url>] -c
  remote-update [-v] [-y] [-u <update url>] -w
  remote-update [-d] [-n] [-v] [-y] [-s <sleep seconds>] [-u <update url>]

Actions:
  -h    Display this help message and exit.
  -c    Check for firmware update and exit.
  -w    Fetch image and exit, do not perform flash write.

Options:
  -d    Do not detach from terminal.
  -n    Do not backup configuration.
  -v    Skip verification of downloaded image.
  -y    Assume defaults for all questions.

  -s <seconds>
    Sleep given amount of seconds before starting flash write.
    If ommitted and '-y' is not used, 5 seconds are assumed.

  -u <url>
    Fetch firmware image from given url. A file "md5sums" is expected
    in the same remote directory. If there is no such file, use -v to
    suppress verification.

EOT

	exit 1
}


while getopts "s:u:cdnvwyh" flag; do
	case $flag in
		s) sleeptime="$OPTARG";;
		u) updateurl="$OPTARG";;
		c) checkupdate=1;;
		d) nodetach=1;;
		n) nobackup=1;;
		v) noverify=1;;
		w) noflash=1;;
		y) noquestions=1;;
		*) usage;;
	esac
done


local image_url="$updateurl"
local image_name="${image_url##*/}"

[ -z "$image_url" ] && {
	local arch=$(find_architecture)
	local image=$(find_image "$arch")
	local repo=$(uci get freifunk.upgrade.repository 2>/dev/null)
	repo=${repo:-$(uci get system.upgrade.repository 2>/dev/null)}

	[ -z "$arch" ] && {
		echo "Can not determine the current architecture."
		exit 1
	}

	[ -z "$repo" ] && {
		echo "No repository configured in 'system.upgrade.repository'."
		echo "Use the '-u' flag to specify an image location."
		exit 1
	}

	[ -z "$image" ] && {
		echo "No suitable image for the '$arch' architecture."
		echo "Your platform is not supported."
		exit 1
	}

	echo "Architecture: $arch"
	echo "Repository:   $repo"

	image_name="$image"
	image_url="${repo%/}/$arch/$image"
}


if [ "$checkupdate" = 1 ]; then
	local v1=$(find_local_version)
	local v2=$(find_remote_version "$image_url")

	[ -n "$v1" -a -n "$v2" ] && {
		version_compare "$v1" "$v2"
		[ $? == 2 ] && {
			echo "Update available!${NL}Local:  $v1${NL}Remote: $v2${NL}--"
			find_remote_info "$image_url"
			exit 0
		} || {
			echo "Local version $v1 is up to date"
			exit 2
		}
	} || {
		echo "No remote time stamp found."
		exit 1
	}
else
	if [ "$noquestions" != 1 ]; then
		echo -n "${NL}About to download $image_name. Continue? [y] "
		read answer
		case "$answer" in
			[nN]) exit 1;;
		esac
	fi

	echo -n "Downloading $image_name ... "
	rm -f $tempfile
	wget -qO $tempfile "$image_url" 2>/dev/null
	[ $? == 0 ] && echo done || {
		echo failed
		rm -f $tempfile
		exit 1
	}

	if [ "$noverify" != 1 ]; then
		echo -n "Verifying $image_name ... "

		local md5_remote=$(find_remote_checksum "$image_url" "$image_name")
		local md5_local=$(find_local_checksum)

		check_image "$tempfile"
		local image_ok=$?

		if [ $image_ok = 0 -a -n "$md5_remote" -a -n "$md5_local" -a "$md5_remote" = "$md5_local" ]; then
			echo "done"
		else
			if [ $image_ok != 0 ]; then
				echo "unsupported image type"
			else
				echo "checksum mismatch! (local:${md5_local:-(none)} remote:${md5_remote:-(none)})"
			fi

			local answer=n
			if [ "$noquestions" != 1 ]; then
				echo -n "${NL}Verification failed. Continue anyway? [n] "
				read answer
			fi

			case "$answer" in
				[yYjJ]*) : ;;
				*)
					echo "Aborting."
					rm -f $tempfile
					exit 1
				;;
			esac
		fi
	fi

	if [ "$noflash" != 1 ]; then
		if [ -f "$tempfile" ]; then
			if [ "$noquestions" == 1 ]; then
				do_wait ${sleeptime:-5} "${NL}About to start flashing, hit <Ctrl-C> to abort!${NL}${NL}Starting in"
			else
				if [ -z "$nobackup" ]; then
					echo -n "${NL}Keep configuration files? [y] "
					read answer
					case "$answer" in
						[nN]) nobackup=1;;
					esac
				fi

				echo -n "${NL}About to start flashing!${NL}Hit <Enter> to continue or <Ctrl-C> to abort.${NL}"
				read answer
			fi

			for s in lucid collectd; do stop_service $s; done

			if [ "$nodetach" != 1 ]; then
				echo -n "Starting sysupgrade in background ... "
				/bin/busybox start-stop-daemon -S -b -x /sbin/sysupgrade -- ${nobackup:+-n} "$tempfile"
				echo "done"
			else
				echo "Executing sysupgrade ... "
				exec /sbin/sysupgrade ${nobackup:+-n} "$tempfile"
			fi
		else
			echo "No upgrade image found!"
			exit 1
		fi
	else
		echo "Image saved in '$tempfile'"
	fi
fi
