#!/bin/bash
#
# __copy1__
# __copy2__
#
# write message on stderr, and notify user using first
# available method of a defined stack (not parametric,
# at the moment, in the future it will be external
# defined, and dependent on various scenarios)
#
CMD=`basename $0`


list_queue()
{
	(cd $bufdir ; ls -t "$sanitized_title".*.msg 2>/dev/null)
}

last_flush()
{
	local lastflush=`(cd $bufdir ; ls -t "$sanitized_title".lastflush 2>/dev/null)`

	if [ "$lastflush" != "" ]
	then
		stat --format '%Y' "$bufdir/$lastflush"
	else
		echo 0
	fi
}



# flushes notifications buffer (bufdir), trying to interfere
# with concurrent invocations of this command
#
flush_notify()
{
	local text=
	local folded=
	local msgfile=
	local foldfile=
	local iconfile=
	local remove=

	for msgfile in `list_queue`
	do
		[ -f "$bufdir/$msgfile" ] && {
			case $msgfile in
		  		*.flushed) continue ;;
			esac
			text="${text}`cat \"$bufdir/$msgfile\"`"
			mv "$bufdir/$msgfile" "$bufdir/$msgfile.flushed"
			foldfile=`echo "$msgfile" | sed -e 's/\.msg$/\.folded/'`
			folded="${folded}`cat \"$bufdir/$foldfile\"`"
			remove="$remove$bufdir/$msgfile.flushed\n$bufdir/$foldfile\n"
		}
	done

	case $xcmd in
	  */zenity)
	  	[ "$DISPLAY" == "" ] && return
	  	$xcmd --info --text "$msg"
		;;
	  */xmessage)
	  	[ "$DISPLAY" == "" ] && return
		echo "$msg" | $xcmd -center -file -
		;;
	  */notify-send)
	  	iconfile=`search_icon "$icon"` && iconfile="--icon '$iconfile'"
	  	$xcmd $iconfile "$title" "$text"
		;;
	esac

	# cleanup
	echo -en "$remove" | while read msgfile
	do
		rm -f "$msgfile"
	done

	# mark last flush timestamp
	cp /dev/null "$bufdir/$sanitized_title.lastflush"

	return 0
}

listicons()
{
	cd /usr/share/icons
	ls ku-notify-* 2>/dev/null
}

search_icon()
{
	local icon=$1
	local file=
	for file in "$icon" "/usr/share/icons/$icon" "/usr/share/icons/ku-notify-$icon.png"
	do
		[ -f "$file" ] && {
			echo "$file"
			return 0
		}
	done

	# last resort
	echo "ku-notify-$icon"
	return 0
}


usage()
{
	echo "
usage:	$CMD [options] title message
	$CMD --listicons

options:
  -n		no newline
  --nobuf	don't buffer
  --nofold	don't fold long lines (default: uses 'fold' command)
  --flush	flushes notifications buffer
  --interval n	set display interval (in seconds, default=$interval)
  --icon str	set icon or iconfile (see /usr/share/icons tree, or
  		--listicons to show default KU notifications icons)
  --cols n	overrides column width (now: $columns)
" >&2
	exit 127
}


# (MAIN)

f_nl=true
f_buf=true
f_fold=true
f_flush=false

xcmd=
msg=
title=
sanitized_title=
bufdir="/var/tmp/$CMD"
interval=6	# seconds
newlineopt=
columns=${COLUMNS:-"80"}
icon="default"

[ "X$1" == "--listicons" ] && {
	list_icons
	exit 0
}

while [ $# != 0 ]
do
  case "$1" in 
    -n)		f_nl=false ;;
    --nobuf)	f_buf=false ;;
    --nofold)	f_fold=false ;;
    --flush)	f_flush=true ;;
    --interval)
    	shift
	case $1 in
		[0-9]*)	interval=$1 ;;
	 	*)	usage ;;
	esac
	;;
    --cols)
    	shift
	case $1 in
		[0-9]*)	columns=$1 ;;
	 	*)	usage ;;
	esac
	;;
    --icon)
    	shift
	[ $# == 0 ] && usage
	icon=$1
	;;
    -*)		usage ;;
    *)
    	if [ "X$title" == "X" ]
	then
		title="$1"
	else
		msg="${msg}$1"
	fi
	;;
  esac
  shift
done

[ "X$title" == "X" ] && usage
[ "X$msg" == "X" ] && usage

sanitized_title=$(echo "X$title" | sed -e 's/[^a-zA-Z0-9]*//g' -e 's/^X//')

$f_nl || newlineopt="-n"


if $f_fold
then
	folded=`echo -e$newlineopt "$msg" | fold -s -w $columns`
else
	folded=`echo -e$newlineopt "$msg"`
fi

# writes on stderr
echo "$folded" >&2

# search X notification command
#
for cmd in notify-send zenity xmessage
do
	xcmd=`which $cmd 2>/dev/null`
	[ "$xcmd" != "" ] && break
done


# buffering / flushing

[ -d $bufdir ] || mkdir $bufdir

now=`date +%s`

echo -n "$msg" >"$bufdir/$sanitized_title.$now.msg"
echo -n "$folded" >"$bufdir/$sanitized_title.$now.folded"

if $f_flush
then
	flush_notify
else
	last=`last_flush`
	diff=`expr $now - $last`
	[ $diff -gt $interval ] && flush_notify
fi

exit 0
