# $Id: ejabberd.tcl 1354 2008-01-28 17:39:01Z sergei $

package require msgcat

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

namespace eval ejabberd {
    custom::defvar ejabberd_server_list {} \
	[::msgcat::mc "List of ejabberd servers."] \
	-group Hidden
}

set ::NS_ECONFIGURE "http://ejabberd.jabberstudio.org/protocol/configure"

proc ejabberd::setup_menu {} {
    catch {
        set m [.mainframe getmenu admin]

        $m add command -label [::msgcat::mc "Administrate ejabberd..."] \
	    -command [namespace current]::ask_server_dialog
    }
}

hook::add finload_hook [namespace current]::ejabberd::setup_menu

disco::browser::register_feature_handler $::NS_ECONFIGURE \
    [namespace current]::ejabberd::open_win \
    -desc [list * [::msgcat::mc "Administrate ejabberd"]]

proc ejabberd::ask_server_dialog {} {
    global ejabberd_server
    global ejabberd_connid
    variable ejabberd_server_list

    set gw .ejabberdserver
    catch { destroy $gw }

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

    set ejabberd_connid [jlib::connection_jid [lindex [jlib::connections] 0]]

    Dialog $gw -title [::msgcat::mc "ejabberd server"] -separator 1 -anchor e \
	    -default 0 -cancel 1

    set gf [$gw getframe]
    grid columnconfigure $gf 1 -weight 1

    if {[llength $ejabberd_server_list]} {
	set ejabberd_server [lindex $ejabberd_server_list 0]
    }

    label $gf.ljid -text [::msgcat::mc "Server JID:"]
    ComboBox $gf.jid \
	     -textvariable ejabberd_server \
	     -values $ejabberd_server_list \
	     -width 35

    grid $gf.ljid -row 0 -column 0 -sticky e
    grid $gf.jid  -row 0 -column 1 -sticky ew

    if {[llength [jlib::connections]] > 1} {
	foreach c [jlib::connections] {
	    lappend connections [jlib::connection_jid $c]
	}
	set ejabberd_connid [lindex $connections 0]

	label $gf.lconnid -text [::msgcat::mc "Connection:"]
	ComboBox $gf.connid \
		 -textvariable ejabberd_connid \
		 -values $connections \
		 -editable 0

	grid $gf.lconnid -row 1 -column 0 -sticky e
	grid $gf.connid  -row 1 -column 1 -sticky ew
    }

    $gw add -text [::msgcat::mc "Administrate"] -command "[namespace current]::administrate $gw"
    $gw add -text [::msgcat::mc "Cancel"] -command "destroy $gw"

    $gw draw $gf.jid
}

proc ejabberd::administrate {gw} {
    global ejabberd_server
    global ejabberd_connid
    variable ejabberd_server_list

    destroy $gw

    set ejabberd_server_list \
	[update_combo_list $ejabberd_server_list $ejabberd_server 10]

    foreach c [jlib::connections] {
	if {[jlib::connection_jid $c] == $ejabberd_connid} {
	    set connid $c
	}
    }

    if {![info exists connid]} return

    open_win $ejabberd_server -connection $connid
}


proc ejabberd::open_win {jid args} {

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

    if {![info exists connid]} {
	return -code error "ejabberd::open_win: -connection is mandatory"
    }

    set w [win_id ejabberd $connid:$jid]
    if {[winfo exists $w]} {
	raise_win $w
	return
    }

    set title [format [::msgcat::mc "%s administration"] $jid]
    add_win $w -title $title \
	       -tabtitle $jid \
	       -class Ejabberd \
	       -raise 1

    set nb [NoteBook $w.nb]
    pack $nb -fill both -expand yes

    # Binding $nb, not $w to avoid multiple calls if $w is a toplevel
    bind $nb <Destroy> [list [namespace current]::cleanup $connid $jid]

    foreach {page title} \
	[list main   [::msgcat::mc "Main"] \
	      nodes  [::msgcat::mc "Nodes"] \
	      reg    [::msgcat::mc "Registration"] \
	      access [::msgcat::mc "Access"] \
	      last   [::msgcat::mc "Last Activity"]] {
	set f [$nb insert end $page -text $title]

	fill_page_$page $f $connid $jid
    }
    $nb raise main
}

