# $Id$

package require base64

namespace eval ibb {}

proc ibb::load {} {
    ::xmpp::iq::register set query jabber:iq:ibb [namespace current]::iq_set_handler
    ::xmpp::iq::register set query jabber:iq:inband [namespace current]::iq_inband_set_handler

    jidlink::register_transport inband-bytestream inband-bytestream 75 enabled \
				[namespace current]::connect \
				[namespace current]::send_data \
				[namespace current]::close
}

proc ibb::unload {} {
    ::xmpp::iq::unregister set query jabber:iq:ibb
    ::xmpp::iq::unregister set query jabber:iq:inband

    #jidlink::unregister_transport inband-bytestream

    namespace delete [namespace current]
}

proc ibb::connect {xlib jid key} {
    variable connection

    set_status [::msgcat::mc "Opening IBB connection"]

    ::xmpp::sendIQ $xlib set \
	-query [::xmpp::xml::create query \
		    -xmlns jabber:iq:ibb \
		    -subelement [::xmpp::xml::create comment \
				    -subelement [::xmpp::xml::create key \
							-cdata $key]]] \
	-to $jid \
	-command [list [namespace current]::recv_connect_response $xlib $jid $key]
	 
    vwait [namespace current]::connection(status,$key)
}

proc ibb::recv_connect_response {xlib jid key status xml} {
    variable connection

    if {$status != "ok"} {
	# TODO
	set connection(status,$key) 0
	return
    }

    ::xmpp::xml::split $xml tag xmlns attrs cdata subels

    if {$tag == "query"} {
	foreach item $subels {
	    ::xmpp::xml::split $item stag sxmlns sattrs scdata ssubels
	    if {$stag == "streamid"} {
		set streamid $scdata
		debugmsg jidlink "STREAMID: $streamid"
	    }
	}

	if {[info exists streamid]} {
	    variable stream_key
	    variable key_stream

	    set stream_key($streamid) $key
	    set key_stream($key) $streamid

	    set connection(xlib,$key) $xlib
	    set connection(jid,$key) $jid
	    set connection(status,$key) 1

	} else {
	    # TODO
	}
    } else {
	# TODO
    }
    set connection(status,$key) 0
}

proc ibb::send_data {key data} {
    variable connection
    variable key_stream

    debugmsg jidlink [array get stream_key]

    ::xmpp::sendIQ $connection(xlib,$key) set \
	-query [::xmpp::xml::create query \
		    -xmlns jabber:iq:inband \
		    -subelement [::xmpp::xml::create streamid \
					-cdata $key_stream($key)] \
		    -subelement [::xmpp::xml::create data \
					-cdata [base64::encode $data]]] \
	-to $connection(jid,$key) \
	-command [list [namespace current]::send_data_ack $key]

    vwait [namespace current]::connection(ack,$key)

    return $connection(ack,$key)
}

proc ibb::send_data_ack {key status xml} {
    variable connection
    if {$status != "ok"} {
	# TODO
	set connection(ack,$key) 0
	return
    }
    set connection(ack,$key) 1
}

proc ibb::close {key} {
    variable connection
    variable key_stream

    ::xmpp::sendIQ $connection(xlib,$key) set \
	-query [::xmpp::xml::create query \
		    -xmlns jabber:iq:inband \
		    -subelement [::xmpp::xml::create streamid \
					-cdata $key_stream($key)] \
		    -subelement [::xmpp::xml::create close]] \
	-to $connection(jid,$key)
}

proc ibb::iq_set_handler {xlib from xml args} {
    ::xmpp::xml::split $xml tag xmlns attrs cdata subels

    if {$tag == "query"} {
	foreach item $subels {
	    ::xmpp::xml::split $item stag sxmlns sattrs scdata ssubels
	    if {$stag == "comment"} {
		foreach sitem $ssubels {
		    ::xmpp::xml::split $sitem sstag ssxmlns ssattrs sscdata sssubels
		    if {$sstag == "key"} {
			set key $sscdata
			debugmsg jidlink "KEY: $key"
		    }
		}
	    }
	}

	if {[info exists key]} {
	    variable stream_key
	    variable key_stream

	    set streamid [rand 1000000000]
	    set stream_key($streamid) $key
	    set key_stream($key) $streamid

	    set res [::xmpp::xml::create query \
			 -xmlns jabber:iq:ibb \
			 -subelement [::xmpp::xml::create streamid \
					     -cdata $streamid]]
	    return [list result $res]
	} else {
	    # TODO
	}
    } else {
	# TODO
    }
}

proc ibb::iq_inband_set_handler {xlib from xml args} {
    variable stream_key

    ::xmpp::xml::split $xml tag xmlns attrs cdata subels

    if {$tag == "query"} {
	foreach item $subels {
	    ::xmpp::xml::split $item stag sxmlns sattrs scdata ssubels
	    switch -- $stag {
		streamid {
		    set streamid $scdata
		}
		data {
		    set data $scdata
		}
		close {
		    set close 1
		}
	    }
	}

	if {[info exists streamid] && [info exists stream_key($streamid)]} {
	    if {[info exists data]} {
		if {[catch {set decoded [base64::decode $data]}]} {
		    # TODO
		    debugmsg jidlink "IBB: WRONG DATA"
		} else {
		    debugmsg jidlink "IBB: RECV DATA [list $data]"
		    jidlink::recv_data $stream_key($streamid) $decoded
		}
		
	    }
	    
	    if {[info exists close]} {
		jidlink::closed $stream_key($streamid)
	    }

	    return [list result ""]
	} else {
	    # TODO
	}
    } else {
	# TODO
    }
}

