#!/bin/bash

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

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

# 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.3.3"

# Can be configured at "/etc/default/impressive-display"
DEFAULT_PDF_URI="file:///usr/share/doc/impressive-display/impressive-display.pdf.gz"
DEFAULT_RESOLUTION=""

# all displays that need to be changed
declare -A DISPLAYS

# 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"

LOG_TO_SYSLOG=

# 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="5"

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

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

if type -p xrandr 1>/dev/null; then
	currentOutput=`echo "$(xrandr)" | grep -w 'connected' | sed -r -e 's/connected.*//' | head -n 1`
fi

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

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

if [ "x$LOG_TO_SYSLOG" = "xyes" ]; then
	OUTPUT="logger -t impressive-display"
else
	OUTPUT="echo"
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 impressive display 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

# if FAKE_HOSTNAME is not empty, use that string for hostname
THIS_HOSTNAME=$(hostname -f)
if [ -n "$FAKE_HOSTNAME" ]; then
	THIS_HOSTNAME="$FAKE_HOSTNAME"
fi


if `echo ${!DISPLAYS[@]} | grep -q "$THIS_HOSTNAME"`; then 
	$OUTPUT "INFO: $THIS_HOSTNAME has extra properties. loading them.."

	if echo ${DISPLAYS[$THIS_HOSTNAME]} | grep -q "pdf_uri="; then
		PDF_URI=`echo ${DISPLAYS[$THIS_HOSTNAME]} | sed -r -e 's/(^|.*\|)pdf_uri=([^|]*).*/\2/'`
	else
		PDF_URI="$DEFAULT_PDF_URI"
	fi

	if echo ${DISPLAYS[$THIS_HOSTNAME]} | grep -q "res="; then
		RESOLUTION=`echo ${DISPLAYS[$THIS_HOSTNAME]} | sed -r -e 's/(^|.*\|)res=([^|]*).*/\2/'`
	else
		RESOLUTION="$DEFAULT_RESOLUTION"
	fi
else
	PDF_URI="$DEFAULT_PDF_URI"
	RESOLUTION="$DEFAULT_RESOLUTION"
fi

if ! echo "$PDF_URI" | grep -q -E "^(file://|http://|https://).*"; then
	$OUTPUT "ERROR: PDF_URI format not supported: $PDF_URI"
	$OUTPUT "       Use file://<path>/<file>.pdf(.gz) or http(s)://<host>/<path>/<file>.pdf. Doing nothing."
	exit -1
fi

if [ -n "${RESOLUTION}" ]; then
	if type -p xrandr 1>/dev/null; then
		xrandr -d :0 --output "$(echo $currentOutput)" --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 type -p xrandr 1>/dev/null; then
		$OUTPUT "Info: resetting resolution"
		xrandr -d :0 --output "$(echo $currentOutput)" --auto
	fi

	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

}
trap "cleanup" SIGINT SIGTERM ERR EXIT

function pdf_is_portrait {

	if ! which bc 1>/dev/null; then
		$OUTPUT "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
		$OUTPUT "WARNING: The pdfnup tool is not installed."
		cp "$pdffile_downloaded" "$pdffile_display"
	fi

}

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
	
	DOWNLOADED_FILE="$workdir/$(basename $PDF_URI)"
	if [ -f "$workdir/secrets/default.secret" ]; then
		NETRCFILE=" --netrc-file $workdir/secrets/default.secret"
	fi
	if [ -f "$workdir/secrets/$THIS_HOSTNAME.secret" ]; then
		NETRCFILE=" --netrc-file $workdir/secrets/${THIS_HOSTNAME}.secret"
	fi

	if [ "x$LOG_TO_SYSLOG" = "xyes" ]; then
		if ! curl $NETRCFILE "$PDF_URI" 1> "$DOWNLOADED_FILE" 2>/dev/null; then
			$OUTPUT "The curl tool failed in retrieving PDF file. Run this tool interactively to debug problems."
		fi
	else
		curl $NETRCFILE "$PDF_URI" 1> "$DOWNLOADED_FILE"
	fi

	# is the PDF file gzipped?
	if echo "$DOWNLOADED_FILE" | grep -q -E '.*\.gz$'; then
		gunzip -f "$DOWNLOADED_FILE"
		mv "${DOWNLOADED_FILE/.gz/}" "$pdffile_downloaded"
	else
		mv "${DOWNLOADED_FILE}" "$pdffile_downloaded"
	fi

	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
			$OUTPUT "INFO: Triggering PDF file reload, PDF file has changed..."
		fi

		pdffile=$pdffile_display

	else

		$OUTPUT "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
		(
			while [ -e "$session_lock" ]; do

				if [ -n "$DEBUG_DOWNLOADS" ]; then
					$OUTPUT "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
						$OUTPUT "INFO: RUSH HOUR download, URL: $PDF_URI"
					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
						$OUTPUT "INFO: SLEEP HOUR download, URL: $PDF_URI"
					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
						$OUTPUT "INFO: NORMAL HOUR download, URL: $PDF_URI"
					fi
					download_pdffile
				else
					if [ -n "$DEBUG_DOWNLOADS" ]; then
						$OUTPUT "DEBUG: Not doing any download."
					fi
					sleep 60
				fi
			done
		) &
	fi

}

function reloadable_impressive {

	if which impressive 1>/dev/null; then

		while [ -e "$session_lock" ]; do

			# FIXME: display error msg if no PDF file could be retrieved

			$OUTPUT "INFO: Starting a new instance of the impressive application."
			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"
			$OUTPUT "INFO: The impressive application has terminated."

		done

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

}


function create_lock {

	touch "$session_lock"

}

### MAIN ###

$OUTPUT "INFO: IMPRESSIVE Display (version $VERSION)"
$OUTPUT "INFO: HOSTNAME set to: $THIS_HOSTNAME"

if [ -n "$PDF_URI" ]; then

	$OUTPUT "INFO: PDF_URI is configured. Using PDF file from given URL: $PDF_URI"
	create_lock
	download_loop

else

	$OUTPUT "ERROR: PDF_URI hasn't been configured. Doing nothing."
	exit 0

fi

reloadable_impressive

exit 0
