# ho_stats_p.pl
#
# $Id: ho_stats_p.pl,v 1.7 2004/09/05 18:48:14 jvunder REL_0_3 $
#
# Part of the Hybrid Oper Script Collection
#
# Reformats /stats p output.
#

use strict;
use vars qw($VERSION %IRSSI $SCRIPT_NAME);

use Irssi;
use Irssi::Irc;
use HOSC::again;
use HOSC::again 'HOSC::Base';
use HOSC::again 'HOSC::Tools';
import HOSC::Tools qw(seconds_to_hms);

# ---------------------------------------------------------------------

$SCRIPT_NAME = 'Stats p reformat';
($VERSION) = '$Revision: 1.7 $' =~ / (\d+\.\d+) /;
my ($changed) = '$Id: ho_stats_p.pl,v 1.7 2004/09/05 18:48:14 jvunder REL_0_3 $' =~ / (\d+\/\d+\/\d+ \d+:\d+:\d+) /;
%IRSSI = (
    authors     => 'Garion',
    contact     => 'garion@efnet.nl',
    name        => 'ho_stats_p',
    description => 'Reformats stats p',
    license     => 'Public Domain',
    url         => 'http://www.garion.org/irssi/hosc/',
    changed     => $changed,
);

my %stats_p_data;
my @stats_p_idletimes;
my ($stats_p_num_tcm, $stats_p_num_bopm, $stats_p_num_ddd);


# ---------------------------------------------------------------------
# Adds this oper to the stats p data hash.

sub event_stats_p_line {
    my ($server, $data, $servername) = @_;

    my %oper;

    if ($data =~ /\[([OoAa])\](\[.*\])? (.+) \((.+)\) [Ii]dle:? ([0-9]+)/) {
        $oper{level}    = $1;
        $oper{flags}    = $2;
        $oper{nick}     = $3;
        $oper{hostmask} = $4;
        $oper{idle}     = $5;
	} else {
	    return;
	}

    if ($oper{nick} =~ /tcm$/i || $oper{hostmask} =~ /tcm@/i) { 
       $oper{tcm} = 1;
       $stats_p_num_tcm++;
    }

    $oper{bopm} = 0;
    if ($oper{nick} =~ /bopm$/i || $oper{hostmask} =~ /bopm@/i) { 
        $oper{bopm} = 1;
        $stats_p_num_bopm++;
    }

    if ($oper{nick} =~ /ddd/i || $oper{hostmask} =~ /ddd@/i) {
        $oper{ddd} = 1;
        $stats_p_num_ddd++;
    }
    
    $stats_p_data{ $oper{nick} } = \%oper;

    # Check if this idle time is already present in the array with
    # idle times; if not, add it.
    my $alreadypresent = 0;
    for my $idletime (@stats_p_idletimes) {
        if ($oper{idle} == $idletime) {
            $alreadypresent = 1;
            last;
        }
    }

    push @stats_p_idletimes, $oper{idle} unless $alreadypresent;

    Irssi::signal_stop();
}

# ---------------------------------------------------------------------

sub reemit_stats_p_line {
    my ($server, $data, $servername) = @_;

	# We need to re-emit this 249 numeric in case it contains data which
	# has nothing to do with stats p. Unfortunately, the end of STATS ?
	# also uses numeric 249, and we don't want to lose this data.

	# For some reason I do not comprehend, Irssi does not display
	# the first word of $args when re-emitting this signal. Hence
	# the 'dummy_data' addition.
	# Perhaps the number of the numeric should be here.
	# Perhaps there is a rational explanation.
	# I do not know, but this seems to work properly.
	Irssi::signal_emit("default event numeric", 
		$server, "dummy_data " . $data, $servername);
	Irssi::signal_stop();
}

# ---------------------------------------------------------------------
# Prints the hash of collected stats p data.

sub event_stats_end {
    my ($server, $data, $servername) = @_;

    return unless $data =~ /p :End of \/STATS report/;

    Irssi::signal_stop();

    print_stats_p_data($servername);

    undef %stats_p_data;
    undef @stats_p_idletimes;
    $stats_p_num_tcm = 0;
    $stats_p_num_bopm = 0;
}

