package require msgcat

namespace eval ::jidlink {

    ::msgcat::mcload [file join [file dirname [info script]] msgs]

    set transport(list) {}
}

proc ::jidlink::connect {connid jid {key {}}} {
    variable connection

    if {$key == ""} {
	set key [rand 1000000000]
    }

    #set connection(sf,$key) $send_func
    #set connection(rf,$key) $recv_func
    set connection(connid,$key) $connid
    set connection(jid,$key) $jid

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

    jlib::send_iq set \
	[jlib::wrapper:createtag query \
	     -vars {xmlns jabber:iq:jidlink} \
	     -subtags [list [jlib::wrapper:createtag key -chdata $key]]] \
	-to $jid \
	-command [list [namespace current]::connect_response $connid $jid $key] \
	-connection $connid

    vwait [namespace current]::connection(status,$key)
    return connection(status,$key)
}

proc ::jidlink::connect_response {connid jid key res child} {
    variable connection
    variable transport

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

    set trans [lsort -unique -index 1 $transport(list)]
    set options {}
    foreach t $trans {
	set name [lindex $t 0]
	if {![info exists transport(allowed,$name)] || \
		$transport(allowed,$name)} {
	    lappend options $name
	}
    }

    if {[llength $options] == 0} {
	# TODO
	set connection(status,$key) 0
	return
    }

    lassign [negotiate::send_request $connid $jid jabber:iq:jidlink $options] res opts

    if {[llength $opts] == 1 && [lcontain $options [lindex $opts 0]]} {
	set name [lindex $opts 0]
	set connection(transport,$key) $name
	eval $transport(connect,$name) [list $connid $jid $key]
	set connection(status,$key) 1
	return
    }
    set connection(status,$key) 0
}


proc ::jidlink::set_readable_handler {key handler} {
    variable connection
    set connection(readable_handler,$key) $handler
}

proc ::jidlink::set_closed_handler {key handler} {
    variable connection
    set connection(closed_handler,$key) $handler
}

proc ::jidlink::send_data {key data} {
    variable connection
    variable transport
    eval $transport(send,$connection(transport,$key)) [list $key $data]
}

proc ::jidlink::recv_data {key data} {
    variable connection
    debugmsg jidlink "RECV_DATA [list $key $data]"

    append connection(data,$key) $data
    if {[info exists connection(readable_handler,$key)]} {
	eval $connection(readable_handler,$key) [list $key]
    }
}

proc ::jidlink::read_data {key} {
    variable connection

    set data $connection(data,$key)
    set connection(data,$key) {}
    return $data
}

proc ::jidlink::close {key} {
    variable connection
    variable transport
    eval $transport(close,$connection(transport,$key)) [list $key]
    set_status [::msgcat::mc "Jidlink connection closed"]
}

proc ::jidlink::closed {key} {
    variable connection
    if {[info exists connection(closed_handler,$key)]} {
	eval $connection(closed_handler,$key) [list $key]
    }
}


# TODO: connid
proc ::jidlink::negotiate_handler {from type options} {
    variable transport

    set trans [lsort -unique -index 1 $transport(list)]
    set myoptions {}
    foreach t $trans {
	set name [lindex $t 0]
	if {![info exists transport(allowed,$name)] || \
		$transport(allowed,$name)} {
	    lappend myoptions $transport(oppos,$name)
	}
    }

    if {$options == {}} {
	return $myoptions
    }

    foreach opt $options {
	if {[lcontain $myoptions $opt]} {
	    return [list $opt]
	}
    }
    return {}
}

negotiate::register_handler jabber:iq:jidlink ::jidlink::negotiate_handler


proc ::jidlink::set_handler {connid from lang child} {
    debugmsg jidlink "set: [list $from $child]"

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

    if {$tag == "query"} {
	foreach item $children {
	    jlib::wrapper:splitxml $item tag1 vars1 isempty1 chdata1 children1
	    if {$tag1 == "key"} {
		set key $chdata1
		debugmsg jidlink "KEY: $key"
	    }
	}

	if {[info exists key]} {
	    return [list result $child]

	} else {
	    # TODO
	}
    } else {
	# TODO
    }
}

iq::register_handler set query jabber:iq:jidlink ::jidlink::set_handler


proc ::jidlink::register_transport {name oppos prio connect send close} {
    variable transport

    lappend transport(list) [list $name $prio]
    set transport(oppos,$name) $oppos
    set transport(connect,$name) $connect
    set transport(send,$name) $send
    set transport(close,$name) $close
}

# Loading jidlink plugins
foreach file [lsort [glob -nocomplain \
		    [file join [file dirname [info script]] plugins]/*.tcl]] {
    debugmsg jidlink "Loading plugin from $file"
    source $file
}

proc ::jidlink::setup_customize {} {
    variable transport

    set trans [lsort -unique -index 1 $transport(list)]

    foreach t $trans {
	lassign $t name prio

	custom::defvar transport(allowed,$name) 1 \
	[format [::msgcat::mc "Enable Jidlink transport %s."] $name] \
	-type boolean -group Jidlink
    }
}

hook::add finload_hook ::jidlink::setup_customize 40

