#!/bin/sh

# This script is called by fwinstall which controls logging behavior.
# Default to high verbosity on what is happening to enable troubleshooting the critical firmware update process.
echo "$0 $@"
set -x

#we don't want any errors in here to cancel the script
set +e

USER_BACKUP_FILE="/etc/smart/custom_channels.lst" #list of custom user channels
INSTALL_IN_PROGRESS="/etc/smart/user_channels.bak" #old user channels now being used as install flag
TEMP_CHANNEL_LIST="/etc/smart/temp_channel.lst"

VIPER4_NIGHTLY_CHANNEL_LIST="/etc/smart/v4_nightly.lst"
VIPER4_RC_CHANNEL_LIST="/etc/smart/v4_rc.lst"
VIPER4_RELEASE_CHANNEL_LIST="/etc/smart/v4_release.lst"
VIPER4_DEVELOPMENT_CHANNEL_LIST="/etc/smart/v4_development.lst"
VIPER4_LOCAL_CHANNEL_LIST="/etc/smart/v4_local.lst"
VIPER4_OTA_CHANNEL_LIST="/etc/smart/v4_ota.lst"
VIPER4_OTA_REVERT_CHANNEL_LIST="/etc/smart/v4_ota_revert.lst"

OTA_IPC="/usr/bin/raven/userFiles/softwareUpdates"
CHANNEL_LIST=""

begin_install()
{
	echo "installing" > ${INSTALL_IN_PROGRESS}
}

end_install()
{
	rm -f ${INSTALL_IN_PROGRESS}
}

