#!/bin/bash

# uncomment for very verbose script debugging...
#set -x

# Copyright (C) 2012-2016 by Debian Edu project, http://wiki.debian.org/DebianEdu
#       Mike Gabriel <mike.gabriel@das-netzwerkteam.de>

# Impressive PDF Display 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.
#
# Impressive PDF Display 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 this program; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.

# dependencies:
#     wmctrl
#     matchbox-window-manager
#     pulseaudio-utils
#
# recommendations:
#     unclutter
#     pulseaudio
#     x11-xserver-utils
#     texlive-extra-utils (for pdfnup)
#     poppler-utils (for pdfinfo)

VERSION="0.2.3"

PDF_URL="http://localhost"

WITH_PULSEAUDIO="yes"
HIDE_IDLE_POINTER="yes"

# There can be master terminals and slave display.
# All terminal not listed here are slave displays...
PRIMARY_DISPLAYS="$(hostname -f)"

# these terminals can have different startup URLs
PDF_URL_PRIMARIES=""
PDF_URL_SECONDARIES=""
PDF_URL_PRIMARIES_CREDS=""
PDF_URL_SECONDARIES_CREDS=""

PDF_FILE_PRIMARIES=""
PDF_FILE_SECONDARIES=""

# enforce fixed resolution for displays
# PRIMARIES_RESOLUTION="1920x1080"
# SLAVE_RESOLUTION="1920x1080"
PRIMARIES_RESOLUTION=
SLAVE_RESOLUTION=

# launch pulseaudio daemon if not already running
WITH_PULSEAUDIO="yes"

# hide idle mouse pointer
HIDE_IDLE_POINTER="yes"

# default screensaver settings
SCREENSAVER_SETTINGS=""

# don't use an HTTP proxy by default
HTTP_PROXY_URL=""

# interval of PDF continuous downloads
DOWNLOAD_INTERVAL="600"

# During rush hours check PDF file on remote URL more often
RUSH_HOURS="07-11"
RUSH_HOURS_DOWNLOAD_INTERVAL="180"

# Disable PDF downloads at night time completely...
SLEEP_HOURS="22-06"
SLEEP_HOURS_DOWNLOAD_INTERVAL="0"

# show each slide for 20 seconds by default
SLIDE_DURATION="20"

# option for impressive fading...
IMPRESSIVE_OPTIONS="--transition None"

# write some debugging output to stdout when downloading a remote PDF
DEBUG_DOWNLOADS=""

if [ -r $HOME/.impressive-display-secrets ] && [ ! -d $HOME/.impressive-display-secrets ]; then
	. $HOME/.impressive-display-secrets
fi

if [ -r /etc/default/impressive-display ] && [ ! -d /etc/default/impressive-display ]; then
	. /etc/default/impressive-display
fi

if [ -r $HOME/.impressive-display-rc ] && [ ! -d $HOME/.impressive-display-rc ]; then
	. $HOME/.impressive-display
fi

workdir="$HOME/.impressive-display"
mkdir -p "$workdir"
pdffile_previous="$workdir/impressive-pdffile-previous.pdf"
pdffile_downloaded="$workdir/impressive-pdffile-downloaded.pdf"
pdffile_display="$workdir/impressive-pdffile-display.pdf"

session_lock="$workdir/.session-lock.$$"
impressive_lock="$workdir/.impressive-lock"

# provide pulseaudio support in the browser session, if not
# already available...
if ! pacmd stat 1>/dev/null 2>/dev/null; then
	if [ "x$WITH_PULSEAUDIO" = "xyes" ]; then
		if which pulseaudio 1>/dev/null; then
			pulseaudio -D -n \
			           -L 'module-udev-detect' \
			           --exit-idle-time=65535
		fi
	fi
fi

# launch matchbox manager
if ! wmctrl -m 1>/dev/null 2>/dev/null; then
	if which matchbox-window-manager 1>/dev/null; then
		matchbox-window-manager 1>/dev/null 2>/dev/null&
	fi
fi

# use unclutter to hide idle mouse pointers
if [ "x$HIDE_IDLE_POINTER" = "xyes" ]; then
	if which unclutter 1>/dev/null; then
		unclutter 1>/dev/null 2>/dev/null &
	fi
fi

PDF_URL="$PDF_URL_SECONDARIES"
PDF_URL_CREDS="$PDF_URL_SECONDARIES_CREDS"
PDF_FILE="$PDF_FILE_SECONDARIES"
RESOLUTION="$SLAVE_RESOLUTION"

for primary_terminal in $PRIMARIES_TERMINALS; do
	if [ "x$(hostname -f)" = "x$primary_terminal" ]; then
		PDF_URL="$PDF_URL_PRIMARIES"
		PDF_URL_CREDS="$PDF_URL_PRIMARIES_CREDS"
		PDF_FILE="$PDF_FILE_PRIMARIES"
		RESOLUTION="$PRIMARIES_RESOLUTION"
		break
	fi
