#!/bin/bash

####################################################
# Bygfoot Football Manager                         #
# AUTHOR: Gyozo Both (gyboth@bygfoot.com)          #
# http://www.bygfoot.com                           #
####################################################

# Skript that updates src packages of the Bygfoot Football Manager
# using wget to retrieve patches from the homepage

# version number
version="0.13"
# the bygfoot release version the script is shipped with
relversion=VERSION
# the current release version on the server
packversion=

# exit codes
EXITOK=0
EXITNOPROG=1
EXITNOREV=2
EXITABORT=3
EXITWGETFAIL=4
EXITUSR=6
EXITNEWSCRIPT=7
EXITCOUNTRY=8
EXITPACKFORMAT=9
EXITDEBIAN=10

# variables

# a variable we sometimes read something into
tempvar=
# the directory containing the Bygfoot src package
packdir=
# a directory we can write to and read from
tmpdir=
# destination for the country files
countrydir=
# the Bygfoot package type, stable or unstable
type_stable=stable
type_unstable=unstable
type=
# the current revision number of the user's package
revnr=
# revision numbers fetched from the homepage
newrevnr=
# number of new revisions found
found=0
# the arguments for the script
args="$*"
# the package format the user wants to download
format_rpm=.i586.rpm
format_bin=-binary.tar.bz2
format_src=.tar.bz2
format_srpm=.src.rpm
format_deb=-1_i386.deb
format=
# which cvs version to get
cvs_version1=bygfoot-unstable
cvs_version2=bygfoot2-unstable
cvs_version=

# SourceForge.Net username (for cvs checkout)
cvs_user=

# The file we redirect dialog output to
input_file=$PWD/bygfoot-update-dialog.tmp

# The file containing all output
log_file=$PWD/bygfoot-update.log

# options

# whether all new patches should be applied automatically
apply_all=0
# whether we should skip some queries and assume standard values
auto=0
# whether we recompile automatically after patching
recompile=0
# whether we check for auxiliary programs and
# newer update script versions
check=1
# whether we just fetch the latest version number from
# the server
get_version=0

# whether we show the log file before terminating
# if so, the file doesn't get deleted by cleanup()
show_log=0

# operation modes
# source update
mode_src=0
# country file download
mode_country=1
# package download
mode_pack=2
# get cvs version
mode_cvs=3
mode=

# print a help text
function print_help()
{
    cat <<END

Usage: bygfoot-update [OPTIONS]
Note: You can call bygfoot-update without any options.

MAIN OPTIONS:
-c|--country-files         Download country files with official team names
                           and team definitions file
-n|--new-package           Download the latest complete package
-u|--update                Update your Bygfoot source package using patches
-b|--cvs                   Get CVS version

AUXILIARY OPTIONS:

Global:
-A|--auto                  Assume [y] for all prompts
-h|--help                  Print help and exit
-l|--show-log              Don't clear the log file before exiting;
                           show its contents instead.
-t|--temp-dir DIR          Set temp directory to DIR
-v|--version               Print version information and exit

Relevant for source update mode:
-a|--apply-all             Apply all new patches without prompting
-p|--package-dir DIR       Set source package directory to DIR
-r|--recompile             Run './configure && make' after updating
-R|--no-recompile          Don't recompile after updating

Relevant for country files mode:
-C|--country-dir DIR       Set destination directory for the
                           country files and def file to DIR

Relevant for package download mode:
-f|--format FORMAT         Set package format to FORMAT:
                           'src', 'rpm', 'srpm', 'bin' or 'deb.
                           Note that 'deb' isn't allowed for unstable
                           packages.
-t|--temp-dir DIR          Set download destination directory
                           to DIR (same as temp directory)
-T|--type TYPE             Download latest TYPE package, TYPE
                           being either 'stable' or 'unstable'.
-V|--get-version           Fetch version number of the latest
                           release from the server and exit.

Relevant for CVS mode:
-B|--branch BRANCH         Which CVS branch to get; currently 1 or 2
                           for the 1.8 or 1.9 branch.
-U|--username NAME         Your SourceForge.Net username used for
                           checking out, or A for anonymous checkout.
END
}

# print program version
function print_version()
{
    cat <<END

bygfoot-update: A bash script keeping your Bygfoot Football Manager up-to-date.
Version $version.
See the file UPDATE for some more information.
Call bygfoot-update -h|--help for usage information.

END
}

# print output to stdout and the log file
function my_echo()
{
    echo "$@" 2>> $log_file | tee -a $log_file
}