# ---------------------------------------------------------------------
# Prints a list of opers, tcms and bopms, sorted by idle time.

sub print_stats_p_data {
    my ($servername) = @_;
    my @sorted_idletimes = sort {$a <=> $b} @stats_p_idletimes;

	Irssi::printformat(MSGLEVEL_CRAP, 'ho_stats_p_begin_report',
		$servername);
	Irssi::printformat(MSGLEVEL_CRAP, 'ho_stats_p_head_opers',
	    $servername);

    # Kind of clumsy way to sort these opers on idle times.
    # Sort the idle times, then for each idle time value, walk
    # through the whole hash of opers and print the one(s) with
    # this idle time.
    for my $idletime (@sorted_idletimes) {
        for my $opernick (keys %stats_p_data) {
            next unless $stats_p_data{$opernick}->{idle} == $idletime;

			next if $stats_p_data{$opernick}->{tcm} ||
                    $stats_p_data{$opernick}->{bopm} ||
                    $stats_p_data{$opernick}->{ddd};
            
			print_stats_p_oper($stats_p_data{$opernick});
        }
    }

    # Print the TCM(s)
    if ($stats_p_num_tcm > 0) { 
	    Irssi::printformat(MSGLEVEL_CRAP, 'ho_stats_p_head_tcm',
		    $servername);
        for my $opernick (keys %stats_p_data) {
            if ($stats_p_data{$opernick}->{tcm} == 1) { 
                print_stats_p_oper($stats_p_data{$opernick});
            }
        }
    }
   
    # Print the BOPM(s)
    if ($stats_p_num_bopm > 0) { 
	    Irssi::printformat(MSGLEVEL_CRAP, 'ho_stats_p_head_proxy',
		    $servername);
        foreach my $opernick (keys %stats_p_data) {
            if ($stats_p_data{$opernick}->{"bopm"} == 1) { 
                print_stats_p_oper($stats_p_data{$opernick});
            }
        }
    }

    # Print the DDD(s)
    if ($stats_p_num_ddd > 0) {
            Irssi::printformat(MSGLEVEL_CRAP, 'ho_stats_p_head_ddd',
	            $servername);
        for my $opernick (keys %stats_p_data) {
	        if ($stats_p_data{$opernick}->{"ddd"} == 1) {
	            print_stats_p_oper($stats_p_data{$opernick});
	        }
        }
    }
												
	Irssi::printformat(MSGLEVEL_CRAP, 'ho_stats_p_end_report',
		$servername);
}

# ---------------------------------------------------------------------
# Prints a line with idle time, nick and hostmask of this oper.
 
sub print_stats_p_oper {
    my ($oper) = @_;

    my ($hours, $mins, $secs) = seconds_to_hms($oper->{idle});

	Irssi::printformat(MSGLEVEL_CRAP, 'ho_stats_p_line', $oper->{nick},
		$hours, $mins, $secs, $oper->{hostmask});
}

# ---------------------------------------------------------------------

ho_print_init_begin();

#>> :irc.Prison.NET 249 Garion :[O] RFdrone (~asamonte@SanQuentin.Prison.NET) idle 31546s
#>> :irc.Prison.NET 219 Garion p :End of /STATS report
Irssi::signal_add_first('event 249', 'event_stats_p_line');
Irssi::signal_add_last('event 249', 'reemit_stats_p_line');
Irssi::signal_add_last('event 219', 'event_stats_end');

Irssi::theme_register( [
	'ho_stats_p_begin_report',
    '%YSTATS p report%n of $0',
	
	'ho_stats_p_head_opers',
    '* %_Operators%_ on $0:',

	'ho_stats_p_head_tcm',
    '* %_TCM bots%_ on $0:',

	'ho_stats_p_head_proxy',
    '* %_Proxy monitors%_ on $0:',

	'ho_stats_p_end_report',
    '* %_End of report%_ of $0',

	'ho_stats_p_line',
    '$[-9]0 $[-3]1:$[-2]2:$[-2]3 ($4)',

    	'ho_stats_p_head_ddd',
    '* %_DDD bots%_ on $0',
] );

ho_print("Output style is determined by ho_stats_p_* formats.");
ho_print_init_end();

# ---------------------------------------------------------------------