proc ejabberd::cleanup {connid jid} {
    variable data

    catch {unset data($connid,$jid,total_users)}
    catch {unset data($connid,$jid,online_users)}
    catch {unset data($connid,$jid,running_nodes)}
    catch {unset data($connid,$jid,stopped_nodes)}
    catch {unset data($connid,$jid,outgoing_s2s)}
    catch {unset data($connid,$jid,welcome_subj)}
    catch {unset data($connid,$jid,welcome_body)}
    catch {unset data($connid,$jid,reg_watchers)}
    catch {unset data($connid,$jid,acls)}
    catch {unset data($connid,$jid,access_rules)}
    catch {unset data($connid,$jid,last)}
    catch {unset data($connid,$jid,last_int)}
}

proc ejabberd::add_grid_record {connid jid info name desc row} {
    label $info.l$name -text $desc
    label $info.v$name -textvariable [namespace current]::data($connid,$jid,$name)
    grid $info.l$name -row $row -column 0 -sticky e
    grid $info.v$name -row $row -column 1 -sticky w
}

proc ejabberd::add_grid_edit {connid jid info name desc row} {
    label $info.l$name -text $desc
    entry $info.v$name -textvariable [namespace current]::data($connid,$jid,$name)
    grid $info.l$name -row $row -column 0 -sticky e
    grid $info.v$name -row $row -column 1 -sticky we
}

proc ejabberd::add_grid_text {connid jid info name desc row} {
    label $info.l$name -text $desc
    set sw [ScrolledWindow $info.s$name -scrollbar vertical]
    text $info.v$name -height 6 -wrap word
    $sw setwidget $info.v$name
    grid $info.l$name -row $row -column 0 -sticky e
    grid $info.s$name -row $row -column 1 -sticky we
}

proc ejabberd::fill_page_main {f connid jid} {
    variable data

    set info [frame $f.info]
    pack $info -side top -anchor w -fill both

    grid columnconfigure $info 1 -weight 2

    add_grid_record $connid $jid $info total_users   [::msgcat::mc "Registered users:"] 0
    add_grid_record $connid $jid $info online_users  [::msgcat::mc "Online users:"]     1
    add_grid_record $connid $jid $info running_nodes [::msgcat::mc "Running nodes:"]    2
    add_grid_record $connid $jid $info stopped_nodes [::msgcat::mc "Stopped nodes:"]    3
    add_grid_record $connid $jid $info outgoing_s2s  [::msgcat::mc "Outgoing S2S:"]     4

    set reload \
	[button $f.reload -text [::msgcat::mc "Reload"] \
	     -command [list [namespace current]::reload_page_main $f $connid $jid]]
    pack $reload -side bottom -anchor e
    reload_page_main $f $connid $jid
}

proc ejabberd::reload_page_main {f connid jid} {
    jlib::send_iq get \
	[jlib::wrapper:createtag info \
	     -vars [list xmlns $::NS_ECONFIGURE]] \
	-to $jid \
	-connection $connid \
	-command [list [namespace current]::parse_main_info $f $connid $jid]
}

proc ejabberd::parse_main_info {f connid jid res child} {
    variable data

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

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

    set data($connid,$jid,total_users)   [jlib::wrapper:getattr $vars registered-users]
    set data($connid,$jid,online_users)  [jlib::wrapper:getattr $vars online-users]
    set data($connid,$jid,running_nodes) [jlib::wrapper:getattr $vars running-nodes]
    set data($connid,$jid,stopped_nodes) [jlib::wrapper:getattr $vars stopped-nodes]
    set data($connid,$jid,outgoing_s2s)  [jlib::wrapper:getattr $vars outgoing-s2s-servers]
}


