############ Command Binds ###########################

a:command -add stats      pub:stats      1067 536 |v

############ Command Procs ###########################

proc pub:stats {hand chan args x mix} {
	global settings

	set option  [lindex  $args 0]
	set period  [lindex  $args 1]
	set level   [lindex  $args 2]
	set limit   [lindex  $args 3]
	set value   [lindex  $args 4]
	set outchan [lindex $x 2] 

	if { $option == "" || ![string is alnum $option]} {a:usage $x stats ; return "FAILED: not all parameters specified"}
	if {![::stats::channel -exists $chan]} {if {![string equal -nocase [lindex $x 2] $settings(homechan)]} {a:tell $x 238} ; return "FAILED: invalid chan ($chan)"}
	if {![regexp -- {^(channels|purge|join|reset|reload|templeave|time|joins|topics|traffic|traffics|users|bans|kicks|deops|ops|devoices|voices|banned|deopped|kicked|all)$} $option]} {a:usage $x stats ; return "FAILED: invalid parameters specified ($option)"}
	if {![regexp -- {^(hour|day|week|month|year)$} $period]} { set period day; set level [lindex $args 1]; set limit [lindex $args 2]; set value [lindex $args 3] }
	if {![a:check -digit $value] || ![regexp {^((min|max))$} $limit] || $level == ""} {

		if { [regexp -- {^(topics|bans|kicks|deops|ops|devoices|voices)$} $option]} {set limit min; set value 0     } elseif {
		     [regexp -- {^(banned|deopped|kicked)$} $option]}                       {set limit max; set value 2     } elseif {
		     [string equal $option users]}                                          {set limit min; set value 8     } elseif {
		     [string equal $option joins]}                                          {set limit min; set value 30    } elseif {
		     [string equal $option traffic]}                                        {set limit min; set value 100   } elseif {
		     [string equal $option traffics]}                                       {set limit min; set value 10000 } elseif {
		     [string equal $option channels] && ![check:v:gl $hand]}		    {return "FAILED: not enough access"} else {
											     set limit min; set value 0     
		}
	}

	if { [string equal $level global]} {
		
		set temp ""
		
		if { [regexp -- {^(join|purge|temleave|all|channels)$} $option]} {return "FAILED: invalid option ($option)"}
		if { [string equal $option reset]}    {if { [check:N:gl $hand]}  {::stats::channel -unload; foreach chan [channels] {::stats::channel -add $chan}; a:tell $x 2} {return "FAILED: not enough access"}} elseif {
		     [string equal $option reload]}   {if { [check:N:gl $hand]}  {::stats::channel -load; a:tell $x 153} {return "FAILED: not enough access"}} elseif {
		     [string equal $option users]}    {foreach chan [channels]   {set out [a:validate -secret $chan $outchan]; append temp " $out %b[::stats::channel -get $chan maxusers]/[::stats::average $option $chan $period $limit $value],"}; a:tell $x 240 "$option [string trimright $temp ,]"} elseif {
		     [string equal $option time]}     {foreach chan [channels]   {set out [a:validate -secret $chan $outchan]; append temp " $out %b[duration [::stats::channel -get $chan time]],"}; a:tell $x 240 "$option [string trimright $temp ,]"} else {
					               foreach chan [channels]   {set out [a:validate -secret $chan $outchan]; append temp " $out %b[::stats::channel -get $chan $option]/[::stats::average $option $chan $period $limit $value],"}; a:tell $x 240 "$option [string trimright $temp ,]" 
		}

		return "GLOBAL $option" 

	} else {

		if { [string equal $option reload]}   {return "FAILED: ${option}, not available locally"} elseif {
		     [string equal $option join]}     {if { [::stats::channel -get $chan joinwhom] == ""} {a:tell $x 238} {a:tell $x 241 "$chan $option »[join [ctime [::stats::channel -get $chan jointime]]]« [::stats::channel -get $chan joinwhom]"}} elseif {
		     [string equal $option reset]}    {if { [check:N:gl $hand]} {::stats::channel -add $chan {}; a:tell $x 3 "$chan"} {return "FAILED: not enough access"}} elseif {
		     [string equal $option users]}    {a:tell $x 244 "$chan [::stats::channel -get $chan maxusers] [::stats::average users $chan $period $limit $value] »[duration [::stats::channel -get $chan time]]«"} elseif {
		     [string equal $option time]}     {a:tell $x 243 "$chan »[duration [::stats::channel -get $chan time]]«"} elseif {
		     [string equal $option all]}      {a:tell $x 245 "$chan »[::stats::channel -get $chan joins]/[::stats::average joins $chan $period $limit $value]« »[::stats::channel -get $chan topics]/[::stats::average topics $chan $period $limit $value]« »[::stats::channel -get $chan traffic]/[::stats::average traffic $chan $period $limit $value]« »[::stats::channel -get $chan traffics]/[::stats::average traffics $chan $period $limit $value]« »[::stats::channel -get $chan maxusers]/[::stats::average users $chan $period $limit $value]« »[::stats::channel -get $chan bans]/[::stats::average bans $chan $period $limit $value]« »[::stats::channel -get $chan kicks]/[::stats::average kicks $chan $period $limit $value]« »[::stats::channel -get $chan deops]/[::stats::average deops $chan $period $limit $value]« »[::stats::channel -get $chan ops]/[::stats::average ops $chan $period $limit $value]« »[::stats::channel -get $chan devoices]/[::stats::average devoices $chan $period $limit $value]« »[::stats::channel -get $chan voices]/[::stats::average voices $chan $period $limit $value]« »[::stats::channel -get $chan banned]/[::stats::average banned $chan $period $limit $value]« »[::stats::channel -get $chan deopped]/[::stats::average deopped $chan $period $limit $value]« »[::stats::channel -get $chan kicked]/[::stats::average kicked $chan $period $limit $value]« $period »[duration [::stats::channel -get $chan time]]«"} elseif {
		     [string equal $option channels]} {set temp ""; foreach chan [::stats::channel -all] { if {![validchan $chan] } {set chan %r${chan}%%} {set chan %b[a:validate -secret $chan $outchan]%%}; lappend temp "${chan}," } ; a:tell $x 248 "[llength $temp] [string trimright [join $temp] ,]"} elseif {
		     [string equal $option traffic] || [string equal $option traffics]}  {a:tell $x 247 "$chan [::stats::channel -get $chan traffic] [::stats::channel -get $chan traffics] [::stats::average traffic $chan $period $limit $value] [::stats::average traffics $chan $period $limit $value] $period »[duration [::stats::average time $chan $period $limit $value]]«"} elseif {
    		     [string equal $option purge]   || [string equal $option templeave]} {if { [::stats::channel -get $chan ${option}whom] == ""} {a:tell $x 238} {a:tell $x 242 "$chan $option »[join [ctime [::stats::channel -get $chan ${option}time]]]« [::stats::channel -get $chan ${option}whom] »[::stats::channel -get $chan ${option}why]«"}} else {
						       a:tell $x 246 "$chan [::stats::channel -get $chan $option] $option [::stats::average $option $chan $period $limit $value] $option $period »[duration [::stats::channel -get $chan time]]«" 
		}

		return "$option"
	}
}

