#
# Plugin implements commands /time, /last, /vcard, /version in chat
# and groupchat windows.
#

##############################################################################

namespace eval chatinfo {

    custom::defgroup VCard \
	[::msgcat::mc "vCard display options in chat windows."] \
	-group Chat
    
    set vcard_defs [list fn        [::msgcat::mc "Full Name"]		    1 \
			 family    [::msgcat::mc "Family Name"]		    1 \
			 name      [::msgcat::mc "Name"]		    1 \
			 middle    [::msgcat::mc "Middle Name"]		    0 \
			 prefix    [::msgcat::mc "Prefix"]		    0 \
			 suffix    [::msgcat::mc "Suffix"]		    0 \
			 nickname  [::msgcat::mc "Nickname"]		    1 \
			 email     [::msgcat::mc "E-mail"]		    1 \
			 url       [::msgcat::mc "Web Site"]		    1 \
			 jabberid  [::msgcat::mc "JID"]			    1 \
			 uid       [::msgcat::mc "UID"]			    1 \
			 tel_home  [::msgcat::mc "Phone Home"]		    1 \
			 tel_work  [::msgcat::mc "Phone Work"]		    1 \
			 tel_voice [::msgcat::mc "Phone Voice"]		    1 \
			 tel_fax   [::msgcat::mc "Phone Fax"]		    0 \
			 tel_pager [::msgcat::mc "Phone Pager"]		    0 \
			 tel_msg   [::msgcat::mc "Phone Message Recorder"]  0 \
			 tel_cell  [::msgcat::mc "Phone Cell"]		    1 \
			 tel_video [::msgcat::mc "Phone Video"]		    0 \
			 tel_bbs   [::msgcat::mc "Phone BBS"]		    0 \
			 tel_modem [::msgcat::mc "Phone Modem"]		    0 \
			 tel_isdn  [::msgcat::mc "Phone ISDN"]		    0 \
			 tel_pcs   [::msgcat::mc "Phone PCS"]		    0 \
			 tel_pref  [::msgcat::mc "Phone Preferred"]	    1 \
			 address   [::msgcat::mc "Address"]		    1 \
			 address2  [::msgcat::mc "Address 2"]		    0 \
			 city      [::msgcat::mc "City"]		    1 \
			 state     [string trim [::msgcat::mc "State "]]    1 \
			 pcode     [::msgcat::mc "Postal Code"]		    0 \
			 country   [::msgcat::mc "Country"]		    1 \
			 geo_lat   [::msgcat::mc "Latitude"]		    0 \
			 geo_lon   [::msgcat::mc "Longitude"]		    0 \
			 orgname   [::msgcat::mc "Organization Name"]	    1 \
			 orgunit   [::msgcat::mc "Organization Unit"]	    1 \
			 title     [::msgcat::mc "Title"]		    1 \
			 role      [::msgcat::mc "Role"]		    1 \
			 bday      [::msgcat::mc "Birthday"]		    1 \
			 desc      [string trim [::msgcat::mc "About "]]    0]

    foreach {opt name default} $vcard_defs {
	custom::defvar options($opt) $default \
	    [::msgcat::mc "Display %s in chat window when using /vcard command." \
		 $name] \
	    -type boolean -group VCard
    }
}

##############################################################################

