#!/usr/bin/env bash
#
# Wrapper script for Eternal Lands client.
# - Checks the el packages are configured OK
# - Copies required files to ~/.elc if not already there
# - Checks the data_dir in "to be used" el.ini file and optionally corrects
# - Optionally displays a server/configuration selection GUI
# - Optionally runs a user specified client executable
# - If a crash is detected, help is offered
#
# Author Paul Broadhead pjbroad@twinmoons.org.uk
#
# This program (script) is released as Public Domain software.  You are free to
# use it as you wish.
#
# This program 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.
#

# Show an error message, and exit the script
show_error()
{
	echo -e $1
	case $dialog in
	zenity)
		zenity --error --no-wrap --text="$1"
		;;
	kdialog)
		kdialog --error "$1"
		;;
	dialog)
		dialog --msgbox "$1" 0 0
		;;
	esac
	exit 1
}

# Show an information message
show_info()
{
	case $dialog in
	zenity)
		zenity --info --no-wrap --text="$1"
		;;
	kdialog)
		kdialog --msgbox "$1"
		;;
	dialog)
		dialog --msgbox "$1" 0 0
		;;
	*)
		echo -e $1
		;;
	esac
}

# Show a (large) text box with the contents of a file
show_text_info()
{
	case $dialog in
	zenity)
		zenity --text-info --width=500 --height=300 --title "$1" --filename="$2"
		;;
	kdialog)
		kdialog --title "$1" --textbox "$2" 500 300
		;;
	dialog)
		# Ugh, we have the error string in a temporary file, but dialog's textbox
		# doesn't fold the lines automatically. So try to do it ourselves by
		# wrapping to the terminal width, minus a bit for the textbox borders,
		# and write to a second temp file.
		fold_fname=$(mktemp)
		columns=$(expr $(tput cols || echo 80) - 5)
		cat "$2" | fold -w "$columns" -s > "$fold_fname"
		dialog --title "$1" --textbox "$fold_fname" 0 0
		rm -f $fold_fname
		;;
	*)
		cat "$2"
		;;
	esac
}

# Show a confirmation dialog. Returns 0 if the user answers "yes" to the
# question posed, 1 otherwise.
yes_no()
{
	case $dialog in
	zenity)
		zenity --question --no-wrap --text="$1"
		;;
	kdialog)
		kdialog --yesno "$1"
		;;
	dialog)
		dialog --yesno "$1" 0 0
		;;
	*)
		while true
		do
			read -p "$1 [y/n] " ans
			case $ans in
			[Yy]*)
				return 0
				;;
			[Nn]*)
				return 1
				;;
			*)
				echo "Please answer yes or no."
				;;
			esac
		done
	esac
}

# get users choice from the $serverfile
getconfig()
{
	title="Choose the Server/Configuration - main is the standard"
	case $dialog in
	zenity)
		sort -u $serverfile | tr -d '\015' | grep -v -e ^$ -e ^# | \
		while read name dir server port description
		do
			echo $name
			echo $description
			echo $server
			echo $port
			echo $dir
		done | \
		zenity --title="Eternal Lands Launcher${non_standard}" --width=450 --height=280 \
			--list \
			--column "Name" \
			--column "Description" \
			--column "Server" \
			--column "Port" \
			--column "Directory" \
			--text "${title}"
		;;
	kdialog)
		sort -u $serverfile | tr -d '\015' | grep -v -e ^$ -e ^# | \
		while read name dir server port description
		do
			printf "${name}\0${dir}\t${server}\t${port}\t${description}\0"
		done | \
		xargs -0 kdialog --menu "${title}"
		;;
	dialog)
		sort -u $serverfile | tr -d '\015' | grep -v -e ^$ -e ^# | \
		while read name dir server port description
		do
			printf "${name}\0${dir}|${server}|${port}|${description}\0"
		done | \
		xargs -0 dialog --stdout --column-separator '|' \
			--menu "${title}" 0 0 10
		;;
	*)
		show_error "No method found to show the server selection screen\n"
		;;
	esac
}

# check which dialog method to use
for dialog in zenity kdialog dialog none; do
	command -v $dialog > /dev/null 2>&1 && break
done

# don't run as root
if [ "$(id -u)" = "0" ]
then
	show_error "Don't run as the root/administration user.\n\nJust don't!"
fi

# check the minimum packages are installed OK
if [ -x /usr/bin/dpkg ]
then
	installedOK=true
	[ -z "$(dpkg --list eternallands | grep ^ii)" ] && installedOK=false
	[ -z "$(dpkg --list eternallands-data | grep ^ii)" ] && installedOK=false
	if ! $installedOK
	then
		show_error "Eternal Lands is not completely installed. As root or using sudo, please run \"dpkg --configure -a\" to complete the install."
	fi