proc ejabberd::fill_page_nodes {f connid jid} {
}

proc ejabberd::fill_page_reg {f connid jid} {
    variable data

    set info [frame $f.info]
    pack $info -side top -anchor w -fill both

    grid columnconfigure $info 1 -weight 2

    add_grid_edit $connid $jid $info welcome_subj [::msgcat::mc "Welcome message subject:"] 0
    add_grid_text $connid $jid $info welcome_body [::msgcat::mc "Welcome message body:"]    1
    add_grid_text $connid $jid $info reg_watchers [::msgcat::mc "Registration watchers:"]   2


    #set set_b [button $f.set -text [::msgcat::mc "Set"]]
    #pack $set_b -side right -anchor se
    set reload \
	[button $f.reload -text [::msgcat::mc "Reload"] \
	     -command [list [namespace current]::reload_page_reg $f $connid $jid]]
    pack $reload -side right -anchor se
    reload_page_reg $f $connid $jid
}

proc ejabberd::reload_page_reg {f connid jid} {
    jlib::send_iq get \
	[jlib::wrapper:createtag welcome-message \
	     -vars [list xmlns $::NS_ECONFIGURE]] \
	-to $jid \
	-connection $connid \
	-command [list [namespace current]::parse_welcome_message $f $connid $jid]
    jlib::send_iq get \
	[jlib::wrapper:createtag registration-watchers \
	     -vars [list xmlns $::NS_ECONFIGURE]] \
	-to $jid \
	-connection $connid \
	-command [list [namespace current]::parse_registration_watchers $f $connid $jid]
}

proc ejabberd::parse_welcome_message {f connid jid res child} {
    variable data

    set wsubj $f.info.vwelcome_subj
    set wbody $f.info.vwelcome_body

    if {![winfo exists $wsubj]} {
	return
    }

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

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

    set subj ""
    set body ""

    foreach ch $children {
	jlib::wrapper:splitxml $ch tag1 vars1 isempty1 chdata1 children1

	switch -- $tag1 {
	    subject {set subj $chdata1}
	    body {set body $chdata1}
	}
    }

    set data($connid,$jid,welcome_subj) $subj
    set data($connid,$jid,welcome_body) $body
    $wbody delete 0.0 end
    $wbody insert 0.0 $body
}


proc ejabberd::parse_registration_watchers {f connid jid res child} {
    variable data

    set wwatchers $f.info.vreg_watchers

    if {![winfo exists $wwatchers]} {
	return
    }

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

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

    set jids {}

    foreach ch $children {
	jlib::wrapper:splitxml $ch tag1 vars1 isempty1 chdata1 children1

	switch -- $tag1 {
	    jid {lappend jids $chdata1}
	}
    }

    set data($connid,$jid,reg_watchers) $jids
    $wwatchers delete 0.0 end
    $wwatchers insert 0.0 [join $jids \n]
}



proc ejabberd::fill_page_access {f connid jid} {
    variable data

    set info [frame $f.info]
    pack $info -side top -anchor w -fill both

    grid columnconfigure $info 1 -weight 2

    add_grid_text $connid $jid $info acls         [::msgcat::mc "ACLs:"]         0
    add_grid_text $connid $jid $info access_rules [::msgcat::mc "Access rules:"] 1


    #set set_b [button $f.set -text [::msgcat::mc "Set"]]
    #pack $set_b -side right -anchor se
    set reload \
	[button $f.reload -text [::msgcat::mc "Reload"] \
	     -command [list [namespace current]::reload_page_access $f $connid $jid]]
    pack $reload -side right -anchor se

    reload_page_access $f $connid $jid
}

