# $Id: autoaway.tcl 1125 2007-04-29 11:52:38Z sergei $

namespace eval autoaway {
    variable options
    variable savestatus ""
    variable savetext   ""
    variable savepriority 0
}


proc autoaway::load {} {
    global tcl_platform
    global idle_command

    if {[catch {tk inactive}] || ([tk inactive] < 0)} {
	switch -- $tcl_platform(platform) {
	    macintosh {
		set idle_command [namespace current]::AquaIdleTime
	    }

	    unix {
		if {$::aquaP} {
		    set idle_command [namespace current]::AquaIdleTime
		} elseif {[catch { package require tkXwin }]} {
		    return
		} else {
		    set idle_command tkXwin::idletime
		}
	    }
	    windows {
		if {![catch { package require tkinactive }]} {
		    set idle_command tkinactive
		} elseif {![catch { package require tclWinidle }]} {
		    set idle_command tclWinidle::idletime
		} else {
		    return
		}
	    }
	    default {
		return
	    }
	}
    } else {
	set idle_command {tk inactive}
    }

    custom::defgroup AutoAway \
	[::msgcat::mc "Options for module that automatically marks\
		       you as away after idle threshold."] \
	-group Tkabber

    custom::defvar options(awaytime) 5 \
	[::msgcat::mc "Idle threshold in minutes after that\
		       Tkabber marks you as away."] \
	-group AutoAway -type integer

    custom::defvar options(xatime) 15 \
	[::msgcat::mc "Idle threshold in minutes after that\
		       Tkabber marks you as extended away."] \
	-group AutoAway -type integer

    custom::defvar options(status) \
	[::msgcat::mc "Automatically away due to idle"] \
	[::msgcat::mc "Text status, which is set when\
		       Tkabber is moving to away state."] \
	-group AutoAway -type string

    custom::defvar options(drop_priority) 1 \
	[::msgcat::mc "Set priority to 0 when moving to extended away state."] \
	-group AutoAway -type boolean

    hook::add connected_hook    [namespace current]::after_idle
    hook::add disconnected_hook [namespace current]::after_idle_cancel
}


proc autoaway::after_idle {args} {
    after cancel [namespace current]::after_idle
    after_idle_aux
    if {$::aquaP} {
        set msec 1000
    } else {
        set msec 250
    }
    after $msec [namespace current]::after_idle
}

proc autoaway::after_idle_cancel {args} {
    variable options
    variable savestatus
    variable savetext
    variable savepriority
    global userstatus textstatus userpriority

    if {[jlib::connections] == {}} {
        if {![cequal $savestatus ""]} {
	    if {$options(drop_priority) && ($userpriority >= 0)} {
		set userpriority $savepriority
	    }
	    set savepriority 0
	    set textstatus $savetext
	    set savetext ""
            set userstatus $savestatus
            set savestatus ""
        }
	
	after cancel [namespace current]::after_idle
    }
}

proc autoaway::after_idle_aux {} {
    variable options
    variable savestatus
    variable savetext
    variable savepriority
    global idle_command
    global userstatus textstatus userpriority

    if {($options(awaytime) <= 0) && ($options(xatime) <= 0)} {
        return
    }

    set idletime [eval $idle_command]

    if {$idletime < [expr {$options(awaytime)*60*1000}]} {
        if {![cequal $savestatus ""]} {
	    if {$options(drop_priority) && ($userpriority >= 0)} {
		set userpriority $savepriority
	    }
	    set savepriority 0
	    set textstatus $savetext
	    set savetext ""
            set userstatus $savestatus
            set savestatus ""
            set_status [::msgcat::mc "Returning from auto-away"]
        }

        return
    }

    switch -- $userstatus {
        available -
        chat {
            set savestatus $userstatus
	    set savetext $textstatus
	    set savepriority $userpriority
	    if {![cequal $options(status) ""]} {
	       set textstatus $options(status)
	    }
            if {$idletime >= [expr {$options(xatime)*60*1000}]} {
		if {$options(drop_priority) && ($userpriority >= 0)} {
		    set userpriority 0
		}
                set userstatus xa
                set_status [::msgcat::mc "Moving to extended away"]
            } else {
                set userstatus away
                set_status [::msgcat::mc "Starting auto-away"]
            }
            return
        }

        away {
            if {(![cequal $savestatus ""]) && \
		    ($idletime >= [expr {$options(xatime)*60*1000}])} {
		set savepriority $userpriority
		if {![cequal $options(status) ""]} {
		    set textstatus $options(status)
		}
		if {$options(drop_priority) && ($userpriority >= 0)} {
		    set userpriority 0
		}
                set userstatus xa
                set_status [::msgcat::mc "Moving to extended away"]
                return
            }
        }

        default {
        }
    }

    if {![cequal $savestatus ""]} {
        set_status [format [::msgcat::mc "Idle for %s"] [format_time [expr {$idletime/1000}]]]
    }
}

proc autoaway::AquaIdleTime {} {
    catch { set line [read [set fd [open {|ioreg -x -c IOHIDSystem}]]] }
    close $fd

    expr {"0x[lindex [regexp -inline {"HIDIdleTime" = (?:0x|<)([[:xdigit:]]+)} \
                 $line] 1]"/1000000}
}

autoaway::load

# vim:ts=8:sw=4:sts=4:noet
