#!/bin/sh
#
#  dosbox-install-game  --  part of DOSBox package
#
#  Purpose:
#    * Downloads game archive,
#    * Extracts it to directory,
#    * Looks for executable
#    * Creates menu item
#
#  Requires: wget or lftpget, update-menus, dosbox, unarj/unzip/unrar
#

  TARGET_DIR=/usr/games/dosbox
  DOSBOX_BIN=/usr/bin/dosbox
DEFAULT_ICON=dosbox.xpm
     PACKAGE=dosbox
    MENU_DIR=/usr/lib/menu
 MENU_UPDATE=/usr/bin/update-menus
  PROXY_CONF=/etc/profile.d/proxy.sh

fname0=`basename $0`
verbose=no
mode=install

VERSION="$fname0 1.0 (20 Feb 2004)"

declare PROJECT_NAME
declare EXECUTABLE_FILENAME
declare BASE_PROJECT_DIR

if [ "$1" = "-d" ]; then
    : ${doit:=echo}
    $doit : Enable dry running...
    shift
fi

function report_error()
{
    echo "Error: $*!" > /dev/stderr
}

function report_verbose()
{
    test "$verbose" = "yes" || return
    echo $*
}

function usage()
{
    test $# = 0 && echo $VERSION || report_error $*
    echo "Usage: $fname0 [options] resource...
Supported resource types:
  - archive URL,
  - archive filepath,
  - directory path,
  - executable filepath.
Purpose:
  - download archive(!),
  - extract it to directory(!),
  - find DOS executable in directory(!),
  - make menu item for running executable by DOSBox(!!).
Options:
  --executable xxx ...explicitly set executable filename for (!)
  --project xxx    ...explicitly set name of project
                      containing executable for (!!)
  --basedir        ...set directory containing executable
                      with relative filename for (!!)"
    return 1
}

function mkchdir()
{
    if [ ! -d $1 ]; then
	report_verbose "Create directory $1..."
	$doit mkdir -p $1
    fi
    $doit cd $1
}

function init_tmpdir()
{
    if [ -z "$TMPDIR" ]; then
	if [ -d $HOME/tmp ]; then
	    TMPDIR=$HOME/tmp
	else
	    TMPDIR=/tmp
	fi
    fi

    if [ -d "$TMPDIR" ]; then
	export TMPDIR
	return 0
    fi

    report_error "cannot assign TMPDIR"
    return 1
}

function init_proxy()
{
    [ -z "$http_proxy" -a -x $PROXY_CONF ] && . $PROXY_CONF
    [ -n "$http_proxy" ] && export http_proxy
    [ -n  "$ftp_proxy" ] && export  ftp_proxy
    return 0
}

function is_url()
{
    case "$1" in
	*://* ) return 0 ;;
    esac
    return 1
}

function install_url()
{
    report_verbose "Download $1..."
    local oldPWD=$PWD
    mkchdir $TMPDIR/dosbox-install
    if [ -n "`which wget`" ]; then
	eval wget -c -N -nc -nH -nd $1 || return 1
    elif [ -n "`which lftpget`" ]; then
	eval lftpget -c $1   # 'eval' hides lftpget from rpmbuild
    else
	report_error "cannot find wget or lftpget needed for downloading \"$1\""
	return 1
    fi
    install_archive $1
    cd $oldPWD
}

function is_archive()
{
    case "$1" in
	*.zip | *.ZIP ) ARCHIVER=unzip; ARCHIVER_OPTS="-o -q" ;;
	*.rar | *.RAR ) ARCHIVER=unrar; ARCHIVER_OPTS="x -o+ -y -inul" ;;
	*.arj | *.ARJ ) ARCHIVER=unarj; ARCHIVER_OPTS="x" ;;
	* ) return 1
    esac
    if [ -z "`which $ARCHIVER`" ]; then
	report_error "archiver needed for extracting $1 is not installed"
    fi
    return 0
}