# show log file before exiting if the option is set
function my_exit()
{
    if [ $show_log -eq 1 ]; then
	if [ -r $log_file ]; then
	    dialog --title "Bygfoot Online Update" --textbox $log_file 22 75
	else
	    echo "** WARNING: log file $log_file not readable."
	fi
    fi

    cleanup
    exit $1
}

# parse arguments
function parse_args()
{
    TEMP=`getopt -o aAbcB:C:f:hlnNp:rRt:T:uU:vV --long apply-all,\
auto,branch:,country-files,country-dir:,cvs,format:,help,new-package,no-check,\
package-dir:,recompile,no-recompile,show-log,temp-dir:,type:,update,username:\
version,get-version -- $*`

    if [ $? != 0 ]; then
	my_echo "** b-u: There was an error parsing the arguments."
	my_echo "** b-u: The arguments will be ignored."
	return
    fi

    eval set -- "$TEMP"

    while true; do
	case "$1" in
	    -a|--apply-all) apply_all=1; shift ;;
	    -A|--auto) auto=1; apply_all=1; shift ;;
	    -b|--cvs) mode=$mode_cvs; shift ;;
	    -B|--branch) set_branch $2; shift 2 ;;
	    -c|--country-files) mode=$mode_country; shift ;;
	    -C|--country-dir) pushd $2 &> /dev/null; countrydir=$PWD; popd &> /dev/null; shift 2 ;;
	    -f|--format) set_format $2; shift 2 ;;
	    -h|--help) print_help; exit $EXITOK ;;
	    -l|--show-log) show_log=1; shift ;;
	    -n|--new-package) mode=$mode_pack; shift ;;
	    -N|--no-check) check=0; shift ;;
	    -p|--package-dir) pushd $2 &> /dev/null; packdir=$PWD; popd &> /dev/null; shift 2 ;;
	    -r|--recompile) recompile=1; shift ;;
	    -R|--no-recompile) recompile=-1; shift ;;
	    -t|--temp-dir) pushd $2 &> /dev/null; tmpdir=$PWD; popd &> /dev/null; shift 2 ;;
	    -T|--type) type=$2; shift 2 ;;
	    -u|--update) mode=$mode_src; shift ;;
	    -U|--username) cvs_user=$2; shift 2 ;;
	    -v|--version) print_version; exit $EXITOK ;;
	    -V|--get-version) mode=$mode_pack; get_version=1; shift ;;
	    --) shift; break ;;
	esac
    done
}

# clean up in the temp dir
function cleanup()
{
    my_echo
    my_echo "** b-u: Removing dialog output file $input_file."
    rm -rfv $input_file 2>> $log_file | tee -a $log_file

    if [ ! -z $tmpdir -a $mode -neq $mode_pack ];then
	my_echo "** b-u: Cleaning up in the temp directory."
	rm -rfv  2>> $log_file | tee -a $log_file
    fi

    if [ $show_log -eq 0 ]; then
	my_echo "** b-u: Removing log file $log_file."
	rm -rfv $log_file
    fi    
}

# wget something, exit if it doesn't work
function my_wget()
{
    if ! wget -v $1 2>> $log_file | tee -a $log_file; then
	my_echo
	my_echo "** b-u: wget failure."
	my_exit $EXITWGETFAIL
    fi
}

# check for the programs needed
function check_progs()
{
    if [ $check -eq 0 ]; then
	return
    fi

    my_echo
    for i in sed tar bzip2 wget patch cvs; do
	my_echo -n "** b-u: checking for $i... "
	if which $i &> /dev/null; then
	    my_echo "ok"
	else
	    my_echo "failed"
	    my_echo
	    my_echo "** WARNING: Didn't find working $i, maybe it's not in your PATH."
	    my_echo "** WARNING: You might not be able to use all bygfoot-update features."
	    read a
	fi
    done
}

function read_input()
{
    if [ $? -eq 1 ];then
	my_echo "** b-u: User abort."
	my_exit $EXITUSR
    fi

    if [ -r $input_file ]; then
	tempvar=$(cat $input_file)
    else
	tempvar=
    fi

    my_echo "** b-u: User input: $tempvar"
    my_echo
}

# get country files with official team names
function get_country_files()
{
    my_echo
    my_echo "** b-u: Fetching country files with official team names and"
    my_echo "** b-u: team definitions file."

    pushd $countrydir &>/dev/null

    my_wget http://bygfoot.sourceforge.net/revisions/bygfoot-countries.tar.bz2

    for i in country_* teams; do
	mv -vf $i $i.old 2>> $log_file | tee -a $log_file
    done

    tar xfjv bygfoot-countries.tar.bz2 2>> $log_file | tee -a $log_file
    rm -vf bygfoot-countries.tar.bz2 2>> $log_file | tee -a $log_file

    popd

    my_echo "** b-u: done."
    my_exit $EXITCOUNTRY
}

