#!/bin/bash
#
#Copyright 2012 CurlyMo <development@xbian.org>
#
#This file is part of XBian - XBMC on the Raspberry Pi.
#
#XBian is free software: you can redistribute it and/or modify it under the
#terms of the GNU General Public License as published by the Free Software
#Foundation, either version 3 of the License, or (at your option) any later
#version.
#
#XBian is distributed in the hope that it will be useful, but WITHOUT ANY
#WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
#FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
#details.
#
#You should have received a copy of the GNU General Public License along
#with XBian. If not, see <http://www.gnu.org/licenses/>

#|------------------------------------|
#|          Global variables          |
#|------------------------------------|

# The arguments this module accepts
ARGUMENTS=(list info installtest install removetest remove progress status updatedb);
if [ -f "$BASEPATH/config/pkglist" ]; then
	CONTENT=$(cat $BASEPATH/config/pkglist);
else
	CONTENT="";
fi

#|------------------------------------|
#|          Include files             |
#|------------------------------------|

source $BASEPATH/modules/packages/functions
if [ $GUIMODE -eq 1 ]; then
	source $BASEPATH/modules/packages/dialogs
fi
source $BASEPATH/functions/packages

[ -z "$ALLPKGLST" ] && updateAllPackagesListFn
PKGNOTFOUND=0;
#|------------------------------------|
#|           Main program             |
#|------------------------------------|

function showPackageActionsFn() {
	PACKAGE=${PACKAGES[$2]};
	getPackageInformationFn "$PACKAGE";
	showPackageOptionsDlg;
	if [ $? -eq 0 ]; then
		if [ $RETURN -eq 1 ]; then
			showPackageInfoDlg "${PKGINFO[*]}";
			showPackageActionsFn $1 $2;
		elif [ $RETURN -eq 2 ]; then
			showConfirmInstallUpdateDlg;
			if [ $? -eq 0 ]; then
				showInstallUpdatePackageDlg;
				installPackageFn 1 "${PKGINFO[0]}=${PKGINFO[1]}";
				STATUS=$?;
				if [ $STATUS -eq 1 ]; then
					showPackageAlreadyInstalledDlg;
				elif [ $STATUS -eq 2 ]; then
					showPackageVersionNotExistDlg;
				elif [ $STATUS -eq 3 ]; then
					if [ $PKGNOTFOUND -eq 0 ]; then
						showPackageNotExistsDlg;
						showUpdateAptDBDlg;
						updateAptFn;
						if [ $? -eq 1 ]; then
							LOCALPKGDBUPDATED=1;
							showPacakgeInstallRetryDlg;
						else
							showUpdateAptDBFailedDlg;
						fi
					else
						showErrorDlg;
					fi
				elif [ $STATUS -eq 4 ]; then
					showPackageDowngradeDlg;
				elif [ $STATUS -ge 5 ]; then
					showPackageAdvErrorDlg;
				elif [ $STATUS -eq 0 ]; then
					installPackageFn 0 "${PKGINFO[0]}=${PKGINFO[1]}";
				fi
				showAskForLogDlg;
				if [ $? -eq 0 ]; then
					showInstallLogDlg;
				fi
				showGUIFn;
			else
				showPackageActionsFn $1 $2;
			fi
		elif [ $RETURN -eq 3 ]; then
			showConfirmRemoveDlg;
			if [ $? -eq 0 ]; then			
				showRemovingPackageDlg;
				removePackageFn 0 "${PKGINFO[0]}";
				STATUS=$?;
				if [ $STATUS -eq 1 ]; then
					showPackageNotInstalledDlg;
				elif [ $STATUS -eq 2 ]; then
					showPackageEssentialDlg
				elif [ $STATUS -eq 3 ]; then
					showPackageNotExistsDlg;
				elif [ $STATUS -eq 0 ]; then
					showPackageRemovedSuccessDlg
				fi
				showAskForLogDlg;
				if [ $? -eq 0 ]; then
					showInstallLogDlg;
				fi
				showGUIFn;
			else
				showPackageActionsFn $1 $2;
			fi
		else
			showPackageActionsFn $1 $2;
		fi
	else
		showPackageListFn $1 $2;
	fi
}

