#! /bin/bash
# Copyright (C) 2004, 2005 Stephen Bach
# This is script is a wrapper interface to the Viewglob package.
#
# Viewglob 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 2 of the License, or
# (at your option) any later version.
#
# Viewglob 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 Viewglob; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

SCRIPT_NAME="${0##*/}"
VG_LIB_DIR="/usr/lib/viewglob"
VGPING="$VG_LIB_DIR/vgping"

HOST_DEFAULT=localhost
PORT_DEFAULT=16108

# Execution configuration
REMOTE=
VGSEER_OPTS=
VGSEER_EXEC=vgseer
VGD_OPTS=

# We need extended globbing.
shopt -s extglob

vg_usage() {
	cat >&2 << EOF
usage: viewglob [-h <host>] [-p <port>] [-c <shell mode>] [-d <display>]
                [-s <sort style>] [-r <dir ordering>] [-t <on/off>]
                [-i <on/off>] [-z <font size modifier>]

-h, --host                  Host to connect to.            [localhost]
-p, --port                  Port to use or connect to.     [16108]
-c, --shell-mode            Shell to use (bash or zsh).    [bash]
-d, --display               Display program.               [vgmini]
-s, --sort-style            Windows (dirs first) or ls.    [ls]
-r, --dir-order             Directory list ordering.       [ascending]

-t, --shell-star            Asterisk character at prompt.  [on]
-i, --file-icons            File type icons in display.    [on]

-z, --font-size-modifier    Increase/decrease display font size.

-h, --help                  This usage.
-V, --version               Print the version.
EOF

	exit 0
}

vg_error() {
	echo "$SCRIPT_NAME: $1" >&2
	exit $2
}

vg_version() {
cat << EOF
viewglob 2.0.4
Released April 26, 2006
EOF
	exit 0
}


# Option verification functions

vg_test_shell_mode() {
	if [ "$1" != bash ] && [ "$1" != zsh ]
		then vg_error "Shell mode must be \"bash\" or \"zsh\"" 1
	fi
}

vg_test_display() {
	if [ ! "$1" ]
		then vg_error "No display program specified" 1
	elif [ "$1" = vgmini ] || [ "$1" = vgclassic ]
		then vg_disp="$VG_LIB_DIR/$1"
	else
		vg_disp="$1"
	fi

	if [ ! -x "$vg_disp" ]
		then vg_error "$1 is not present or not executable" 1
	fi
}

vg_test_sort_style() {
	if [ "$1" != ls ] && [ "$1" != win ]
		then vg_error "Unknown sort style \"$1\"" 1
	fi
}

vg_test_dir_order() {
	if [ "$1" != descending ] && \
	   [ "$1" != ascending ] && \
	   [ "$1" != ascending-pwd-first ]
		then vg_error "Invalid directory ordering \"$1\"" 1
	fi
}

vg_test_font_size_modifier() {
	if [[ "$1" != ?([-+])*([0-9]) ]]
		then vg_error "Invalid font size modifier" 1
	fi
}

vg_test_onoff() {
	if [[ "$OPTARG" != on ]] && [[ "$OPTARG" != off ]]
		then vg_error "Argument must be \"on\" or \"off\"" 1
	fi
}


if [[ "$VG_VIEWGLOB_ACTIVE" = yep ]]
	then vg_error "This shell is already being monitored" 2
elif [[ -z "$DISPLAY" ]]
	then REMOTE=yep
elif [[ -z "$TERM" ]] || [[ "$TERM" = dumb ]]; then
	# There's no terminal associated with the shell, but an X display is
	# present, so make a new xterm.  Try to use gconf-tool2 to determine
	# a usable terminal program.

	GCONF='gconftool-2'
	if [ `which ${GCONF} 2>/dev/null` ]; then
		TERM_EXEC="`${GCONF} -g \
			/desktop/gnome/applications/terminal/exec \
			2>/dev/null`"
		TERM_EXEC_ARG="`${GCONF} -g \
			/desktop/gnome/applications/terminal/exec_arg \
			2>/dev/null`"
	fi

	if [ -z "$TERM_EXEC" ] || [ -z "$TERM_EXEC_ARG" ]; then
		# Fallback to xterm.
		if [ -n "`which x-terminal-emulator 2>/dev/null`" ] ; then
			TERM_EXEC=x-terminal-emulator
		else
			TERM_EXEC=xterm
		fi
		TERM_EXEC_ARG=-e
	fi

	VGSEER_EXEC="$TERM_EXEC $TERM_EXEC_ARG $VGSEER_EXEC"
fi

# This is an excellent script to replace bash's getopts with one which allows
# long names.  It's written by Grigoriy Strokin.
. $VG_LIB_DIR/getopt.sh