# get the paths for a temp directory and
# the location of the user's bygfoot src package
function get_paths()
{
    if [ $mode -eq $mode_src ]; then
	if [ -z $packdir ]; then
	    if [ $auto -eq 0 ]; then
		dialog --title "Bygfoot Online Update" \
		    --inputbox "Source package directory" 22 80 $PWD 2> $input_file
		read_input

		pushd $tempvar; packdir=$PWD; popd
	    else
		packdir=$PWD
	    fi

	    my_echo
	    my_echo "** b-u: Package dir set to"
	    my_echo "** b-u: $packdir"	
	fi
    fi

    if [ $mode -ne $mode_country ]; then
	if [ -z $tmpdir ]; then
	    if [ $auto -eq 0 ]; then
		dialog --title "Bygfoot Online Update" --inputbox "Temporary directory\n(you need read/write permissions there)" \
		    22 80 /tmp 2> $input_file
		read_input

		if [ ! -z $tempvar ]; then
		    pushd $tempvar &> /dev/null ; tmpdir=$PWD; popd &> /dev/null
		else
		    tmpdir=/tmp
		fi

	    else
		tmpdir=/tmp
	    fi
	    my_echo
	    my_echo "** b-u: Temp dir set to"
	    my_echo "** b-u: $tmpdir"
	fi
    fi

    if [ $mode -eq $mode_country ]; then
	if [ -z $countrydir ]; then
	    if [ $auto -eq 0 ]; then
		dialog --title "Bygfoot Online Update" --inputbox "Country files destination directory\n(default destination recommmended)" \
		    22 80 $HOME/.bygfoot/text_files 2> $input_file
		read_input

		if [ ! -z $tempvar ]; then
		    pushd $tempvar; countrydir=$PWD; popd
		else
		    countrydir=$HOME/.bygfoot/text_files
		fi
	    else
		countrydir=$HOME/.bygfoot/text_files
	    fi
	    my_echo
	    my_echo "** b-u: Country dir set to"
	    my_echo "** b-u: $countrydir"
	fi
    fi
}