function showPackageListFn() {
	CATEGORY=${CATEGORIES[$1]};
	getPackagesFromCategoryFn "$CATEGORY"
	showPackagesListDlg "${PACKAGES[*]}"
	if [ $? -eq 0 ]; then
		showPackageActionsFn $1 $(($RETURN-1));
	else
		showGUIFn;
	fi
}

function showGUIFn() {
	if [ $REMOTEPKGDBUPDATED -eq 0 ]; then
		showDownloadPackageListDlg;
		if ! updateAptMirrorsFn; then
			showFailedToRetrieveAptMirrosDlg;
		else
			downloadPackageListFn;
			REMOTEPKGDBUPDATED=$((1-$?))
		fi;
	CONTENT=$(cat $BASEPATH/config/pkglist);
	fi
	if [ $LOCALPKGDBUPDATED -eq 0 ]; then
		if [ $REMOTEPKGDBUPDATED -eq 1 ]; then
			localPackageDBOutdatedFn;
			if [ $? -eq 1 ]; then
				showUpdateAptDBDlg;
				updateAptFn;
				if [ $? -eq 1 ]; then
					LOCALPKGDBUPDATED=1;
				else
					showUpdateAptDBFailedDlg;
				fi
			fi
		fi
	fi
	showGettingLocalPackageInfoDlg;
	getPackageCategoryListFn;
	if [ ${#CATEGORIES[@]} -gt 0 ]; then
		showPackageCategoryListDlg "${CATEGORIES[*]}";
		if [ $? -eq 0 ]; then
			showPackageListFn $(($RETURN-1));
		fi
	fi
}

# Executes the command line version of this module
#  $1 Argument [String]
# list | status | info | installtest | install | removetest | remove
#  $2 Package [String]
# Returns
# list | status | info | installtest | install | removetest | remove
#  -  1: Success
#  -  0: Failed
#  - -1: Wrong number of arguments
#  - -2: Package not found
#  - -3: You need to run an updatedb first
#  *list
#  -  0 arguments
#  -  [categoryname],[# packages],[# installed]
#  -  1 argument
#  -  [packagename],[installed]
#  *status
#  -  1: Installed, 0: Not-Installed
#  *info
#  -  name: Full package name
#  -  versionl: Locally installed package version
#  -  versioni: Remote available package version
#  -  sized: Download size
#  -  sizei: Installed size
#  -  desc: Full package description
#  -  dep: Full dependency list
#  *installtest | install - (Simulates an) apt-get install
#  -  1: Package can be installed without problems
#  -  2: This package is already installed
#  -  3: Package version not found in apt repository
#  -  4: Package not found in apt repository
#  -  5: A newer version of this package is already installed
#  -  6: There is a size mismatch for the remote package
#  -  7: The package itself got an internal error
#  *removetest | remove - (Simulates an) apt-get remove
#  -  1: Package can be removed without problems
#  -  2: This package is not installed
#  -  3: This is an essential pacakge and cannot be removed
#  -  4: Package not found in apt repository
#  *progress
#  -  1: Apt is still running
#  -  0: Apt is not running
#  *updatedb - Updates local and remote apt library (when needed)
function showCMDFn() {
	case $1 in
		list)
                        int=$(grep "APT::Periodic::Update-Package-Lists" /etc/apt/apt.conf.d/20auto-upgrades 2>/dev/null| grep -o "[0-9]*")
                        [ -z "$int" -o "$int" -eq 0 ] && int=1440 || int=$((int*24*60))
                        [ -z "$(eval find /var/lib/apt/periodic/update-success-stamp -cmin -$int 2>/dev/null)" ] && getInternetFn  && { echo -3; exit 0; }
 
			if [ $# -eq 1 ]; then
				if [ -f "$BASEPATH/config/pkglist" ] && [ -f "$BASEPATH/config/aptmirror" ]; then
					getPackageCategoryListFn
					updateAllPackagesListFn
					for CATEGORY in ${CATEGORIES[@]}; do
						getPackagesFromCategoryFn $CATEGORY;
						X=0; L=""; S=''
						for P in ${PACKAGES[@]}; do
							L=$L"$S$P|xbian-package-$P"; S='|'
						done
						echo $CATEGORY,${#PACKAGES[@]},$(getPackageStatusCountFn $L; echo $?)
					done;
				else
					echo -3;
				fi
			elif [ $# -eq 2 ]; then
				if [ -f "$BASEPATH/config/pkglist" ] && [ -f "$BASEPATH/config/aptmirror" ]; then
					updateAllPackagesListFn;
					getPackageCategoryListFn;
					if [ $(echo ${CATEGORIES[*]} | grep -c -o $2 ) -eq 1 ]; then
						getPackagesFromCategoryFn "$2"
						for PACKAGE in ${PACKAGES[@]}; do
							getPackageStatusFn $PACKAGE;
							if [ $? -eq 1 ]; then
								echo $PACKAGE,1
							else
								echo $PACKAGE,0
							fi
						done
					else
						echo -2;
					fi
				else
					echo -3;
				fi
			else
				echo -1;
			fi		
		;;
		status)
			if [ $# -eq 2 ]; then
				if [ -f "$BASEPATH/config/pkglist" ] && [ -f "$BASEPATH/config/aptmirror" ]; then
					getAllPackagesFn;
					if [ $(echo ${PACKAGES[*]} | grep -c -o $2) -eq 1 ]; then
						updateAllPackagesListFn;
						if [ $(echo ${ALLPKGLST[*]} | grep -c -o $2) -eq 1 ]; then
							getPackageStatusFn $2;
							if [ $? -eq 1 ]; then
								echo 1;
							else
								echo 0;
							fi
						else
							echo 0;
						fi
					else
						echo -2;
					fi
				else
					echo -3;
				fi
			else
				echo $(cat /tmp/aptstatus | grep -i "newly installed" | awk '{ print $1+$3+$6 }');
			fi
		;;
		info)
			if [ $# -eq 2 ]; then
				if [ -f "$BASEPATH/config/pkglist" ] && [ -f "$BASEPATH/config/aptmirror" ]; then
					getAllPackagesFn;
					if [ $(echo ${PACKAGES[*]} | grep -c -o $2) -eq 1 ]; then
						getPackageInformationFn $2;
						echo "name "${PKGINFO[0]} 
						echo "versionl "$(getPackageVersionFn ${PKGINFO[0]});
						echo "versionr "${PKGINFO[1]};
						echo "sized " ${PKGINFO[3]};
						echo "sizei " ${PKGINFO[2]};
						echo "desc" ${PKGINFO[4]};
						echo "dep" ${PKGINFO[5]};
					else
						echo -2;
					fi
				else
					echo -3;
				fi
			else
				echo -1;
			fi
		;;
		installtest|install)
			if [ $# -ge 2 ]; then
				[ "$1" == "install" ] && fn=2 || fn=1
				if [ -f "$BASEPATH/config/pkglist" ] && [ -f "$BASEPATH/config/aptmirror" ]; then
					shift
					getAllPackagesFn;
					if [ $(echo ${PACKAGES[*]} | grep -c -o $1) -eq 1 ]; then
						getPackageInformationFn $1;
						[ "$2" == "-" ] && shift
						shift
						installPackageFn $fn ${PKGINFO[0]} $@;
						echo $(($?+1));
					else
						echo -2;
					fi
				else
					echo -3;
				fi
			else
				echo -1;
			fi
		;;
		removetest|remove)
			if [ $# -eq 2 ]; then
				[ "$1" == "remove" ] && fn=2 || fn=1
				if [ -f "$BASEPATH/config/pkglist" ] && [ -f "$BASEPATH/config/aptmirror" ]; then
					getAllPackagesFn;
					if [ $(echo ${PACKAGES[*]} | grep -c -o $2) -eq 1 ]; then
						getPackageInformationFn $2;
						removePackageFn $fn ${PKGINFO[0]}
						echo $(($?+1));
					else
						echo -2;
					fi
				else
					echo -3;
				fi
			else
				echo -1;
			fi
		;;
		progress)
			if [ $(kill -0 $(pgrep apt-get) 2>/dev/null; echo $?) -eq 0 ]; then
				echo 1;
			else
				echo 0;
			fi
		;;
		updatedb)
			STATUS=0;
			updateAptMirrorsFn;
			if [ $? -eq 0 ]; then
				downloadPackageListFn;
				if [ $? -eq 0 ]; then
					localPackageDBOutdatedFn;
					if [ $? -eq 1 ]; then
						updateAptFn;
						if [ $? -eq 0 ]; then
							STATUS=1;
						else
							STATUS=0;
						fi
					else
						STATUS=1;
					fi
				else
					STATUS=1;
				fi
			else
				STATUS=0;
			fi
			echo $STATUS;
		;;
	esac
}
