#!/bin/bash
#
# TouchScale updater script
# Unauthorized changes forbidden
#
# Parameters
# $1: package name (optional
# $2: ip addrest to transfer this package (optional)
# $3: package source path (optional) -> 
#     If exist, implies that package($1) must be transferred directly to ip address($2) from source ($3)

# Installation variables
install_package=$1	  					# Package name to install
transfer_ip=$2							# Target IP to transfer package
source_folder=$3						# Source folder to take de package to transfer (if different than default)

# Detect OS version 
dist=$(lsb_release -si)
ver=$(lsb_release -sr)
nam=$(lsb_release -sc)
desc=$(lsb_release -sd)
kernel=$(uname -r | awk -F '-' '{print $1}')

install_pattern="TouchScale-*-$dist""_""$nam.deb"
install_folder="/home/pcscale/scale/update"	# Folder
install_type="alone"						# Scale type
install_log="update.log"
start_app=1

cd $install_folder
echo -----------Called $0 $1 $2 $3 at $(date) >> $install_log



# Detect hardware
cpu=$(pcs-cpu)
# Enable update_app in Generic machines (24/10/2023)
#if [ "_$cpu" = "_Generic" ]; then
#	echo Generic CPU detected. Update aborted >> $install_log
#	echo ' '
#	exit 1
#fi

# Return codes
#    0: OK (install_package & install_type values updated)
#    1: TouchScale not installed
#    2: No package candidate to install
#    3: Package must be transferred
CheckInstall() {

	installed=$(dpkg -s TouchScale | grep "Version:" | awk -F ': ' '{print $2}')
	if [ "$installed" ]; then
		# Determite install_type
		scale_is_master=$(mysql -N -s -pepelsa -upcscale pcscale -e "show master status")
		scale_is_slave=$(mysql -N -s -pepelsa -upcscale pcscale -e "show slave status")
		if [ "$scale_is_master" ]; then
			install_type="master"
			echo "This is a master scale" >> $install_log
		elif [ "$scale_is_slave" ]; then
			install_type="slave"
			echo "This is a slave scale" >> $install_log
		else
			install_type="alone"
			echo "This is a alone scale" >> $install_log
		fi

		if [ "$install_package" = "" ]; then
			start_app=0
			# Search packages to install
			cd $install_folder
			packages=$(ls $install_pattern)
			toinstall=$installed
			for pack in $packages; do
				# to install...
				ver1=$(echo $toinstall | awk -F '.' '{print $1}')
				rev1=$(echo $toinstall | awk -F '.' '{print $2}')
				bld1=$(echo $toinstall | awk -F '.' '{print $3}')

				candidate=$(echo $pack | awk -F '-' '{print $2}')
				# candidate...
				ver2=$(echo $candidate | awk -F '.' '{print $1}')
				rev2=$(echo $candidate | awk -F '.' '{print $2}')
				bld2=$(echo $candidate | awk -F '.' '{print $3}')
				#echo $installed ... $candidate

				# new versions comparative
				v_toinstall=$ver1.$rev1.$bld1
				v_candidate=$ver2.$rev2.$bld2
				printf '%s\n%s\n' "$v_candidate" "$v_toinstall" | sort -V -C
				if [ $? -ne 0 ]; then
						toinstall=$candidate
				fi	

# Old wrong comparative
#				if [ "$ver2" -ge "$ver1" ]; then 
#					#echo " ok1"
#					if [ "$rev2" -ge "$rev1" ] || [ "$ver2" -gt "$ver1" ]; then 
#		 		 		#echo "  ok2"
#		 				if [ "$bld2" -gt "$bld1" ]; then 
#			 		 		#echo "   ok3"
#							toinstall=$candidate
#						fi
#					fi
#				fi

			done
			echo Current installed $installed. Candidate to install $toinstall >> $install_log
			if [ "$installed" = "$toinstall" ]; then
				echo "No package to install" >> $install_log
				return 2
			else
				install_package="TouchScale-$toinstall-$dist""_""$nam.deb"
				echo To install: $install_package >> $install_log
			fi
		else
			if [ "$transfer_ip" ]; then
				if [ "$source_folder" ]; then
					echo "Package $install_package must be transferred to $transfer_ip from $source_folder">> $install_log
				else
					echo "Package $install_package must be transferred to $transfer_ip" >> $install_log
				fi
				return 3
			fi
		fi
	else
		echo Touchscale not installed!
		return 1
	fi
	return 0
}

DeleteCrontab () {
#	croncmd="/home/pcscale/scale/update/update_app $1 $2 > /home/pcscale/scale/update/cron_errors.log < /dev/null"
#	cronjob="* * * * * $croncmd"
# remove all update_app lines
	( crontab -l | grep -v "/home/pcscale/scale/update/update_app" ) | crontab -
}