done

if [ -n "${RESOLUTION}" ]; then
	if which xrandr 1>/dev/null; then
		xrandr -d :0 --output default --mode ${RESOLUTION}
	fi
fi

# Set screensaver settings
if which xset 1>/dev/null; then
	xset s ${SCREENSAVER_SETTINGS}
fi

# set some proxy related env variables, if requested...
if [ -n "$HTTP_PROXY_URL" ]; then
	export http_proxy="$HTTP_PROXY_URL"
	export https_proxy="$HTTP_PROXY_URL"
	export ftp_proxy="$HTTP_PROXY_URL"
fi

rush_hours_start=`echo $RUSH_HOURS | grep -E '^[0-9]{2}-[0-9]{2}$' | sed  -n -r -e 's/^([0-9]{2})-([0-9]{2})$/\1/p'`
rush_hours_end=`echo $RUSH_HOURS | grep -E '^[0-9]{2}-[0-9]{2}$' | sed  -n -r -e 's/^([0-9]{2})-([0-9]{2})$/\2/p'`
sleep_hours_start=`echo $SLEEP_HOURS | grep -E '^[0-9]{2}-[0-9]{2}$' | sed  -n -r -e 's/^([0-9]{2})-([0-9]{2})$/\1/p'`
sleep_hours_end=`echo $SLEEP_HOURS | grep -E '^[0-9]{2}-[0-9]{2}$' | sed  -n -r -e 's/^([0-9]{2})-([0-9]{2})$/\2/p'`

function cleanup {

	if [ -r "$impressive_lock" ]; then
		impressive_pid=$(cat "$impressive_lock" | sed -e 's/[^0-9]*//g')
		if [ -n "$impressive_pid" ]; then
			kill -0 $impressive_pid 2>/dev/null && kill "$impressive_pid"
		fi
	fi

	for rmfile in $impressive_lock \
	              $session_lock \
	              $pdffile_previous \
	              $pdffile_downloaded \
	              $pdffile_display \
	              ;
	do
		if [ -e "$rmfile" ]; then
			rm "$rmfile"
		fi
	done

}

function pdf_is_portrait {

	if ! which bc 1>/dev/null; then
		echo "WARNING: The 'bc' command line tool is not installed on this system."
		return -1
	fi

	check_pdffile=$1
	if [ -n "$check_pdffile" ] && [ -r "$check_pdffile" ]; then

		pdfinfo \
		    -f 1 \
		    -l 1000 \
		 ${check_pdffile} \
		| grep "Page.* size:" \
		| while read Page _pageno size _width x _height rest; do 
			if [ "$(echo "${_width} / 1"|bc)" -gt "$(echo "${_height} / 1"|bc)" ]; then
			    let num_of_landscape_pages=num_of_landscape_pages+1 # Page is landscape...
			    echo "PAGE_IS_LANDSCAPE"
			    break
			fi
		done | tail -n1 | grep -q -E ".*PAGE_IS_LANDSCAPE.*" && return 1
		return 0
	else
		# something went wrong with the provided file name...
		return -1
	fi

}

function merge_portrait_documents {

	if which pdfnup 1>/dev/null ; then
		if pdf_is_portrait "$pdffile_downloaded"; then
			cd $(dirname "$pdffile_downloaded") && pdfnup "$pdffile_downloaded" && cd - 1>/dev/null
			mv "${pdffile_downloaded/.pdf/-nup.pdf}" "$pdffile_display"
		else
			cp "$pdffile_downloaded" "$pdffile_display"
		fi
	else
		echo "WARNING: The pdfnup tool is not installed."
		cp "$pdffile_downloaded" "$pdffile_display"
	fi

}

function local_pdffile {

	cp $PDF_FILE $workdir/$(basename $PDF_FILE)

	# is the PDF file gzipped?
	if echo $(basename $PDF_FILE) | grep -E ".*\.gz"; then
		PDF_FILE=${PDF_FILE/.gz/}
		gunzip $workdir/$(basename $PDF_FILE).gz
	fi
	mv $workdir/$(basename $PDF_FILE) "$pdffile_downloaded"

	merge_portrait_documents

}

function is_rush_hour {

	if [ -n "$rush_hours_start" ] && [ -n "$rush_hours_end" ]; then

		current_hour=`date +%H`
		if [ $rush_hours_end -gt $rush_hours_start ]; then

			if [ $rush_hours_start -le $current_hour  ] && [ $current_hour -lt $rush_hours_end ]; then
				echo "true"
				return 0
			fi

		else

			if [ $rush_hours_end -le $current_hour  ] && [ $current_hour -lt $rush_hours_start ]; then
				:
			else
				echo "true"
				return 0
			fi

		fi

	fi
	echo "false"
	return -1

}