proc ejabberd::reload_page_access {f connid jid} {
    jlib::send_iq get \
	[jlib::wrapper:createtag acls \
	     -vars [list xmlns $::NS_ECONFIGURE]] \
	-to $jid \
	-connection $connid \
	-command [list [namespace current]::parse_access acls $f $connid $jid]
    jlib::send_iq get \
	[jlib::wrapper:createtag access \
	     -vars [list xmlns $::NS_ECONFIGURE]] \
	-to $jid \
	-connection $connid \
	-command [list [namespace current]::parse_access access_rules $f $connid $jid]
}

proc ejabberd::parse_access {var f connid jid res child} {
    variable data

    set w $f.info.v$var

    if {![winfo exists $w]} {
	return
    }

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

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

    set data($connid,$jid,$var) $chdata
    $w delete 0.0 end
    $w insert 0.0 $chdata
}


proc ejabberd::fill_page_last {f connid jid} {
    variable data

    set info [frame $f.info]
    pack $info -side top -anchor w -fill both -expand yes

    #grid columnconfigure $info 1 -weight 2

    #add_grid_text $connid $jid $info acls         [::msgcat::mc "ACLs:"]         0
    #add_grid_text $connid $jid $info access_rules [::msgcat::mc "Access rules:"] 1

    label $info.lplot \
	-text [::msgcat::mc \
		   "Number of users that used this service N days ago:"]
    pack $info.lplot -side top -anchor w

    set sw [ScrolledWindow $info.sw]
    pack $sw -side top -fill both -expand yes
    set plot [canvas $info.plot -background white]
    $sw setwidget $plot

    set data($connid,$jid,last) {}
    set data($connid,$jid,last_int) 0

    set integral \
	[checkbutton $f.integral -text [::msgcat::mc "Integral"] \
	     -variable [namespace current]::data($connid,$jid,last_int) \
	     -command [list [namespace current]::redraw_last $f $connid $jid]]
    pack $integral -side left -anchor se

    set reload \
	[button $f.reload -text [::msgcat::mc "Reload"] \
	     -command [list [namespace current]::reload_page_last $f $connid $jid]]
    pack $reload -side right -anchor se
}

proc ejabberd::reload_page_last {f connid jid} {
    jlib::send_iq get \
	[jlib::wrapper:createtag last \
	     -vars [list xmlns $::NS_ECONFIGURE]] \
	-to $jid \
	-connection $connid \
	-command [list [namespace current]::parse_last $f $connid $jid]
}

proc ejabberd::parse_last {f connid jid res child} {
    variable data

    set plot $f.info.plot

    if {![winfo exists $plot]} {
	return
    }

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

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

    set data($connid,$jid,last) $chdata

    redraw_last $f $connid $jid
}

proc ejabberd::redraw_last {f connid jid} {
    variable data

    set plot $f.info.plot

    set maxdays 0

    foreach t $data($connid,$jid,last) {
	set days [expr {$t / (60*60*24)}]
	if {$days > $maxdays} {set maxdays $days}

	if {![info exists last($days)]} {
	    set last($days) 0
	}
	incr last($days)
    }

    set xscale 20
    set yscale 200

    $plot delete all

    set val 0

    for {set i 0} {$i <= $maxdays} {incr i} {
	if {[info exists last($i)]} {
	    set v $last($i)
	} else {
	    set v 0
	}

	if {$data($connid,$jid,last_int)} {
	    incr val $v
	} else {
	    set val $v
	}

	set x1 [expr {$xscale * $i}]
	set x2 [expr {$xscale * ($i+1)}]
	set x [expr {($x1 + $x2)/2}]
	set y [expr {-$yscale * $val}]

	$plot create rectangle $x1 0 $x2 $y -fill red

	$plot create text $x 0 -text $i -anchor n
	$plot create text $x $y -text $val -anchor s
    }

    set bbox [$plot bbox all]

    set y1 [lindex $bbox 1]
    set y2 [lindex $bbox 3]
    set height [winfo height $plot]

    $plot scale all 0 0 1 [expr {0.9 * $height / (0.0 + $y2 - $y1)}]
    $plot configure -scrollregion [$plot bbox all]
}
