# $Id: conferenceinfo.tcl 1184 2007-08-12 15:42:55Z sergei $

namespace eval conferenceinfo {
    custom::defgroup ConferenceInfo \
	[::msgcat::mc "Options for Conference Info module, that allows you to see list of\
participants in roster popup, regardless of whether you are currently joined\
with the conference."] \
	-group Tkabber \
	-tag "Conference Info"

    custom::defvar options(autoask) 0 \
	[::msgcat::mc "Use this module"] -group ConferenceInfo -type boolean \
	-command [namespace current]::ask
    custom::defvar options(interval) 2 \
	[::msgcat::mc "Interval (in minutes) between requests of participants list."] \
	-type integer -group ConferenceInfo
    custom::defvar options(err_interval) 60 \
	[::msgcat::mc "Interval (in minutes) after error reply on request of participants list."] \
	-type integer -group ConferenceInfo
}


# TODO: connid
proc conferenceinfo::add_user_popup_info {infovar connid jid} {
    variable data
    variable options
    upvar 0 $infovar info

    if {!$options(autoask)} return
    if {[chat::is_opened [chat::chatid $connid $jid]]} return

    if {![info exists data(error_browse,$jid)] || \
	    ![info exists data(error_disco,$jid)]} return

    if {$data(error_disco,$jid) != "" && $data(error_browse,$jid) != ""} {
	if {$data(error_browse_code,$jid) != "feature-not-implemented" && \
		$data(error_browse_code,$jid) != "service-unavailable"} {
	    set errstr $data(error_browse,$jid)
	} else {
	    set errstr $data(error_disco,$jid)
	}
	append info [format [::msgcat::mc "\n\tCan't browse: %s"] $errstr]
    } else {
	if {$data(error_browse,$jid) == ""} {
	    set mech browse
	} else {
	    set mech disco
	}
	if {$data(users_$mech,$jid) != {}} {
	    append info \
		[format [::msgcat::mc "\nRoom participants at %s:"] \
		     [clock format $data(time_$mech,$jid) -format %R]]
	    foreach name $data(users_$mech,$jid) {
		append info "\n\t$name"
	    }
	} else {
	    append info \
		[format [::msgcat::mc "\nRoom is empty at %s"] \
		     [clock format $data(time_$mech,$jid) -format %R]]
	}
    }
}
hook::add roster_user_popup_info_hook \
    [namespace current]::conferenceinfo::add_user_popup_info


proc conferenceinfo::ask {args} {
    variable options
    variable data

    if {!$options(autoask)} return

    foreach connid [jlib::connections] {
	if {[catch { set roster::roster(jids,$connid) } jids]} {
	    continue
	}
	foreach jid $jids {
	    lassign [roster::get_category_and_subtype $connid $jid] \
		category type
	    if {$category == "conference" && [node_from_jid $jid] != "" && \
		    ![chat::is_opened [chat::chatid $connid $jid]]} {
	    
		set sec [clock seconds]
 
		if {![info exists data(error_browse,$jid)] || \
			$data(error_browse,$jid) == "" || \
			$sec - $data(time_browse,$jid) >= $options(err_interval) * 60} {

		    jlib::send_iq get \
			[jlib::wrapper:createtag query \
			     -vars {xmlns jabber:iq:browse}] \
			-to $jid \
			-connection $connid \
			-command [list [namespace current]::receive $jid browse]
		}

		if {![info exists data(error_disco,$jid)] || \
			$data(error_disco,$jid) == "" || \
			$sec - $data(time_disco,$jid) >= $options(err_interval) * 60} {

		    jlib::send_iq get \
			[jlib::wrapper:createtag query \
			     -vars [list xmlns $::NS(disco_items)]] \
			-to $jid \
			-connection $connid \
			-command [list [namespace current]::receive $jid disco]
		}
	    }
	}
    }

    after cancel [list [namespace current]::ask]
    after [expr {$options(interval) * 60 * 1000}] [list [namespace current]::ask]
}

proc conferenceinfo::receive {jid mech res child} {
    variable options
    variable data

    set data(error_$mech,$jid) ""
    set data(error_${mech}_code,$jid) ""
    set data(time_$mech,$jid) [clock seconds]
    set data(users_$mech,$jid) {}

    if {$res != "OK"} {
	set data(error_${mech}_code,$jid) [lindex [error_type_condition $child] 1]
	set data(error_$mech,$jid) [error_to_string $child]
	return
    }

    jlib::wrapper:splitxml $child tag vars isempty chdata children

    foreach item $children {
	jlib::wrapper:splitxml $item tag1 vars1 isempty1 chdata1 children1
	switch -- $mech {
	    browse {
		if {$tag1 == "user" || ($tag1 == "item" && \
			[jlib::wrapper:getattr $vars1 category] == "user")} {
		    set name [jlib::wrapper:getattr $vars1 name]
		    if {$name != ""} {
			lappend data(users_browse,$jid) $name
		    }
		}
	    }
	    disco {
		if {$tag1 == "item"} {
		    set node [jlib::wrapper:getattr $vars1 node]
		    set name [jlib::wrapper:getattr $vars1 name]
		    if {$name != "" && $node == ""} {
			lappend data(users_disco,$jid) $name
		    }
		}
	    }
	}
    }
    set data(users_$mech,$jid) [lsort -dictionary $data(users_$mech,$jid)]
}

proc conferenceinfo::stop {args} {
    if {[jlib::connections] == {}} {
	after cancel [list [namespace current]::ask]
    }
}

hook::add roster_end_hook [namespace current]::conferenceinfo::ask
hook::add disconnected_hook [namespace current]::conferenceinfo::stop

proc conferenceinfo::setup_menu {} {
    set m [.mainframe getmenu roster]

    $m add checkbutton \
	-label [::msgcat::mc "Periodically browse roster conferences"] \
	-variable [namespace current]::options(autoask)
}
hook::add finload_hook [namespace current]::conferenceinfo::setup_menu

