# $Id: avatars.tcl 1244 2007-10-06 07:53:04Z sergei $

if {![cequal $::interface tk]} return

package require base64
package require sha1

namespace eval ::avatar {
    set options(announce) 0
    set options(share) 0
}

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

proc ::avatar::setup_menu {} {
    catch {
	#set m [.mainframe getmenu services]
	#for {set ind [$m index end]} {$ind > 0} {incr ind -1} {
	#    if {[$m type $ind] == "separator"} {
	#	break
	#    }
	#}
	set m [.mainframe getmenu plugins]

	set mm .avatar_menu
	menu $mm -tearoff $ifacetk::options(show_tearoffs)
	$mm add checkbutton -label [::msgcat::mc "Announce"] \
	    -variable avatar::options(announce)
	$mm add checkbutton -label [::msgcat::mc "Allow downloading"] \
	    -variable avatar::options(share)
	$mm add command -label [::msgcat::mc "Send to server"] \
	    -command {avatar::store_on_server}

	$m add cascade -label [::msgcat::mc "Avatar"] \
	    -menu $mm
    }
}

hook::add finload_hook ::avatar::setup_menu

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

proc ::avatar::load_file {filename} {
    variable avatar
    variable options

    image create photo user_avatar -file $filename
    set f [open $filename]
    fconfigure $f -translation binary
    set data [read $f]
    close $f

    set avatar(userhash) [sha1::sha1 $data]
    set avatar(userdata) [base64::encode $data]

    set options(announce) 1
    set options(share) 1
}

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

proc ::avatar::get_presence_x {varname connid status} {
    variable avatar
    variable options
    upvar 2 $varname var

    if {$options(announce) && [info exists avatar(userhash)]} {
	set children [jlib::wrapper:createtag hash -chdata $avatar(userhash)]
	lappend var [jlib::wrapper:createtag x \
			 -vars [list xmlns $::NS(xavatar)] \
			 -subtags [list $children]]

    }
    return
}

hook::add presence_xlist_hook ::avatar::get_presence_x

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

proc ::avatar::process_presence {connid from type x args} {
    switch -- $type {
	available -
	unavailable {
	    foreach xs $x {
		jlib::wrapper:splitxml $xs tag vars isempty chdata children
		if {[jlib::wrapper:getattr $vars xmlns] == $::NS(xavatar)} {
		    set_hash $connid $from $children
		    break
		}
	    }
	}
    }
}

hook::add client_presence_hook ::avatar::process_presence

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

proc ::avatar::insert_userinfo {tab connid jid editable} {
    if {$editable} return

    set avatar_img [get_image $connid [get_jid_of_user $connid $jid]]
    if {$avatar_img != ""} {
	set avatar [$tab insert end avatar -text [::msgcat::mc "Avatar"]]

	set av [userinfo::pack_frame $avatar.avatar [::msgcat::mc "Avatar"]]
	label $av.a -image $avatar_img
	pack $av.a -expand yes -fill both
    }
}

hook::add userinfo_hook ::avatar::insert_userinfo 40

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

proc ::avatar::set_hash {connid jid children} {
    variable avatar

    debugmsg avatar "set hash $connid $jid $children"
    foreach child $children {
	jlib::wrapper:splitxml $child tag vars isempty chdata children1
	if {$tag == "hash"} {
	    set hash $chdata
	}
    }
    if {[info exists hash]} {
	if {![info exists avatar(hash,$connid,$jid)] || \
		$hash != $avatar(hash,$connid,$jid)} {
	    set avatar(hash,$connid,$jid) $hash
	    set avatar(needupdate,$connid,$jid) 1
	}
    }
}

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

proc ::avatar::get_image {connid jid} {
    variable avatar

    debugmsg avatar "$jid; [array name avatar]"
    if {[info exists avatar(hash,$connid,$jid)]} {
	if {![info exists avatar(data,$connid,$jid)]} {
	    image create photo avatar$connid@$jid
	    get $connid $jid
	} elseif {$avatar(needupdate,$connid,$jid)} {
	    get $connid $jid
	}
	return avatar$connid@$jid
    } else {
	return ""
    }
}

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

proc ::avatar::get {connid jid} {
    variable avatar

    set avatar(needupdate,$connid,$jid) 0

    jlib::send_iq get \
	[jlib::wrapper:createtag query \
	     -vars [list xmlns $::NS(iqavatar)]] \
	-to $jid -command [list avatar::recv $connid $jid] \
	-connection $connid
}

proc ::avatar::recv {connid jid res child} {
    variable avatar

    if {![cequal $res OK]} {
	jlib::send_iq get [jlib::wrapper:createtag query \
			       -vars {xmlns storage:client:avatar}] \
	    -to [node_and_server_from_jid $jid] \
	    -command [list avatar::recv_from_serv $connid $jid] \
	    -connection $connid

	return
    }

    jlib::wrapper:splitxml $child tag vars isempty chdata children
    foreach child1 $children {
	jlib::wrapper:splitxml $child1 tag1 vars1 isempty1 chdata1 childrens1
	if {$tag1 == "data"} {
	    catch {
		set avatar(data,$connid,$jid) [base64::decode $chdata1]
		avatar$connid@$jid put $chdata1
	    }
	}
    }
}

proc ::avatar::recv_from_serv {connid jid res child} {
    variable avatar

    if {![cequal $res OK]} {
	# TODO
	return
    }

    jlib::wrapper:splitxml $child tag vars isempty chdata children
    foreach child1 $children {
	jlib::wrapper:splitxml $child1 tag1 vars1 isempty1 chdata1 children1
	if {$tag1 == "data"} {
	    catch {
		set avatar(data,$connid,$jid) [base64::decode $chdata1]
		avatar$connid@$jid put $chdata1
	    }
	}
    }
}

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

proc ::avatar::store_on_server {args} {
    variable avatar

    if {[llength [jlib::connections]] == 0} return

    foreach {opt val} $args {
	switch -- $opt {
	    -connection { set connid $val }
	}
    }

    if {![info exists connid]} {
	set connid [lindex [jlib::connections] 0]
    }

    if {![info exists avatar(userdata)]} {
	MessageDlg .avatar_error -aspect 50000 -icon error \
		-message [::msgcat::mc "No avatar to store"] -type user \
		-buttons ok -default 0 -cancel 0
	return
    }

    set restags \
	[list [jlib::wrapper:createtag data \
		   -chdata $avatar(userdata)]]
    set res [jlib::wrapper:createtag query \
		 -vars {xmlns storage:client:avatar} \
		 -subtags $restags]

    jlib::send_iq set $res -connection $connid
}

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

proc ::avatar::iq_reply {connid from lang child} {
    variable avatar
    variable options

    if {$options(share) && [info exists avatar(userdata)]} {
	set restags \
	    [list [jlib::wrapper:createtag data \
		       -chdata $avatar(userdata)]]
	set res [jlib::wrapper:createtag query \
		     -vars [list xmlns $::NS(iqavatar)] \
		     -subtags $restags]
    } else {
	return [list error cancel service-unavailable]
    }

    return [list result $res]
}

iq::register_handler get query $::NS(iqavatar) ::avatar::iq_reply

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

