# -*- sh -*-
# vim:ft=sh:ts=8:sw=4:noet

XSTATUS_SUSPEND_TEXT="Preparing to suspend..."
XSTATUS_RESUME_TEXT="Resuming from suspend..."
XOSD_SETTINGS="--font '-misc-fixed-medium-r-semicondensed--*-120-*-*-c-*-*-*' --colour=Green --shadow 1 --pos bottom --align center --offset 50"

AddConfigHandler XStatusOptions
AddConfigHelp "XStatus <gnome|kde|x>" "Enables progress display and error reporting for the given environment."
AddConfigHelp "XSuspendText <message>" "Text to display on screen whilst preparing to suspend. (default: \"$XSTATUS_SUSPEND_TEXT\")"
AddConfigHelp "XResumeText <message>" "Text to display on screen whilst coming back from suspend. (default: \"$XSTATUS_RESUME_TEXT\")"
AddConfigHelp "XosdSettings <options>" "Options to pass to osd_cat, see 'man osd_cat' (default: \"$XOSD_SETTINGS\")"

### KDE bits:

XStatusProgressStart_kde() {
    KDEPB_DCOPREF=

    # Lookup dcop, we expect kdialog and kstart to sit there, too.
    if [ "x$DISTRIBUTION" = "xgentoo" ] && ! command -v dcop > /dev/null 2>&1 ; then
	# Gentoo stashes this in a silly place.
	for i in /usr/kde/*/bin/dcop ; do
	    if [ -x "$i" ] ; then
		PATH=$PATH:${i%%/dcop}
		export PATH
		break
	    fi
	done
    fi

    if ! command -v dcop > /dev/null 2>&1 ; then
	vecho 0 'Cannot connect to kdialog. `dcop` program not found.'
	return 1 # abort, unless forced
    fi

    KDEPB_DCOPREF="`su $XUSER -c \"kstart --windowclass KDialog --alldesktops kdialog --title Hibernating --progressbar \\\"$1\\\" 100\"`"
    su $XUSER -c "dcop \"$KDEPB_DCOPREF\" showCancelButton 1"
}

XStatusProgressCheckCancel_kde() {
    [ -z "$KDEPB_DCOPREF" ] && return 0

    local was_cancelled
    was_cancelled=`su $XUSER -c "dcop \"$KDEPB_DCOPREF\" wasCancelled"`
    [ x"$was_cancelled" = "xtrue" ] && SUSPEND_ABORT=1
}

XStatusProgressUpdate_kde() {
    [ -z "$KDEPB_DCOPREF" ] && return 0

    su $XUSER -c "dcop \"$KDEPB_DCOPREF\" setProgress $XSTATUS_PROGRESS"
    XStatusProgressCheckCancel_kde
}

XStatusProgressKill_kde() {
    [ -z "$KDEPB_DCOPREF" ] && return 0

    XStatusProgressCheckCancel_kde
    su $XUSER -c "dcop \"$KDEPB_DCOPREF\" close"
}

XStatusReportErrors_kde() {
    kstart --windowclass KDialog --alldesktops kdialog --title Hibernating --error "$1" > /dev/null 2>&1
}

### Gnome bits:

XStatusProgressPIPEhandler_gnome() {
    ZENITY_OPEN=
    XStatusProgressKill_gnome
}

XStatusProgressStart_gnomeZenityHelper() {
    zenity_hup_handler() {
	[ -n "$pid_to_kill" ] && kill -INT $pid_to_kill
    }
    trap zenity_hup_handler HUP
    zenity --progress --auto-close --title="Hibernate" --text="$1" || kill -INT $pid_to_kill
    exit 0
}

XStatusProgressStart_gnome() {
    trap XStatusProgressPIPEhandler_gnome PIPE
    pid_to_kill=`/bin/sh -c 'echo $PPID'`
    if [ -n "$NEED_POSIX" ] ; then
	[ -p $ZENITY_FIFO ] && rm -f $ZENITY_FIFO
	ZENITY_FIFO=`mktemp /tmp/tmp.hibernate.XXXXXX`
	rm -f $ZENITY_FIFO
	mknod $ZENITY_FIFO p
	XStatusProgressStart_gnomeZenityHelper "$1" < $ZENITY_FIFO &
	ZENITY_PID=$!
	exec 8>$ZENITY_FIFO
    else
	eval "exec 8> >(XStatusProgressStart_gnomeZenityHelper \"$1\")" || return
    fi
    echo $XSTATUS_PROGRESS >&8
    ZENITY_OPEN=1
}

XStatusProgressUpdate_gnome() {
    [ -n "$ZENITY_OPEN" ] && echo $XSTATUS_PROGRESS >&8
    [ x"$XSTATUS_PROGRESS" = "x100" ] && ZENITY_OPEN=
}

XStatusProgressKill_gnome() {
    [ -n "$ZENITY_OPEN" ] && echo 100 >&8
    exec 8>&-
    [ -p "$ZENITY_FIFO" ] && rm -f $ZENITY_FIFO && ZENITY_FIFO=
    [ -n "$ZENITY_PID" ] && sleep 0.2 && kill $ZENITY_PID > /dev/null 2>&1
    ZENITY_OPEN=
}

XStatusReportErrors_gnome() {
    ( zenity --error --title "Hibernate" --text "$1" < /dev/null > /dev/null 2>&1 & )
}

### X bits:

XStatusProgressStart_xXmessageHelper() {
    xmessage_exit_handler() {
	kill -TERM $xmessage_pid
	exit 0
    }
    trap xmessage_exit_handler HUP QUIT INT TERM
    su $XUSER -c "xmessage -buttons 'Cancel:44' -default 'Cancel' -center -title Hibernate \"$1\"" < /dev/null > /dev/null 2>&1 &
    xmessage_pid=$!
    wait $xmessage_pid
    [ $? -eq 44 ] && kill -INT $pid_to_kill > /dev/null 2>&1
    exit 0
}

XStatusProgressStart_x() {
    local new_pid
    if [ -z "$NO_XOSD" ] ; then
	XOSD_TEXT=$1

	new_pid=`( su $XUSER -c "osd_cat $XOSD_SETTINGS --barmode=percentage --percentage=$XSTATUS_PROGRESS --text \"$XOSD_TEXT\"" < /dev/null > /dev/null 2>&1 & echo $! )`
	XOSD_PIDS="$XOSD_PIDS $new_pid"
    fi

    pid_to_kill=`/bin/sh -c 'echo $PPID'`
    XStatusProgressStart_xXmessageHelper "$1" &
    XMESSAGE_PIDS="$XMESSAGE_PIDS $!"
}

XStatusProgressUpdate_x() {
    [ -n "$NO_XOSD" ] && return 0

    local new_pid

    new_pid=`( su $XUSER -c "osd_cat $XOSD_SETTINGS --barmode=percentage --percentage=$XSTATUS_PROGRESS --text \"$XOSD_TEXT\"" < /dev/null > /dev/null 2>&1 & echo $! )`
    XOSD_PIDS="$new_pid $XOSD_PIDS"
}

XStatusProgressKill_x() {
    [ -n "$XOSD_PIDS" ] && kill $XOSD_PIDS > /dev/null 2>&1
    [ -n "$XMESSAGE_PIDS" ] && kill $XMESSAGE_PIDS > /dev/null 2>&1
    XOSD_PIDS=
    XMESSAGE_PIDS=
}

XStatusReportErrors_x() {
    ( /bin/echo -ne "$1" | su $XUSER -c "xmessage -buttons 'Ok:0' -default 'Ok' -center -title 'Hibernate' -file - > /dev/null 2>&1" & )
}

### Wrapper routines:

XStatusSuspendBegin() {
    [ -z $XSTATUS ] && return 0

    XSTATUS_PROGRESS=10
    XStatusProgressStart_$XSTATUS "$XSTATUS_SUSPEND_TEXT"

    return 0
}

XStatusResumeBegin() {
    [ -z $XSTATUS ] && return 0

    XSTATUS_PROGRESS=10
    XStatusProgressStart_$XSTATUS "$XSTATUS_RESUME_TEXT"

    return 0
}

XStatusProgress() {
    [ -z $XSTATUS ] && return 0

    XSTATUS_PROGRESS=$(($XSTATUS_PROGRESS+10))
    XStatusProgressUpdate_$XSTATUS

    return 0
}

XStatusProgressKill() {
    [ -z $XSTATUS ] && return 0

    XSTATUS_PROGRESS=$(($XSTATUS_PROGRESS+10))
    XStatusProgressKill_$XSTATUS

    return 0
}

XStatusReportErrors() {
    [ -z "$XSTATUS" ] && return 0
    [ -z "$ERROR_TEXT" ] && return 0

    XStatusReportErrors_$XSTATUS "$ERROR_TEXT"

    return 0
}

### Hook us in:

XStatusOptions() {
    local foo
    case $1 in
	xstatus)
	    foo=`echo $2|tr '[A-Z]' '[a-z]'`
	    case $foo in
		gnome|kde|x)
		    XSTATUS=$foo
		    ;;
		*)
		    vecho 0 "$EXE: Invalid value for $1 option."
		    exit 1
		    ;;
	    esac
	    ;;
	xsuspendtext)
	    shift
	    XSTATUS_SUSPEND_TEXT="$*"
	    ;;
	xresumetext)
	    shift
	    XSTATUS_RESUME_TEXT="$*"
	    ;;
	xosdsettings)
	    shift
	    XOSD_SETTINGS="$*"
	    ;;
	*)
	    return 1
    esac

    if [ x"$XSTATUS" = "xx" ] && ! command -v osd_cat > /dev/null 2>&1 ; then
	NO_XOSD=1
    fi
    XOSD_PIDS=
    XMESSAGE_PIDS=

    if FindXServer && [ -z "$XSTATUS_HOOKED" ] ; then
	# We can do a pretty progress bar!
	AddSuspendHook 05 XStatusSuspendBegin
	AddSuspendHook 20 XStatusProgress
	AddSuspendHook 30 XStatusProgress
	AddSuspendHook 40 XStatusProgress
	AddSuspendHook 50 XStatusProgress
	AddSuspendHook 60 XStatusProgress
	AddSuspendHook 70 XStatusProgress
	AddSuspendHook 80 XStatusProgress
	AddSuspendHook 90 XStatusProgress
	AddSuspendHook 95 XStatusProgress
	AddSuspendHook 98 XStatusProgressKill
	AddResumeHook 95 XStatusResumeBegin
	AddResumeHook 90 XStatusProgress
	AddResumeHook 80 XStatusProgress
	AddResumeHook 70 XStatusProgress
	AddResumeHook 60 XStatusProgress
	AddResumeHook 50 XStatusProgress
	AddResumeHook 40 XStatusProgress
	AddResumeHook 30 XStatusProgress
	AddResumeHook 20 XStatusProgress
	AddResumeHook 15 XStatusProgress
	AddResumeHook 05 XStatusProgressKill
	AddResumeHook 01 XStatusReportErrors
	XSTATUS_HOOKED=1
    fi

    return 0
}