ReplaceCrontab () {
	croncmd="/home/pcscale/scale/update/update_app $1 $2 > /home/pcscale/scale/update/cron_errors.log < /dev/null"
	cronjob="* * * * * $croncmd"
#	( crontab -l | grep -v "$croncmd" ; echo "$cronjob" ) | crontab -
	( crontab -l | grep -v "/home/pcscale/scale/update/update_app" ; echo "$cronjob" ) | crontab -
}


# Transfer Debian package:
#   param 1: target ip
#   param 2: package name
# Return codes
#    0: OK
#    1: Transfer failed
TransferDEB () {
	if [ -f "$2" ]; then
		echo Transferring $2 to $1... >> $install_log
		fftp=~/transfer_$1_.ftp
		echo "open $1" > $fftp
		echo "user pcscale epelsa" >> $fftp
		echo "put $2 $install_folder/$2" >> $fftp
		echo "bye" >> $fftp
		result=$(ftp -n < $fftp)
		if [ "$result" = "" ]; then
			echo $2 transferred to $1 OK! >> $install_log
			DeleteCrontab $2 $1
			return 0
		else
			echo Transfer $2 to $1 failed! >> $install_log
			ReplaceCrontab $2 $1
			return 1
		fi
		rm $fftp
	else
		echo File $2 not found! >> $install_log
	fi
	
}

KillApp() {
	cd /usr/bin
	pcs-send-trx -n KILL
	cd $install_folder
	while pgrep pcscale
	do
		sleep 1
	done
}

_UpdatePackages() {
	sudo pcs-exec "./$1" >> $install_log  2>&1
	rm -f $1
}

UpdatePackages() {
	updater="pcs-updater.bsx"
	cd $install_folder
	if [ -f $updater ]; then
		_UpdatePackages $updater | zenity --progress --pulsate --auto-close --no-cancel --title="TouchScale" --text="Updating system packages..."
	fi
}

InstallDebian() {
		echo dpkg -i $install_package >> $install_log
		sudo pcs-exec dpkg -i $install_package
}

InstallBSX() {
		echo Executing SelfExtract file $install_package update >> $install_log
		chmod +x $install_package
		./$install_package update
}

TransferPackages() {
	network_scales=$(mysql -pepelsa -upcscale pcscale -B --skip-column-names -e"select IP from Scales WHERE Type='N'")
	if [ "$network_scales" != "" ]; then
		slaves=$(mysql -N -s -pepelsa -upcscale pcscale -e "select Host from information_schema.processlist where Command like 'Bin%'" | awk -F ':' '{print $1}')
		for scale_ip in $network_scales
		do
			TransferDEB $scale_ip $install_package
		done
	fi
}

UpdateApp() {
	cd $install_folder
	if [ "${install_package: -4}" == ".deb" ]; then
		InstallDebian | zenity --progress --pulsate --auto-close --no-cancel --title="TouchScale" --text="Updating to '$install_package'..."
	elif [ "${install_package: -4}" == ".bsx" ]; then
		# Timed progress bar warning that a BSX will be installed
		sleep 4 | zenity --progress --pulsate --auto-close --no-cancel --title="TouchScale" --text="Updating to '$install_package'..."
		InstallBSX
		# Self extact already starts app
		start_app=0
	fi
}

StartApp() {
	if [ $start_app -eq 1 ]; then
		cd /usr/bin
		pcscale &
	fi
}

InstallMaster () {
	echo Master install >> $install_log
	UpdateApp
	TransferPackages | zenity --progress --pulsate --auto-close --no-cancel --title="TouchScale" --text="Transferring '$install_package' to network scales..."
}

InstallSlave () {
	echo Slave install >> $install_log
	UpdateApp
}

InstallAlone () {
	echo Alone install >> $install_log
	UpdateApp
}


# Start script
CheckInstall
chkret=$?
UpdatePackages
if [ $chkret -eq 0 ]; then
	KillApp
	if [ "$install_type" = "master" ]; then
		InstallMaster
	elif [ "$install_type" = "slave" ]; then
		InstallSlave
	else
		InstallAlone
	fi
	StartApp
elif [ $chkret -eq 1 ]; then
	echo TouchScale not installed! >> $install_log
elif [ $chkret -eq 2 ]; then
	echo No package candidate to install! >> $install_log
elif [ $chkret -eq 3 ]; then
	if [ "$source_folder" ]; then
		cd $source_folder
	fi	
	TransferDEB $transfer_ip $install_package
else
	echo Unknown error! >> $install_log
fi
exit 0