function is_sleep_hour {

	if [ -n "$sleep_hours_start" ] && [ -n "$sleep_hours_end" ]; then

		current_hour=`date +%H`
		if [ $sleep_hours_end -gt $sleep_hours_start ]; then

			if [ $sleep_hours_start -le $current_hour  ] && [ $current_hour -lt $sleep_hours_end ]; then
				echo "true"
				return 0
			fi

		else

			if [ $sleep_hours_end -le $current_hour  ] && [ $current_hour -lt $sleep_hours_start ]; then
				:
			else
				echo "true"
				return 0
			fi

		fi

	fi
	echo "false"
	return -1

}

function download_pdffile {

	if [ -r "$pdffile_downloaded" ]; then
		cp "$pdffile_downloaded" "$pdffile_previous"
	fi
	if [ -n "$PDF_URL_CREDS" ]; then
		creds="-u $PDF_URL_CREDS"
	fi
	curl $creds "$PDF_URL" 1> "$pdffile_downloaded" 2>/dev/null

	if pdfinfo "$pdffile_downloaded" 1>/dev/null 2>/dev/null; then

		merge_portrait_documents

		cmp -s  "$pdffile_downloaded" "$pdffile_previous"> /dev/null
		if [ $? -eq 1 ]; then
			echo -n "RELOAD" > $impressive_lock
		fi

		pdffile=$pdffile_display

	else

		echo "WARNING: PDF file format problems. Maybe not a PDF file?"

	fi

}

function download_loop {

	# do an initial PDF retrieval..
	download_pdffile

	if [ "x$DOWNLOAD_INTERVAL" != "x0" ]; then
		(
			#set -x
			while [ -e "$session_lock" ]; do

				if [ -n "$DEBUG_DOWNLOADS" ]; then
					echo "DEBUG: rush hour: `is_rush_hour` (interval: $RUSH_HOURS_DOWNLOAD_INTERVAL), sleep hour: `is_sleep_hour` (interval: $SLEEP_HOURS_DOWNLOAD_INTERVAL). Normal interval: $DOWNLOAD_INTERVAL."
				fi

				if is_rush_hour 1>/dev/null && [ "x$RUSH_HOURS_DOWNLOAD_INTERVAL" != "x0" ]; then
					sleep $RUSH_HOURS_DOWNLOAD_INTERVAL
					if [ -n "$DEBUG_DOWNLOADS" ]; then
						echo "RUSH HOUR download, URL: $PDF_URL"
					fi
					download_pdffile
				elif is_sleep_hour 1>/dev/null  && [ "x$SLEEP_HOURS_DOWNLOAD_INTERVAL" != "x0" ]; then
					sleep $SLEEP_HOURS_DOWNLOAD_INTERVAL
					if [ -n "$DEBUG_DOWNLOADS" ]; then
						echo "SLEEP HOUR download, URL: $PDF_URL"
					fi
					download_pdffile
				elif (! is_rush_hour 1>/dev/null ) && (! is_sleep_hour 1>/dev/null) && [ "x$DOWNLOAD_INTERVAL" != "x0" ]; then
					sleep $DOWNLOAD_INTERVAL
					if [ -n "$DEBUG_DOWNLOADS" ]; then
						echo "NORMAL HOUR download, URL: $PDF_URL"
					fi
					download_pdffile
				else
					if [ -n "$DEBUG_DOWNLOADS" ]; then
						echo "DEBUG: Not doing any download."
					fi
					sleep 60
				fi
			done
			#set +x
		) &
	fi

}

function reloadable_impressive {

	if which impressive 1>/dev/null; then

		while [ -e "$session_lock" ]; do

			impressive ${IMPRESSIVE_OPTIONS} --fake-fullscreen --wrap -a ${SLIDE_DURATION} --nologo "${pdffile_display}" 1>/dev/null 2>/dev/null &
			impressive_pid=$!

			echo -n "$impressive_pid" > "$impressive_lock"

			while [ -r $impressive_lock ] && [ "$(cat $impressive_lock)" != "RELOAD" ] && [ -e "$session_lock" ]; do
				sleep 1
				if ! kill -0 "$impressive_pid" 2>/dev/null; then
					rm "$session_lock"
					break
				fi
			done

			kill -0 "$impressive_pid" 2>/dev/null && kill "$impressive_pid"

		done

	else
		echo "ERROR: The impressive application is not installed."
	fi

}


function create_lock {

	trap "cleanup" SIGINT SIGTERM ERR

	touch "$session_lock"

}

### MAIN ###

echo "INFO: $(basename $0) version $VERSION"

if [ -n "$PDF_URL" ]; then

	echo "INFO: PDF_URL is configured. Using PDF file from given URL: $PDF_URL"
	create_lock
	download_loop

elif [ -n "$PDF_FILE" ]; then

	echo "INFO: PDF_FILE is configured. Using local PDF file: $PDF_FILE"
	create_lock
	local_pdffile

else

	echo "ERROR: Neither PDF_FILE nor PDF_URL has been configured. Doing nothing."
	exit 0

fi

reloadable_impressive

exit 0