function install_archive()
{
    report_verbose "Extract archive $1..."
    local srcPath gameName gameDir oldPWD=$PWD

    case "$1" in
	/* ) srcPath=$1 ;;
	* ) srcPath=$PWD/$1 ;;
    esac

    gameName=`basename $1`
    if [ -z "$gameName" ]; then
	report_error "cannot parse filename \"$1\""
	return 1
    fi

    gameDir=$TARGET_DIR/${gameName%.*}
    mkchdir $gameDir
    
    $doit $ARCHIVER $ARCHIVER_OPTS $srcPath || return 1
    report_verbose "Allow group access to score files..."
    chmod -R g+w *    

    install_directory $gameDir
    
    cd $oldPWD
}

function install_executable()  # $1 = basedir, $2 = relative exe filename
{
    local basedir=$1 exename=$2 exepath=$1/$2
    report_verbose "Install executable $exename in $basedir..."
    if [ ! -d $basedir ]; then
	report_error "cannot find directory \"$basedir\""
	return 1
    fi
    if [ ! -e $exepath ]; then
	report_error "cannot find executable \"$exepath\""
	return 1
    fi

    local runfile
    if [ "`dirname $exename`" = "." ]; then
	runfile=$exepath
    else
	report_verbose "Create loader batch file..."
	runfile=$basedir/_dosbox_.bat
	echo -ne "@cd `dirname $exename`\r\n@`basename $exename`\r\n" \
	    | tr / '\\\\' > $runfile
    fi

    local title
    [ -n "$PROJECT_NAME" ] && title=$PROJECT_NAME || title=`basename $1`
    local menufile=$MENU_DIR/dosbox_$title.menu
    report_verbose "Create menu item in $menufile..."
cat << __MENU__ > $menufile
?package($PACKAGE): needs="x11" section="Amusement/DOSBox" \
title="$title" longtitle="$title - DOS game" \
command="xterm -e $DOSBOX_BIN $runfile" icon="$DEFAULT_ICON"
__MENU__
    report_verbose "Update menus..."
    $doit $MENU_UPDATE
    report_verbose "...executable installed"
    return 0
}

function install_executable_try()
{
    local nfiles=`find . -type f -iname $1 | wc -l`
    [ -z "$nfiles" ] && return 1
    if [ $nfiles -eq 0 ]; then
	return 1
    elif [ $nfiles -gt 1 ]; then
	report_error "Multiple $1 executables found in $PWD, may be wrong"
    fi
    install_executable $PWD `find . -type f -iname $1 -printf '%P\n' | head -1`
}

function install_directory()
{
    report_verbose "Configure directory $1..."
    if [ ! -d $1 ]; then
	report_error "$1 does not exist or is not a directory"
	return 1
    fi
    local oldPWD=$PWD retval=0
    cd $1
    : ${PROJECT_NAME:=`basename $PWD`}
    if [ -n "$EXECUTABLE_FILENAME" ]; then
	install_executable $PWD $EXECUTABLE_FILENAME
    else
        install_executable_try '*.bat' || \
        install_executable_try '*.com' || \
        install_executable_try '*.exe' || {
	    report_error "cannot find executables in \"$1\""
	    retval=1
        }
    fi
    cd $oldPWD
    report_verbose "...directory configured"
    return $retval
}

function install_game()
{
    report_verbose "Install game from $1..."
    if is_url $1; then
	install_url $1
    elif is_archive $1; then
	install_archive $1
    elif [ -d $1 ]; then
	install_directory $1
    else
	install_executable $BASE_PROJECT_DIR $1
    fi
    report_verbose "...installing finished"
}

function uninstall_game()
{
    report_verbose "Uninstall game $1..."

    local menufile=$MENU_DIR/dosbox_$1.menu
    if [ -e $menufile ]; then
	report_verbose "Remove menu file $menufile..."
	$doit rm -f $menufile
	report_verbose "Update menus..."
	$doit $MENU_UPDATE
    else
	report_error "menu record $menufile does not exists"
    fi

    local gamedir=$TARGET_DIR/$1
    if [ -e $gamedir ]; then
	report_verbose "Remove directory $gamedir..."
	rm -rf $gamedir
    else
	report_error "directory $gamedir does not exists"
    fi
    report_verbose "...$1 uninstalled"
    return 0
}

function main()
{
    if [ $# = 0 ]; then
	usage
	return 1
    fi

    while : ; do
	$doit : Parse arg $1...
	case "$1" in
	    -h | --help ) usage; return 0 ;;
	    -v | --verbose ) verbose=yes ;;
	    -V | --version ) echo $VERSION; return 0 ;;
	    --trace-script ) echo Enable tracing output...; set -x ;;
	    -u | --uninstall | --remove ) mode=uninstall ;;
	    --base*    ) shift; BASE_PROJECT_DIR=$1 ;;
	    --project* ) shift; PROJECT_NAME=$1 ;;
	    --exe*     ) shift; EXECUTABLE_FILENAME=$1 ;;
	    -* ) usage "unknown argument \"$1\""; return 1;;
	    * ) break ;;
	esac
	shift
    done

    init_tmpdir || return 1
    init_proxy  || return 1
    for c in "$@"; do
	if [ "$mode" = "install" ]; then
	    install_game $c
	elif [ "$mode" = "uninstall" ]; then
	    uninstall_game $c
	else
	    report_error "Unknown mode \"$mode\""
	fi
    done
}

main "$@"

## EOF ##