# Parse the options.
while getoptex "h: p: i: c: d: r: s: t: H; v; V; z: host: port: shell-mode: display: font-size-modifier: sort-style: dir-order: shell-star: file-icons: help; version;" "$@"
	do case "$OPTOPT" in

		h|host)
			REMOTE=yep
			HOST="$OPTARG"
			VGSEER_OPTS="$VGSEER_OPTS --host=$OPTARG"
			;;

		p|port)
			VGSEER_OPTS="$VGSEER_OPTS --port=$OPTARG"
			PORT="$OPTARG"
			VGD_OPTS="$VGD_OPTS --port=$OPTARG"
			;;

		i|file-icons)
			vg_test_onoff "$OPTARG"
			VGD_OPTS="$VGD_OPTS --file-icons $OPTARG"
			;;

		c|shell-mode)
			vg_test_shell_mode "$OPTARG"
			VGSEER_OPTS="$VGSEER_OPTS --shell-mode=$OPTARG"
			;;

		d|display)
			vg_test_display "$OPTARG"
			VGD_OPTS="$VGD_OPTS --display=$OPTARG"
			;;

		s|sort-style)
			[ "$OPTARG" == windows ] && OPTARG=win
			vg_test_sort_style "$OPTARG"
			VGD_OPTS="$VGD_OPTS --sort-style=$OPTARG"
			;;

		r|dir-order)
			vg_test_dir_order "$OPTARG"
			VGD_OPTS="$VGD_OPTS --dir-order=$OPTARG"
			;;

		t|shell-star)
			vg_test_onoff "$OPTARG"
			VGSEER_OPTS="$VGSEER_OPTS --shell-star $OPTARG"
			;;

		z|font-size-modifier)
			vg_test_font_size_modifier "$OPTARG"
			VGD_OPTS="$VGD_OPTS --font-size-modifier=$OPTARG"
			;;

		H|help) vg_usage ;;

		v|V|version) vg_version ;;

		*) vg_error "invalid argument" 3 ;;
	esac
done
shift $((OPTIND - 1))

if [ "$OPTOPT" = \? ]
	# getopt.sh already emitted an error message.
	then exit 5
fi

# Just in case the user has turned daemonizing off in vgd.conf.
VGD_OPTS="$VGD_OPTS --daemon=on"

if [ -z "${HOST}${PORT}" ]; then
	# A local connection is assumed.

	VGSEER_OPTS="$VGSEER_OPTS --unix-socket=on"
	
	vgd_ports=
	nvgds=0

	# Create list of active sockets, and clean out inactive ones (if any).
	for file in $HOME/.viewglob/.*; do
		if [[ $file == */.+([0-9]) ]]; then
			if $VGPING dummy ${file##*/}; then
				vgd_ports="$vgd_ports ${file##*/.}"
				nvgds=`expr $nvgds + 1`
			else
				rm -f $file
			fi
		fi
	done

	if [ $nvgds -eq 0 ]; then
		# There are no active vgds.

		# Find an unused port for vgd and create new vgd and vgseer
		# processes.
		port=$PORT_DEFAULT
		while true; do

			while true; do
			    if $VGPING localhost $port
				then port=`expr $port + 1`
			    else
				break
			    fi
			done

			vgd $VGD_OPTS --port $port

			case "$?" in
				0)
					exec $VGSEER_EXEC $VGSEER_OPTS \
						--port $port ;;
				2)
					# Socket error -- try another port.
					continue ;;
				*)
					# Other error -- give up.
					break ;;
			esac
		done

	elif [ $nvgds -eq 1 ]; then
		# There is a single active vgd.
		exec $VGSEER_EXEC $VGSEER_OPTS --port $vgd_ports
	else
		echo "There are active vgds on the following local ports:"
		for port in $vgd_ports; do
			echo "	$port"
		done
	fi
else
	test -z "$HOST" && HOST=$HOST_DEFAULT
	test -z "$PORT" && PORT=$PORT_DEFAULT

	if [ "$REMOTE" = yep ]; then
		# We're running in a displayless environment or the user
		# specified a host to connect to.  Either case implies we're
		# not connecting locally, and so we shouldn't create a vgd.

		VGSEER_OPTS="$VGSEER_OPTS --unix-socket=off"

		if ! $VGPING $HOST $PORT ; then
			vg_error "Couldn't handshake with a vgd at \
				${HOST}:${PORT}" 6
		fi

		exec $VGSEER_EXEC $VGSEER_OPTS --unix-socket=off

	else
		VGSEER_OPTS="$VGSEER_OPTS --unix-socket=on"
		
		# First check for an existing vgd.  If there is one, connect
		# to it.
		if $VGPING $HOST .$PORT ; then
			exec $VGSEER_EXEC $VGSEER_OPTS
		fi

		# We'll have to setup a new vgd, then exec.
		if vgd $VGD_OPTS ; then
			exec $VGSEER_EXEC $VGSEER_OPTS
		fi
	fi
fi

