#!/bin/bash

# Opens a URL or local file in a new web browser window/tab.
# Starts web browser if needed.
# Multiple arguments are each opened.
# Uses X11-based browser, if possible.
# Opens new xterm with text-based browser if no X11-browser available.
# Uses text-based browser (one at a time) if DISPLAY is unset.

######################################################################
# constants

# How long to wait after starting a new X browser instance before
# firing more commands at it.  Given to sleep(1).
start_delay=2

######################################################################
# functions

# ----------------------------------------------------------------------
function die () {
# abort program with message

echo "$*" > /dev/stderr
exit 1

}

# ----------------------------------------------------------------------
function decho () {
# debug echo - only echo if DEBUG is set

[ -z "$DEBUG" ] && return
echo "$*" > /dev/stderr

}

# ----------------------------------------------------------------------
function find_a_prog () {
# find a program, from a list of possibilities
# if nothing found, no output

local poss found

unset found
for poss in "$@" ; do
	decho "find_a_prog: trying <$poss>"
	found=$(which "$poss" 2>/dev/null)	# does it exist in PATH?
	[ -n "$found" ] && break		# we found one
done

if [ -n "$found" ]; then # found one
	# only interested in basename
	found=$(basename "$found")
	decho "find_a_prog: found <$found>"
	echo "$found"
	return 0
else
	decho "find_a_prog: found nothing"
	return 1
fi

}

# ----------------------------------------------------------------------
function find_X_browser () {
# figure out which X11-based browser is available

Xbase=$(find_a_prog firefox iceweasel mozilla netscape)

# if nothing was found, don't try the rest
[ -z "$Xbase" ] && return

# figure out where stuff is, based on distribution
if [ -e /etc/redhat-release ] && rpm -q firefox > /dev/null 2>&1 ; then
	mozver=$(rpm -q firefox --qf '%{version}')
	binprefix="/usr/lib/${Xbase}-${mozver}/"
elif [ -e /etc/debian_version ]; then
	# on Debian, "firefox" is an alias for iceweasel
	[ $"Xbase" = firefox ] && Xbase=iceweasel
	binprefix="/usr/lib/${Xbase}/"
else
	# unknown distro, assume everything is in PATH
	binprefix=""
fi
decho "Xbase=<$Xbase> binprefix=<$binprefix>"

Xrmt="${binprefix}${Xbase}-xremote-client"
Xmain="${Xbase}"
decho "Xmain=<$Xmain> Xrmt=<$Xrmt>"

}

# ----------------------------------------------------------------------
function find_text_browser () {
# figure out which text-based browser is available

textbrowser=$(find_a_prog elinks links lynx)
decho "textbrowser=<$textbrowser>"

# if we could not find one, die
[ -z "$textbrowser" ] && die "Could not find a text-based web browser."

}

# ----------------------------------------------------------------------
function open_browser () {

if [ -n "$Xbase" ]; then
	# open in X11-based browser
	open_X_browser "$1"
elif [ -n "$DISPLAY" ]; then
	# DISPLAY set but no X11 browser, use xterm and text browser
	xterm -e "$textbrowser" "$@" &
else
	# no DISPLAY, use text-based browser (in this terminal)
	"$textbrowser" "$@"
fi

}
	
# ----------------------------------------------------------------------
function open_X_browser () {

local arg

arg="$1"
decho "open_X_browser called with arg=<$arg>" 

# are we already running?
if $Xrmt 'ping()' 2>/dev/null ; then
	Xrunning=1
else
	unset Xrunning
fi
decho "Xrunning=<$Xrunning>"

# if no arg, just open a new window
if [ -z "$arg" ]; then
	decho "opening new window with no argument"
	if [ -n "$Xrunning" ]; then
		# attempt to send command, return that exit status
		decho "opening in existing process"
		$Xrmt 'xfeDoCommand(openBrowser)'
		return $?
	else
		# start a new instance in background
		start_new_X_browser
		return 0 # have to assume it worked
	fi
fi

# we have an arg -- is it a file or a URL?
if [ -e "$arg" ]; then
	# if arg exists as a file, we assume user wanted to open it
	decho "opening file, not URL"
	# we just have to figure out how
	if echo "$arg" | egrep -q '^[[:space:]]*/' ; then
		# if file has absolute path, just prefix it
		arg="file://$arg"
	else
		# otherwise, need to make it absolute
		# assume relative to $PWD
		arg="file://$PWD/$arg"
	fi
	# else - did not exist as a file - pass it verbatim to browser
fi

# okay, so now we have an arg that is ready to go
decho "arg=<$arg>"

if [ -n "$Xrunning" ]; then
	# attempt to send command, return that exit status
	decho "opening in existing process"
	$Xrmt "openurl($arg,new-tab)"
	return $?
else
	start_new_X_browser "$arg" &
	return 0 # have to assume it worked
fi

die "should never get here"

}

# ----------------------------------------------------------------------
function start_new_X_browser () {

decho "start_new_X_browser called with 1=<$1>"

$Xmain "$@" &

# give it time to start, if more args to follow
[ -n "$start_delay" ] && sleep "$start_delay" 

}

######################################################################
# main

# figure out what browser to use
if [ -z "$DISPLAY" ]; then # no DISPLAY ...
	find_text_browser
else # DISPLAY present
	find_X_browser
	# fall back to text-browser if no X browser available
	[ -z "$Xbase" ] && find_text_browser
fi

# open browser(s)
if [ "$#" = 0 ]; then # no arguments
	# just open a new browser
	open_browser
else # arguments present
	# do not delay if only one argument
	[ "$#" = 1 ] && unset start_delay
	# open browser(s) for each arg
	while [ "$#" -gt 0 ]; do
		open_browser "$1"
		shift
	done
fi

######################################################################
# EOF "web" shell script
######################################################################