proc chatinfo::handle_info_commands {chatid user body type} {

    if {[string equal -length 6 $body "/time "] || [cequal $body "/time"]} {
	set name [crange $body 6 end]
	set command time
    } elseif {[string equal -length 6 $body "/last "] || [cequal $body "/last"]} {
	set name [crange $body 6 end]
	set command last
    } elseif {[string equal -length 7 $body "/vcard "] || [cequal $body "/vcard"]} {
	set name [crange $body 7 end]
	set command vcard
    } elseif {[string equal -length 9 $body "/version "] || [cequal $body "/version"]} {
	set name [crange $body 9 end]
	set command version
    } elseif {[string equal -length 6 $body "/ping "] || [cequal $body "/ping"]} {
	set name [crange $body 6 end]
	set command ping
    } elseif {[string equal -length 11 $body "/discoinfo "] || [cequal $body "/discoinfo"]} {
	set name [crange $body 11 end]
	set command discoinfo
    } elseif {[string equal -length 12 $body "/discoitems "] || [cequal $body "/discoitems"]} {
	set name [crange $body 12 end]
	set command discoitems
    } elseif {[string equal -length 7 $body "/macaj "] || [cequal $body "/macaj"]} {
	set name [crange $body 7 end]
	set command macaj
    } else {
	return
    }

    set connid [chat::get_connid $chatid]
    set jid [chat::get_jid $chatid]
    set jids {}
    set vcard_jids {}
    if {[cequal $type groupchat]} {
	if {[cequal $name ""]} {
	    set jids [list $jid]
	} else {
	    set jids [list "$jid/$name"]
	}
	set vcard_jids $jids
    } else {
	if {[cequal $name ""]} {
	    set bare_jid [node_and_server_from_jid $jid]
	    set full_jids [::get_jids_of_user $connid $bare_jid]
	    if {[lsearch $full_jids $jid] >= 0} {
		set jids [list $jid]
	    } elseif {[lempty $full_jids]} {
		set jids [list $jid]
	    } else {
		set jids $full_jids
	    }
	    set vcard_jids [list $bare_jid]
	}
    }
    if {[cequal $jids {}]} {
	lassign [roster_lookup $connid $name] jids vcard_jids
	if {[cequal $jids {}]} {
	    set jids [list $name]
	}
    }
    if {[cequal $vcard_jids {}]} {
	set vcard_jids $jids
    }

    if {[cequal $command vcard]} {
	foreach jid $vcard_jids {
	    request_vcard $connid $chatid $jid
	}
    } else {
	foreach jid $jids {
	    switch $command {
	    		macaj {
				request_vcard $connid $chatid $jid
				request_ping $connid $chatid $jid
				request_disco info $connid $chatid $jid
				request_disco items $connid $chatid $jid
				request_iq last $connid $chatid $jid
				request_iq time $connid $chatid $jid
				request_iq version $connid $chatid $jid
			}
			ping { request_ping $connid $chatid $jid }
			discoinfo { request_disco info $connid $chatid $jid }
			discoitems { request_disco items $connid $chatid $jid }
			default { request_iq $command $connid $chatid $jid }
	    }
	}
    }
    return stop
}

hook::add chat_send_message_hook \
    [namespace current]::chatinfo::handle_info_commands 15

##############################################################################

proc chatinfo::roster_lookup {connid name} {
    set ret {}
    set ret1 {}
    foreach jid [roster::get_jids $connid] {
	set rname [roster::get_label $connid $jid]
	if {[cequal $rname $name]} {
	    set bare_jid [node_and_server_from_jid $jid]
	    set full_jids [::get_jids_of_user $connid $bare_jid]
	    if {![cequal $full_jids {}]} {
		set ret [concat $ret $full_jids]
	    } else {
		lappend ret $bare_jid
	    }
	    lappend ret1 $bare_jid
	}
    }
    return [list [lsort -unique $ret] [lsort -unique $ret1]]
}

##############################################################################

proc chatinfo::info_commands_comps {chatid compsvar wordstart line} {
    upvar 0 $compsvar comps

    set commands [list "/time " "/last " "/vcard " "/version " "/ping " "/discoinfo " "/discoitems " "/macaj "]
    
    if {!$wordstart} {
	set comps [concat $comps $commands]
    } elseif {![chat::is_groupchat $chatid]} {
	set q 0
	foreach cmd $commands {
	    if {[string equal -length [string length $cmd] $cmd $line]} {
		set q 1
		break
	    }
	}
	if {!$q} return

	set connid [chat::get_connid $chatid]
	set names {}
	foreach jid [roster::get_jids $connid] {
	    lappend names "[roster::get_label $connid $jid] "
	}
	set comps [concat $comps [lsort -unique $names]]
    }
}

hook::add generate_completions_hook \
    [namespace current]::chatinfo::info_commands_comps