# find out revision number and type
function get_rev_type()
{
    echo
    if [ ! -e $packdir/revision_number ]; then
	dialog --title "Bygfoot Online Update" --msgbox \
"I couldn't find the file containing your current revision number and type ($packdir/revision_number).\nFailure." \
	    22 80 2> $input_file
	    read_input
	    my_exit $EXITNOREV
    fi

    type=$(cat $packdir/revision_number | sed s/[0-9]*//g)   
    revnr=$(cat $packdir/revision_number | sed s/[a-z]*//g)

    my_echo "** b-u: Your current revision is: $type $revnr."
}

function apply_rev()
{
    my_echo
    my_echo "** b-u: Applying patch revision_$type$newrevnr"

    cd $packdir
    
    if [ -e $newrevdir/prepatch ]; then
	$newrevdir/prepatch 2>> $log_file | tee -a $log_file
    fi

    patch -p1 < $newrevdir/patch* 2>> $log_file | tee -a $log_file

    if [ -e $newrevdir/postpatch ]; then
	$newrevdir/postpatch 2>> $log_file | tee -a $log_file
    fi

    cd $tmpdir/bygfoot-update
}

# fetch a revision archive from the homepage and
# patch the src package
function get_revision()
{
    local newrevdir=$tmpdir/bygfoot-update/revision_$type$newrevnr

    my_echo
    my_echo "** b-u: Retrieving revision_$type$newrevnr.tar.bz2."
    my_wget http://bygfoot.sourceforge.net/revisions/$type/revision_$type$newrevnr.tar.bz2

    mkdir $newrevdir
    cd $newrevdir
    tar xfjv ../revision_$type$newrevnr.tar.bz2 2>> $log_file | tee -a $log_file
    
    dialog --title "Bygfoot Online Update" --textbox README 22 75

    if [ $apply_all -eq 0 ]; then
	
	dialog --title "Bygfoot Online Update" --menu \
"Apply patch?\n(You can't apply newer ones if you don't apply this one because they depend on each other.)" \
	    22 80 10 \
	    1 Yes \
	    2 No \
	    3 All 2> $input_file

	    read_input
	
	if [ ! -z $tempvar ]; then
	    if [ $tempvar -eq 3 ]; then
		apply_all=1
	    elif [ $tempvar -ne 1 ]; then
		my_echo
		my_echo "** b-u: User abort."
		my_exit $EXITUSR
	    fi
	fi
    fi

    apply_rev
}

# look for new revisions
function get_revs()
{
    my_echo
    cd $tmpdir
    my_echo "** b-u: Cleaning up old update directories and creating a new one..."
    rm -rfv bygfoot-update 2>> $log_file | tee -a $log_file
    mkdir -v bygfoot-update 2>> $log_file | tee -a $log_file
    cd bygfoot-update
    my_echo
    my_echo "** b-u: Fetching revision list..."
    my_wget http://bygfoot.sourceforge.net/revisions/$type/revisions_$type

    for i in $(cat revisions_$type); do
	my_echo
	newrevnr=$(echo $i | sed s/'[a-z_]*\([0-9]*\).*'/'\1'/g)
	if [ $newrevnr -gt $revnr ]; then
	    found=$[found + 1]
	    get_revision
	else
	    my_echo "** b-u: $i is older than your revision..."
	fi
    done
}

# clean up etc.
function update_end()
{
    my_echo
    
    if [ $found -ge 1 ]; then

	dialog --title "Bygfoot Online Update" --msgbox "$found new revisions found.\nYour new revision number should be $[revnr + found].\nHave a look at the files README, ChangeLog and ReleaseNotes to see the changes that were made." 2> $input_file

	if [ $recompile -eq 0 -a $auto -eq 0 ]; then
	    dialog --title "Bygfoot Online Update" --yesno "Would you like me to execute 'configure && make' ?" 22 80 2> $input_file
	    
	    read_input
	fi

	if [ $recompile -ne -1 ]; then
	    cd $packdir
	    ./configure && make 2>> $log_file | tee -a $log_file
	fi
	
    else
	dialog --title "Bygfoot Online Update" --msgbox "No new revisions found.\nYour package seems to be up-to-date." 22 80 2> $input_file
    fi

    my_echo
    my_echo "** b-u: done."

    my_exit $EXITOK
}

# set package format from a command line option
function set_format()
{
    if [ $1 = "rpm" ]; then
	format=$format_rpm
    elif [ $1 = "srpm" ]; then
	format=$format_srpm
    elif [ $1 = "src" ]; then
	format=$format_src
    elif [ $1 = "bin" ]; then
	format=$format_bin
    elif [ $1 = "deb" ]; then
	format=$format_deb
    else
	my_echo "** b-u: Unrecognized package format: $1"
	my_echo "** b-u: Failure."
	my_exit $EXITPACKFORMAT
    fi
}

# set cvs branch from command line option
function set_branch()
{
    if [ $1 -eq 1 ]; then
	cvs_version=$cvs_version1;
    else
	cvs_version=$cvs_version2;
    fi
}

# ask for the package type (stable/unstable)
function get_type()
{
    if [ ! -z $type ]; then
	return
    fi

    if [ $auto -ne 1 ];then
	
	dialog --title "Bygfoot Online Update" --menu "Specify package type" \
	    22 80 10 \
	    1 "Stable" \
	    2 "Unstable" 2> $input_file

	read_input

	if [ $tempvar -eq 2 ]; then
	    type=$type_unstable
	else
	    type=$type_stable
	fi 
    else
	type=$type_stable
    fi
}

# get package format the user wants to download
function get_format()
{
    if [ -z $format ]; then
	if [ $auto -ne 1 -a $get_version -ne 1 ]; then

	    dialog --title "Bygfoot Online Update" --menu "Specify package format" \
		22 80 10 \
		1 "RPM" \
		2 "Binary" \
		3 "Source" \
		4 "Debian" \
		5 "Source RPM" 2> $input_file
	    
	    read_input
	    
	    if [ $tempvar -eq 2 ]; then
		format=$format_bin
	    elif [ $tempvar -eq 3 ]; then
		format=$format_src
	    elif [ $tempvar -eq 4 ]; then
		format=$format_deb
	    elif [ $tempvar -eq 5 ]; then
		format=$format_srpm
	    else
		format=$format_rpm
	    fi
	else
	    format=$format_rpm
	fi
    fi

    if [ "$type" = "$type_unstable" -a "$format" = "$format_deb" ]; then
	dialog --title "Bygfoot Online Update" --msgbox \
"There are no unstable packages for Debian. Sorry.\nFailure." 22 80 2> $input_file
	my_exit $EXITDEBIAN
    fi
}

function get_latest_version()
{
    my_echo
    my_echo "** b-u: Fetching version number of the latest $type release."

    pushd $tmpdir &> /dev/null
    rm -rfv bygfoot-update 2>> $log_file | tee -a $log_file
    mkdir bygfoot-update
    cd bygfoot-update
    my_wget http://bygfoot.sourceforge.net/packages/$type/version

    packversion=$(cat version)

    if [ $get_version -eq 1 ]; then
	my_exit $EXITOK
    fi

    if [ $auto -eq 1 ]; then
	return
    fi

    dialog --title "Bygfoot Online Update" --yesno "Latest $type version is $packversion.\nYour version (as far as i know) is $relversion.\nDo you want me to download the package?" 22 80 2> $input_file

    read_input
}

function get_new_package()
{
    local separator=-
    local file=

    if [ $format = $format_rpm -o $format = $format_srpm ]; then
	packversion=$(echo $packversion | sed s/'\([0-9]*\.[0-9]*\)\(\.\)\([0-9]*\)'/'\1-\3'/g)
    fi
    
    if [ $format = $format_deb ]; then
	separator=_
    fi

    file=bygfoot$separator$packversion$format

    my_wget http://bygfoot.sourceforge.net/packages/$type/$file

    dialog --title "Bygfoot Online Update" --msgbox "You can find the package $file\nin the directory $PWD." \
	22 80 2> $input_file
    my_echo "** b-u: Done."
    
    my_exit $EXITOK
}

# download a bygfoot package
function get_package()
{
    get_type

    get_format
    
    get_latest_version

    get_new_package
}

function get_mode()
{
    if [ ! -z $mode ]; then
	return
    fi
    
    if [ $auto -eq 1 ]; then
	mode=$mode_src
	return
    fi

    dialog --title "Bygfoot Online Update" --menu "Main Menu" 22 80 10 \
	1 " Update your Bygfoot source package using patches" \
	2 " Download the latest Bygfoot release" \
	3 " Get country file package with official team names" \
	4 " Get CVS version (2+ MB 'cause it's not compressed)" 2> $input_file

    read_input

    if [ -z $tempvar ]; then
	mode=$mode_src
	return
    fi

    if [ $tempvar -eq 2 ]; then
	mode=$mode_pack
    elif [ $tempvar -eq 3 ]; then
	mode=$mode_country
    elif [ $tempvar -eq 4 ]; then
	mode=$mode_cvs
    else
	mode=$mode_src
    fi
}

function get_cvs()
{
    if [ -z $cvs_version ];then
	dialog --title "Bygfoot Online Update" --menu "Specify CVS version" 22 80 10 \
	    1 " 1.8 branch" \
	    2 " 1.9 branch" 2> $input_file

	read_input

	if [ $tempvar -eq 2 ]; then
	    cvs_version=$cvs_version2
	else
	    cvs_version=$cvs_version1
	fi
    fi

    if [ -z $cvs_user ];then
	dialog --title "Bygfoot Online Update" --inputbox "If you'd like to check out as a developer, enter your\nSourceForge.net username. Press RETURN to download anonymously." 22 80 2> $input_file

	read_input

	if [ -z $tempvar ]; then
	    cvs_command="cvs -d:pserver:anonymous@cvs.sf.net:/cvsroot/bygfoot"
	else
	    cvs_command="cvs -d:ext:$tempvar@cvs.sf.net:/cvsroot/bygfoot"
	fi
    else
	if [ $cvs_user = "A" ]; then
	    cvs_command="cvs -d:pserver:anonymous@cvs.sf.net:/cvsroot/bygfoot"
	else
	    cvs_command="cvs -d:ext:$cvs_user@cvs.sf.net:/cvsroot/bygfoot"
	fi	
    fi
    
    cd $tmpdir
    $cvs_command checkout $cvs_version 2>> $log_file | tee -a $log_file

    if [ $recompile -eq 0 -a $auto -eq 0 ]; then
	dialog --title "Bygfoot Online Update" \
	    --yesno "Would you like me to execute 'autogen.sh && make' ?" 22 80 2> $input_file
	
	read_input
    fi

    if [ $recompile -ne -1 ]; then
	cd $cvs_version
	./autogen.sh && make 2>> $log_file | tee -a $log_file
    fi

    my_exit $EXITOK
}

parse_args $*
print_version

echo "Bygfoot Online Update $version log file" > $log_file
echo "Don't forget to remove this file if you don't need it anymore." >> $log_file

check_progs
get_mode
get_paths

# what to do when user presses Ctrl-C
trap 'my_echo; my_echo "** b-u: User abort." & my_exit $EXITABORT' 2
if [ $mode -eq $mode_country ]; then
    get_country_files
elif [ $mode -eq $mode_pack ]; then
    get_package
elif [ $mode -eq $mode_cvs ]; then
    get_cvs
else
    get_rev_type
    get_revs
    update_end
fi