clean_channel_cache()
{
	rm -rf /var/lib/smart/channels/*
}

start_jetstream()
{
	/etc/init.d/xserver-nodm restart
}

stop_jetstream()
{
	echo -n "Stopping Jetstream"
	killall -9 softwarelauncher
	killall -9 jetstream
	if [ -f /etc/init.d/watchdog ]; then
		/etc/init.d/watchdog stop
	fi
	echo "."
}

backup_user_channels ()
{
	echo -n "Backing up user channels"
	if [ ! -f $USER_BACKUP_FILE ]; then #if the file is there the install must have failed in some manner, don't erase the backup and continue on
		/usr/bin/smart channel --show > $USER_BACKUP_FILE
	fi
	echo "."
}

load_channel_from_file ()
{
	echo -n "Loading Channels from $1"
	/usr/bin/smart channel --add $1 -y > /dev/null
	echo "."
}

remove_channels() 
{
	echo -n "Removing custom channels"
	CHANNELS=`/usr/bin/smart channel --list`
	for channel in $CHANNELS; 
	do
		echo -n "."
		/usr/bin/smart channel --remove $channel -y > /dev/null
	done
	echo "."
}

rebuild_db()
{
		echo "Cleaning Database Locks"
		rm -f /var/lib/rpm/__db*      # if we are resuming an install we cant trust any of our database locks, remove and recreate
		
		echo "Rebuilding Database"
		rpm -v --rebuilddb  #this will take a while
}

verify_db()
{
	echo "Verifying Database..."

	rpm -V rpm-libs &> /dev/null #verify the rpm-libs package is installed and accesable via the database
	if [ $? -ne 0 ]; then
		echo "Error scanning database, beginning recovery"
		rebuild_db
	fi
}


run_update_cache()
{
	echo "Updating System"
	/usr/bin/smart update 
	RET="$?"
	echo "Smart Update Ret:${RET}"
	
	if [ ${RET} -ne 0 ]; then
		echo "Error: Smart Update Failure"
		return ${RET}
	fi
	
	/usr/bin/smart upgrade -y --download
	RET="$?"
	echo "Smart Download Ret:${RET}"
	
	if [ ${RET} -ne 0 ]; then
		echo "Error: Smart Upgrade Download Failure"
		return ${RET}
	fi
	
	/etc/init.d/fwinstall cache
	
	/usr/bin/smart upgrade -y
	RET="$?"
	echo "Smart Upgrade Ret:${RET}"
	
	if [ ${RET} -ne 0 ]; then
		echo "Error: Smart Upgrade Failure"
	
		rebuild_db
		/usr/bin/smart upgrade -y
		
		RET="$?"
		if [ ${RET} -ne 0 ]; then
			echo "Error: Smart Upgrade Failure"
			return ${RET}
		fi
	fi
	
	return 0
}

run_update()
{
	echo "Updating System"
	/usr/bin/smart update 
	RET="$?"
	echo "Smart Update Ret:${RET}"
	
	if [ ${RET} -ne 0 ]; then
		echo "Error: Smart Update Failure"
		return ${RET}
	fi
	
	/usr/bin/smart upgrade -y
	RET="$?"
	echo "Smart Upgrade Ret:${RET}"
	
	if [ ${RET} -ne 0 ]; then
		echo "Error: Smart Upgrade Failure"
	
		rebuild_db
		/usr/bin/smart upgrade -y
		
		RET="$?"
		if [ ${RET} -ne 0 ]; then
			echo "Error: Smart Upgrade Failure"
			return ${RET}
		fi
	fi
	
	return 0
}

install_package()  #if we specify a single package lets not automatically rebuild database, could just be the package doesn't exist
{
	echo "Installing Package"
	/usr/bin/smart update
	/usr/bin/smart install $1 -y
	
	return 0
}

CHANNEL=`echo $1 | awk -F- '{ print $1 }'`
BRANCH=`echo $1 | awk -F- '{ print $2 }'`

case "$CHANNEL" in
	nightly)
	CHANNEL_LIST=$VIPER4_NIGHTLY_CHANNEL_LIST
    ;;
	rc)
	CHANNEL_LIST=$VIPER4_RC_CHANNEL_LIST
    ;;
    release)
	CHANNEL_LIST=$VIPER4_RELEASE_CHANNEL_LIST
	;;
    local)
	CHANNEL_LIST=$VIPER4_LOCAL_CHANNEL_LIST
    ;;
	development)
	CHANNEL_LIST=$VIPER4_DEVELOPMENT_CHANNEL_LIST
	;;
	ota)
	CHANNEL_LIST=$VIPER4_OTA_CHANNEL_LIST
	;;
  *)
    echo "Usage: update_firmware {nightly|rc|release|local|development|ota} [package name]"
	echo "   If no package name is provided all will be updated"
    exit 1
    ;;
esac

cp $CHANNEL_LIST $TEMP_CHANNEL_LIST

if [ $CHANNEL = "ota" ]; then
	if [ -f "${OTA_IPC}/ota_download.url" ]; then
		URL=`cat ${OTA_IPC}/ota_download.url`
		URL="baseurl = ${URL}"
		echo "OTA $URL"
		echo "$URL" >> $TEMP_CHANNEL_LIST
	else
		echo "Error: Missing ota_download.url file"
		exit 1
	fi
else
	sed -i "s/BRANCH/${BRANCH}/g" $TEMP_CHANNEL_LIST
fi

CHANNEL_LIST=$TEMP_CHANNEL_LIST

backup_user_channels
remove_channels
load_channel_from_file $CHANNEL_LIST

#check if we are doing a local install (revert) and have an ota append repo
if [ $CHANNEL = "local" ]; then
	if [ -d /var/lib/smart/ota_temp ]; then
		load_channel_from_file $VIPER4_OTA_REVERT_CHANNEL_LIST
	fi
fi

clean_channel_cache		#this causes a redownload of data... doing it every time for consistency

if [ $CHANNEL = "ota" ]; then
	case "$2" in
	getsize)
		verify_db
		mkdir -p ${OTA_IPC}
		rm -f ${OTA_IPC}/ota_download.size
		
		rm -f /var/lib/smart/cache   ##delete the cache to force a download of metadata
		/usr/bin/smart update  ##TODO add timer check to this call to prevent repeated syncs ??
		RET=$?
		if [ $RET -ne 0 ]; then
			echo "Update failure: Ret $RET"
			
			remove_channels
			load_channel_from_file $USER_BACKUP_FILE

			rm -f $USER_BACKUP_FILE
			rm -f $TEMP_CHANNEL_LIST
			exit $RET
		fi
		
		DLSIZE=`echo -e 'n\n' | /usr/bin/smart upgrade --download | grep "of package files" | awk '{ print $1 }'`	
		RET=$?
		if [ $RET -ne 0 ]; then
			echo "Upgrade Error: $RET"

			remove_channels
			load_channel_from_file $USER_BACKUP_FILE

			rm -f $USER_BACKUP_FILE
			rm -f $TEMP_CHANNEL_LIST
			exit $RET
		fi
		
		if [ "$DLSIZE" = "" ]; then
			echo "No upgrades found"
			remove_channels
			load_channel_from_file $USER_BACKUP_FILE

			rm -f $USER_BACKUP_FILE
			rm -f $TEMP_CHANNEL_LIST
			exit 8
		fi
		
		
		echo "$DLSIZE" > ${OTA_IPC}/ota_download.size
		echo "Download Size $DLSIZE"
		
		remove_channels
		load_channel_from_file $USER_BACKUP_FILE

		rm -f $USER_BACKUP_FILE
		rm -f $TEMP_CHANNEL_LIST
		exit $RET
	;;
	download)
		verify_db
		rm -f /var/lib/smart/cache   ##delete the cache to force a download of metadata
		/usr/bin/smart update ##TODO add timer check to this call to prevent repeated syncs
		RET=$?
		if [ $RET -ne 0 ]; then
			echo "Update failure: Ret $RET"
			
			remove_channels
			load_channel_from_file $USER_BACKUP_FILE

			rm -f $USER_BACKUP_FILE
			rm -f $TEMP_CHANNEL_LIST
			exit $RET
		fi
		
		/usr/bin/smart upgrade -y --download
		RET=$?
		if [ $RET -ne 0 ]; then
			echo "Update failure: Ret $RET"
			
			remove_channels
			load_channel_from_file $USER_BACKUP_FILE

			rm -f $USER_BACKUP_FILE
			rm -f $TEMP_CHANNEL_LIST
			exit $RET
		fi
		
		#log this to the terminal to signify download is complete incase there was nothing to download
		echo "Fetching packages... [ 100%]"
		
		/etc/init.d/fwinstall cache 2&>/dev/null
		
		remove_channels
		load_channel_from_file $USER_BACKUP_FILE

		rm -f $USER_BACKUP_FILE
		rm -f $TEMP_CHANNEL_LIST
		exit $RET
	;;
	install)
		begin_install
		stop_jetstream
		verify_db
		
		/usr/bin/smart upgrade -y
		RET="$?"
			
		if [ ${RET} -ne 0 ]; then
			echo "Error: Smart Upgrade Failure"
	
			rebuild_db
			/usr/bin/smart upgrade -y
		
			RET="$?"
		fi
		
		if [ $RET -eq 0 ]; then
			/etc/init.d/fwinstall rotate
		fi
		
		remove_channels
		load_channel_from_file $USER_BACKUP_FILE

		rm -f $USER_BACKUP_FILE
		rm -f $TEMP_CHANNEL_LIST
		end_install

		#needed to cleanup symlinks from some packages when going backwards
		ldconfig
		sync

		exit $RET
	;;
   *)
		echo "Error: Invalid parameter for ota"
		remove_channels
		load_channel_from_file $USER_BACKUP_FILE

		rm -f $USER_BACKUP_FILE
		rm -f $TEMP_CHANNEL_LIST
		exit 1;
	esac
fi

#processing for all methods NOT ota
begin_install
stop_jetstream
verify_db

RETVAL=""
if [ $2 ]; then
	install_package $2
	RETVAL=$?
else
	 ##local installs will get checked on reboot
	if [ "$CHANNEL" = "local" ]; then 
		run_update
		RETVAL=$?
		echo "Local install, skipping OEM validation"
	else
		if [ "$CHANNEL" = "development" ]; then #this has multiple repositories so our caching/revert hack wont work.
			run_update
			RETVAL=$?
		else
			run_update_cache
			RETVAL=$?
		fi

		if [ $RETVAL -eq 0 ]; then
			if [ -f /etc/init.d/validate_oem ]; then
				/etc/init.d/validate_oem start update_firmware
			fi
		fi
	fi
	
	echo "UpdateFirmware RETVAL $RETVAL"
	if [ $RETVAL -eq 0 ]; then
		/etc/init.d/fwinstall rotate
	else
		##TODO:: auto revert???
		echo "Install returned an error, not rotating backups"
	fi
fi

remove_channels
load_channel_from_file $USER_BACKUP_FILE

rm -f $USER_BACKUP_FILE
rm -f $TEMP_CHANNEL_LIST
end_install

#needed to cleanup symlinks from some packages when going backwards
ldconfig
sync

##TODO:: should we restart jetstream or restart the controller here??
if [ "$CHANNEL" = "local" ]; then
	echo "Restarting System"
else
	start_jetstream
fi

exit ${RETVAL}