######################################################
############ STATS NAMESPACE START ###################
######################################################

namespace eval stats { 

############ Initializing variables ##################

variable stats
variable infofile

if {![info exists ::infofile]} {set infofile "${::username}.info"} {set infofile $::infofile}

############ Timed routines ##########################

proc 1_hour {min hour day month year} {

	foreach chan [string tolower [channels]] { 
	
		set length [llength [chanlist $chan]]
		
		if { [botonchan $chan]} { 

			if { [channel -get $chan maxusers] < $length } {channel -set $chan maxusers $length}
			if { [channel -get $chan time] < 3600} {channel -set $chan users $length} {
				set temp [expr [channel -get $chan users] + ($length - [channel -get $chan users])/([channel -get $chan time]/3600.0)] 
				channel -set $chan users [string range $temp 0 [expr [string first . $temp] +2]]
			}
			channel -incr $chan time 3600 
		}
	}
}

############ CORE ####################################

proc channel {cmd {chan ""} {options ""} {value ""}} {
	variable stats
	
	set chan [string tolower $chan]

	switch -exact -- $cmd {
		-get	{ return $stats($chan,$options)}
		-set	{ set stats($chan,$options) $value}
		-incr	{ if { [a:check -digit $value]} {incr stats($chan,$options) $value} {incr stats($chan,$options)}}
		-exists { return [info exists stats($chan,channels)]}
		-all	{ set temp ""; foreach w [array names stats *,channels] {lappend temp $stats($w)}; return $temp}
		-unload { if { [info exists stats]} {unset stats}}
		-load	{ global comm; variable infofile; channel -unload; if {![catch {source $infofile}]} {return 1} {return 0}}
		-verify { foreach x [channels] {if {![channel -exists $x]} {channel -add $x}}}
		-clean  { catch {array unset stats $chan,channels}}
		-add	{ if {$chan == ""} {return 0}
			set stats($chan,channels)     $chan

			set statistics                 [lindex $options 1]

			set stats($chan,time)          [a:validate -digit [lindex $statistics 0]]
			set stats($chan,joins)         [a:validate -digit [lindex $statistics 1]]
			set stats($chan,topics)        [a:validate -digit [lindex $statistics 2]]
			set stats($chan,traffic)       [a:validate -digit [lindex $statistics 3]]
			set stats($chan,traffics)      [a:validate -digit [lindex $statistics 4]]
			set stats($chan,maxusers)      [a:validate -digit [lindex $statistics 5]]
			set stats($chan,users)         [a:validate -digit [lindex $statistics 6]]
			set stats($chan,bans)          [a:validate -digit [lindex $statistics 7]]
			set stats($chan,kicks)         [a:validate -digit [lindex $statistics 8]]
			set stats($chan,deops)         [a:validate -digit [lindex $statistics 9]]
			set stats($chan,ops)           [a:validate -digit [lindex $statistics 10]]
			set stats($chan,voices)        [a:validate -digit [lindex $statistics 11]]
			set stats($chan,devoices)      [a:validate -digit [lindex $statistics 12]]

			set stats($chan,banned)        [a:validate -digit [lindex $statistics 13]]
			set stats($chan,deopped)       [a:validate -digit [lindex $statistics 14]]
			set stats($chan,kicked)        [a:validate -digit [lindex $statistics 15]]

			set misc                       [lindex $options 2]

			set join                       [lindex $misc 0]
			set stats($chan,jointime)      [a:validate -digit [lindex $join 0]]
			set stats($chan,joinwhom)      [lindex $join 1]

			set purge                      [lindex $misc 1]
			set stats($chan,purgetime)     [a:validate -digit [lindex $purge 0]]
			set stats($chan,purgewhom)     [lindex $purge 1]
			set stats($chan,purgewhy)      [join [lindex $purge 2]]
			
			set templeave                  [lindex $misc 2]
			set stats($chan,templeavetime) [a:validate -digit [lindex $templeave 0]]
			set stats($chan,templeavewhom) [lindex $templeave 1]
			set stats($chan,templeavewhy)  [join [lindex $templeave 2]]

			set topic                      [lindex $misc 3]
			set stats($chan,topictime)     [a:validate -digit [lindex $topic 0]]
			set stats($chan,topicwhom)     [lindex $topic 1]
			set stats($chan,topictext)     [join [lindex $topic 2]]

			set stats($chan,url)	       [join [lindex $misc 4]]
			set stats($chan,faq)           [join [lindex $misc 5]]
			set stats($chan,fuck)          [join [lindex $misc 6]]
			set stats($chan,news)          [join [lindex $misc 7]]
			set stats($chan,desc)          [join [lindex $misc 8]]
			set stats($chan,mail)          [join [lindex $misc 9]]
			set stats($chan,slap)          [join [lindex $misc 10]]
			set stats($chan,kiss)          [join [lindex $misc 11]]
			set stats($chan,rules)         [join [lindex $misc 12]]
			set stats($chan,ban-reason)    [join [lindex $misc 13]]
			set stats($chan,output)        [join [lindex $misc 14]]

                        set stats($chan,ban-reason)    [join [lindex $misc 13]]
                        set stats($chan,output)        [join [lindex $misc 14]]
                        set stats($chan,kick-reason)        [join [lindex $misc 15]]

                        return 1
                }
                default {return 0}
        }
}

proc average {options chan period limit value} {
	variable stats

	set chan [string tolower $chan]

	if { [string equal $period year] } {set period 31536000.0 } elseif {
	     [string equal $period month]} {set period 2592000.0 } elseif {
	     [string equal $period week] } {set period 604800.0 } elseif {
	     [string equal $period day]  } {set period 86400.0 } elseif {
	     [string equal $period hour] } {set period 3600.0  } else {set period 86400.0 }

	if { $stats($chan,time) < $period } {return "%bn/a%%"}

	set temp   [expr $stats($chan,$options) * $period  / $stats($chan,time)]
	set result [string range $temp 0 [expr [string first . $temp] +2]]

	if { [string equal $options users]} {set result $stats($chan,users)}
        if { [string equal $limit max]} {

	if { $result > $value} {return "%r${result}%%"} {return "${result}%%"}} {
	if { $result < $value} {return "%r${result}%%"} {return "${result}%%"}}
}

proc save {{foo ""}} {
	global username; variable infofile; variable stats
			
	set file [open $infofile w] 

	catch { 
		puts $file "#Dynamic Info Channel File for $username -- written [ctime [unixtime]]\n"

		foreach chan [string tolower [channels]] {if {![info exists stats($chan,channels)]} {::stats::channel -add $chan {}}}
		foreach chan [channel -all] {
			
			puts $file "::stats::channel -add [split $chan] {{RESERVED}\
				    {$stats($chan,time)\
				     $stats($chan,joins)\
				     $stats($chan,topics)\
				     $stats($chan,traffic)\
				     $stats($chan,traffics)\
				     $stats($chan,maxusers)\
				     $stats($chan,users)\
				     $stats($chan,bans)\
				     $stats($chan,kicks)\
				     $stats($chan,deops)\
				     $stats($chan,ops)\
				     $stats($chan,voices)\
				     $stats($chan,devoices)\
				     $stats($chan,banned)\
				     $stats($chan,deopped)\
				     $stats($chan,kicked)}\
				    {{$stats($chan,jointime) [split $stats($chan,joinwhom)]}\
				     {$stats($chan,purgetime) [split $stats($chan,purgewhom)] {[split $stats($chan,purgewhy)]}}\
				     {$stats($chan,templeavetime) [split $stats($chan,templeavewhom)] {[split $stats($chan,templeavewhy)]}}\
				     {$stats($chan,topictime) [split $stats($chan,topicwhom)] {[split $stats($chan,topictext)]}}\
				     {[split $stats($chan,url)]}\
				     {[split $stats($chan,faq)]}\
				     {[split $stats($chan,fuck)]}\
				     {[split $stats($chan,news)]}\
				     {[split $stats($chan,desc)]}\
				     {[split $stats($chan,mail)]}\
				     {[split $stats($chan,slap)]}\
				     {[split $stats($chan,kiss)]}\
				     {[split $stats($chan,rules)]}\
				     {[split $stats($chan,ban-reason)]}\
				     {[split $stats($chan,output)]}}}\
                             {[split $stats($chan,kick-reason)]}"
		}
			puts $file "\n#Disabled local & global commands\n"
			puts $file "[a:command -array]"

	       return ok
	} ok

	close $file

	if {![string equal $ok ok]} {
		a:log high "FAILED to write info file, error: $ok" 
		a:announce -permowner ERROR "FAILED to write info file, error: $ok"
	} else {
		global {quiet-save}
		if {!${quiet-save}} {putlog "Writing info file ..."}
	}
}
		
proc restore {} {
	variable infofile

	if { [file exists ${infofile}~bak]} {

		a:log routines "No infofile found, restoring from backup."
		file copy ${infofile}~bak $infofile} elseif {
	    
	     [file exists ${infofile}~bak~bak]} {

		a:log routines "No infofile found, restoring from backup."
		file copy ${infofile}~bak~bak $infofile} elseif {

	     [file exists ${infofile}~bak~bak~bak]} {

		a:log routines "No infofile found, restoring from backup."
		file copy ${infofile}~bak~bak~bak $infofile} else {

		a:log routines "No infofile found, creating a new one." 
		save
	}
}


############ Modes ###################################

proc modes {nick uhost hand chan mode target} {

	switch -- $mode {
		
		"-v"	{channel -incr $chan devoices}
		"+v"	{channel -incr $chan voices}
		"+o"	{channel -incr $chan ops
			 if { [isbotnick $target]} {a:bind:topic nonick nouhost nohandspecified $chan "[topic $chan]"}
		}
		"-o"	{channel -incr $chan deops
			 if { [isbotnick $target]} {channel -incr $chan deopped}
		}
		"+b"	{channel -incr $chan bans
			 if { [isbotnick $target]} {channel -incr $chan banned}
		}
		"-b"	{ }
		default {a:flood -modes $chan $hand $uhost $nick}

	}
}

proc kicks {nick uhost hand chan target reason} {

	channel -incr $chan kicks
	if { [isbotnick $target]} {channel -incr $chan kicked}
}

############ Routines ################################

setudef flag stats

if {![file exists $infofile]} {restore}
if {![info exists stats]} {if { [channel -load]} {a:log routines "Infofile loaded, proceeding..."}; channel -verify}

############ Binded procs ############################

proc joins  {nick uhost hand chan}	 {channel -incr $chan joins }
proc topics {nick uhost hand chan topic} {channel -incr $chan topics }
proc pubm   {nick uhost hand chan arg}	 {

	channel -incr $chan traffic
	channel -incr $chan traffics [string length $arg]
}

}

######################################################
############ STATS NAMESPACE END #####################
######################################################


############ Binds ###################################

bind time - "00 * * * *"	::stats::1_hour

bind mode -|- *			::stats::modes
bind kick -|- *			::stats::kicks

bind join -|- *			::stats::joins
bind topc -|- *			::stats::topics
bind pubm -|- *			::stats::pubm

bind evnt - save		::stats::save


############ for compatibility to avoid errors
############ to remove in the next version

proc a:channel {cmd {chan ""} {options ""} {value ""}} {
}

return "stats module"
#/OBF