##############################################################################
proc chatinfo::request_ping {connid chatid jid} {
    variable pings
    jlib::send_iq get \
	[jlib::wrapper:createtag ping \
	    -vars [list xmlns urn:xmpp:ping]] \
	-to $jid \
	-connection $connid \
	-command [list [namespace current]::parse_info_ping $chatid $jid]
    set pings($jid) [clock clicks -milliseconds]
}
proc chatinfo::request_disco {type connid chatid jid} {
    jlib::send_iq get \
	[jlib::wrapper:createtag query \
	    -vars [list xmlns http://jabber.org/protocol/disco#$type]] \
	-to $jid \
	-connection $connid \
	-command [list [namespace current]::parse_info_disco $type $chatid $jid]
}

proc chatinfo::parse_info_ping {chatid jid res child} {
    variable pings
    if {![winfo exists [chat::chat_win $chatid]]} {
	return
    }
    if {![info exists pings($jid)]} {
	return
    }
    set rjid [whois $chatid $jid]
    set diff [expr [clock clicks -milliseconds]-$pings($jid)]
    unset pings($jid)
    if {![cequal $res OK]} {
	chat::add_message $chatid $jid error \
	    [::msgcat::mc "ping %s%s: %s, after %s ms" $jid $rjid [error_to_string $child] $diff] {}
	return
    }
    set message [::msgcat::mc "ping %s%s after %s ms" $jid $rjid $diff]
    chat::add_message $chatid $jid info $message {}
}

proc chatinfo::parse_info_disco {type chatid jid res child} {

    if {![winfo exists [chat::chat_win $chatid]]} {
	return
    }

    set rjid [whois $chatid $jid]
    if {![cequal $res OK]} {
	chat::add_message $chatid $jid error \
	    [::msgcat::mc "disco $type %s%s: %s" $jid $rjid [error_to_string $child]] {}
	return
    }

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

    if {[cequal [jlib::wrapper:getattr $vars xmlns] jabber:iq:time]} {
	userinfo::parse_iqtime_item $jid $children
    }
    set message [::msgcat::mc "disco $type %s%s:" $jid $rjid]
    foreach i $children {
	jlib::wrapper:splitxml $i tag2 vars2 isempty2 chdata2 children2
	if {$tag2=="identity"} {
		set category [jlib::wrapper:getattr $vars2 category]
		set type [jlib::wrapper:getattr $vars2 type]
		set name [jlib::wrapper:getattr $vars2 name]
		append message "\n     Identity: $category/$type $name"
	}
	if {$tag2=="feature"} {
		set var [jlib::wrapper:getattr $vars2 var]
		append message "\n     Feature: $var"
	}
	if {$tag2=="item"} {
		set jid [jlib::wrapper:getattr $vars2 jid]
		set name [jlib::wrapper:getattr $vars2 name]
		append message "\n     Item: $jid $name"
	}
    }
    chat::add_message $chatid $jid info $message {}
}
proc chatinfo::request_iq {type connid chatid jid} {
    jlib::send_iq get \
	[jlib::wrapper:createtag query \
	    -vars [list xmlns jabber:iq:$type]] \
	-to $jid \
	-connection $connid \
	-command [list [namespace current]::parse_info_iq$type $chatid $jid]
}

##############################################################################

proc chatinfo::request_vcard {connid chatid jid} {
    jlib::send_iq get \
	[jlib::wrapper:createtag vCard \
	    -vars [list xmlns vcard-temp]] \
	-to $jid \
	-connection $connid \
	-command [list [namespace current]::parse_info_vcard $chatid $jid]
}

##############################################################################

proc chatinfo::whois {chatid jid} {
    set connid [chat::get_connid $chatid]
    set real_jid [muc::get_real_jid $connid $jid]
    if {$real_jid != ""} {
	return " ($real_jid)"
    } else {
	return ""
    }
}

##############################################################################

proc chatinfo::parse_info_iqtime {chatid jid res child} {

    if {![winfo exists [chat::chat_win $chatid]]} {
	return
    }

    set rjid [whois $chatid $jid]
    if {![cequal $res OK]} {
	chat::add_message $chatid $jid error \
	    [::msgcat::mc "time %s%s: %s" $jid $rjid [error_to_string $child]] {}
	return
    }

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

    if {[cequal [jlib::wrapper:getattr $vars xmlns] jabber:iq:time]} {
	userinfo::parse_iqtime_item $jid $children
    }
    set message [::msgcat::mc "time %s%s:" $jid $rjid]
    foreach {i j} [list time [::msgcat::mc "Time:"] \
		    tz   [::msgcat::mc "Time Zone:"] \
		    utc  [::msgcat::mc "UTC:"]] {
	if {[info exists userinfo::userinfo($i,$jid)] && \
		 ![cequal $userinfo::userinfo($i,$jid) ""] } {
	    append message "\n     $j $userinfo::userinfo($i,$jid)"
	}
    }
    chat::add_message $chatid $jid info $message {}
}

##############################################################################

proc chatinfo::parse_info_iqlast {chatid jid res child} {

    if {![winfo exists [chat::chat_win $chatid]]} {
	return
    }

    set rjid [whois $chatid $jid]
    if {![cequal $res OK]} {
	chat::add_message $chatid $jid error \
	    [::msgcat::mc "last %s%s: %s" $jid $rjid [error_to_string $child]] {}
	return
    }

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

    if {[cequal [jlib::wrapper:getattr $vars xmlns] jabber:iq:last]} {
	set ::userinfo::userinfo(lastseconds,$jid) \
	    [format_time [jlib::wrapper:getattr $vars seconds]]
	set ::userinfo::userinfo(lastdesc,$jid) $chdata
    }
    set message [::msgcat::mc "last %s%s:" $jid $rjid]
    foreach {i j} [list lastseconds [::msgcat::mc "Interval:"] \
		    lastdesc    [::msgcat::mc "Description:"]] {
	if {[info exists userinfo::userinfo($i,$jid)] && \
		 ![cequal $userinfo::userinfo($i,$jid) ""]} {
	    append message "\n     $j $userinfo::userinfo($i,$jid)"
	}
    }
    chat::add_message $chatid $jid info $message {}
}

##############################################################################

proc chatinfo::parse_info_iqversion {chatid jid res child} {

    if {![winfo exists [chat::chat_win $chatid]]} {
	return
    }

    set rjid [whois $chatid $jid]
    if {![cequal $res OK]} {
	chat::add_message $chatid $jid error \
	    [::msgcat::mc "version %s%s: %s" $jid $rjid [error_to_string $child]] {}
	return
    }

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

    if {[cequal [jlib::wrapper:getattr $vars xmlns] jabber:iq:version]} {
	userinfo::parse_iqversion_item $jid $children
    }

    set message [::msgcat::mc "version %s%s:" $jid $rjid]
    foreach {i j} [list clientname    [::msgcat::mc "Client:"] \
		    clientversion [::msgcat::mc "Version:"] \
		    os            [::msgcat::mc "OS:"]] {
	if {[info exists userinfo::userinfo($i,$jid)] && \
		 ![cequal $userinfo::userinfo($i,$jid) ""]} {
	    append message "\n     $j $userinfo::userinfo($i,$jid)"
	}
    }
    chat::add_message $chatid $jid info $message {}
}

##############################################################################

proc chatinfo::parse_info_vcard {chatid jid res child} {
    variable options
    variable vcard_defs

    if {![winfo exists [chat::chat_win $chatid]]} {
	return
    }

    set rjid [whois $chatid $jid]
    if {![cequal $res OK]} {
	chat::add_message $chatid $jid error \
	    [::msgcat::mc "vcard %s%s: %s" $jid $rjid [error_to_string $child]] {}
	return
    }

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

    foreach item $children {
	userinfo::parse_vcard_item $jid $item
    }
    set message [::msgcat::mc "vcard %s%s:" $jid $rjid]
    foreach {def name ignore} $vcard_defs) {
	if {$options($def) && \
		[info exists userinfo::userinfo($def,$jid)] && \
		![cequal $userinfo::userinfo($def,$jid) ""]} {
	    append message "\n     $name: $userinfo::userinfo($def,$jid)"
	}
    }
    chat::add_message $chatid $jid info $message {}
}

##############################################################################