fi

# make sure the user config tree exists
mkdir -p ~/.elc/

# copy a servers.lst file if we don't have one
serverfile=~/.elc/servers.lst
if [ ! -r $serverfile -o ! -s $serverfile ]
then
	cp -p /usr/share/games/EternalLands/servers.lst $serverfile
fi
chmod +wr $serverfile

# see if we intend to use non-standard build
el_client=/usr/games/el.linux.bin
if [ -r ~/.elc/el_client ]
then
	tmp_el_client="$(cat ~/.elc/el_client)"
	if [ -x "$tmp_el_client" ]
	then
		non_standard=" (non-standard)"
		el_client="$tmp_el_client"
	fi
fi

# if no command line options specified, see if we want to use the config selection window
if [ "$*" = "" ]
then
	showsel=$HOME/.elc/showconfigsel
	defserver=$HOME/.elc/default_server_id.txt

	# optionally get the server/config option
	[ ! -r $showsel ] && touch $showsel
	if [ -n "$(grep yes $showsel)" -o ! -s $showsel ]
	then
		[ ! -s $showsel ] && rm -f $showsel
		config=""
		until [ -n "$config" ]
		do
			config="$(getconfig)"
			[ $? -ne 0 ] && exit 1
		done
	elif [ -r $defserver ]
	then
		config="$(cat $defserver)"
	else
		config="main"
	fi
	config="$(echo $config | awk -F\| '{print $1}')"

	# if not already configured, choose if to use the server/configuration selection window
	if [ ! -r $showsel ]
	then
		if yes_no "Do you want to choose each time you run the game?"
		then
			echo "yes" > $showsel
		else
			echo "no" > $showsel
			echo "$config" > $defserver
		fi
		show_info "To change this option, edit or remove the file:\n $showsel"
	fi
else
	config="$1"
	shift
fi

# make sure we have the config directory
config="$(basename $config)"
configdir="$(grep ^${config} $serverfile | awk {'print $2'})"
mkdir -p ~/.elc/${configdir}/
inifile=~/.elc/${configdir}/el.ini

# copy an el.ini file if we don't have one
if [ ! -r $inifile -o ! -s $inifile ]
then
	cp -p /usr/share/games/EternalLands/el.ini $inifile
fi
chmod +wr $inifile

# check the chosen el.ini file points to installed data
if [ ! -r ~/.elc/no.el.ini.check -a -n "$config" ]
then
	show_suppression=false
	if [ "$(grep -a ^#data_dir $inifile | tail -1 | grep -a '^#data_dir = /usr/share/games/EternalLands$')" = "" ]
	then
		if yes_no "Warning: $inifile does not use installed game data, shall I fix this problem?"
		then
			sed -i 's/^#data_dir.*$/#data_dir = \/usr\/share\/games\/EternalLands/g' $inifile
		else
			show_suppression=true
		fi
	fi
	if $show_suppression
	then
		show_info "To surpress these warnings, create the file:\n $HOME/.elc/no.el.ini.check"
	fi
fi

# run the client, display error log if it crashes
if ! $el_client $config $* &> ~/.elc/terminal_log.txt
then
	fout=$(mktemp)
	cat > $fout << EOT
Oh my, Eternal Lands Crashed - Don't Panic!

A few of things you can try:
1) Make sure your system is up to date, especially your video drivers.
2) If the client crashes repeatedly, try changing some settings.  Either by directly modifying the configuration file (e.g. gedit ~/.elc/main/el.ini). Or clicking the settings button window at the login screen.
	i) Enable the "Poor Man" option in the "Details" tab of the setting window.  Or edit the configuration file and set "#poor_man=1".
	ii) Disable the "Use animation program" option in the "Adv Video" tab of the setting window.  Or edit the configuration file and set "#use_animation_program=0".

If you continue to have problems check the Eternal Lands forums, especially the "Help Me" and "Bug Report" sections.  If you post a message make sure you include information about your system; i.e video driver and version, operating system and version.  Make sure you check your error log for clues too and include the contents in any forum report.

This information about your graphic hardware and software may help.
Output from "lspci | grep -i vga":
$(lspci | grep -i vga)
Output from "glxinfo | head -5":
$(glxinfo | head -5)

The following is your error log contents.  Note it is overwritten each time you run the game.

$(cat $(ls -1tr ~/.elc/log/main*.log | tail -1) /dev/null)

This was the program output:  Note it is overwritten each time you run the game.

$(cat ~/.elc/terminal_log.txt /dev/null)

A search through dmesg output:
$(dmesg | grep $(basename $el_client))

EOT
	show_text_info "Eternal Lands Crashed, this is the Error log." $fout
	rm -f $fout
	exit 1
fi
exit 0
