#!/usr/bin/perl -w

use utf8;
use strict;
use warnings; no warnings qw(once redefine uninitialized);

BEGIN {
    unshift @INC, ( $ENV{'POPHOME'} || '@POPHOME@' ) . '/lib'
      unless $ENV{'KUNDE_NO_PERLPATH'};
}

use Cf qw($BGCOLOR);
use CGI();
use CGI::Carp 'fatalsToBrowser';
use FindBin();
use HTML::Entities 'encode_entities';
use File::Spec();
use URI::Escape 'uri_escape';

use constant {
    COLOR => { open => '#FF0000', stalled => '#FFFF00', resolved => '#00FF00' },
    ENCODING => 'utf-8',
    PERIODS  => {
        Tag   => -86400,
        Woche => 7 * -86400,
        Monat => 30 * -86400,
        Jahr  => 365 * -86400,
        alles => 1128117600,
    },
    RRD_DIRECTORY => '/www/data/rt-queue_stats',
    TITLE         => 'RT-Queue-Statistiken',
};
use constant STATUS => qw(open stalled resolved);

my $cgi = new CGI;

my @queues = $cgi->param('queue');

sub abs_time($) {
    if   ( ( my $time = shift ) < 0 ) { $^T + $time }
    else                              { $time }
}

my @periods = sort $cgi->param('period');
@periods =
  sort { abs_time( PERIODS->{$b} ) <=> abs_time( PERIODS->{$a} ) }
  keys %{ +PERIODS }
  unless @periods;

if ( @queues == 1 && @periods == 1 ) {
    require RRDs;
    my $rrd = File::Spec->catfile( RRD_DIRECTORY, "@queues.rrd" );
    my @status = grep { defined ( COLOR->{$_}) } ($cgi->param ('status'));
    @status = STATUS unless (@status);
    $| = 1;
    print $cgi->header('image/png');
    my @cmd = ('-', '-s', PERIODS->{$periods[0]},
    '-t', "Queue @queues", '-v', 'Tickets',
    '-l', '0', '--units-exponent', '0');
    for (@status) {
	push (@cmd, "DEF:raw_$_=$rrd:$_:AVERAGE");
    }
    {
	my @tmp = @status;
	while (@tmp)
	{
	    my $foo = shift (@tmp);
	    my $cdef = "CDEF:acc_$foo=" . join (',', map { "raw_$_" } ($foo, @tmp));
	    $cdef .= ',+'x(scalar (@tmp)) if (@tmp);
	    push (@cmd, $cdef);
	}
    }
    for (@status) {
	push (@cmd, sprintf ('AREA:acc_%s%s:%-8s', $_, COLOR->{$_}, $_));
	push (@cmd,
	"GPRINT:raw_$_:MIN:%6.0lf min,",
	"GPRINT:raw_$_:AVERAGE:%6.0lf avg,",
	"GPRINT:raw_$_:MAX:%6.0lf max,",
	"GPRINT:raw_$_:LAST:%6.0lf last\\l");
    }
    RRDs::graph (@cmd) or die (RRDs::error ());
}
elsif ( @queues > 1 && @periods == 1 ) {
    require RRDs;
    my $title = @queues > 5 ? 'Many queues (' . scalar (@queues) . ' total)' : 'Queues ' . join (', ', @queues);
    my @status = grep { defined ( COLOR->{$_}) } ($cgi->param ('status'));
    @status = STATUS unless (@status);
    print $cgi->header('image/png');
    my @cmd = ('-', '-s', PERIODS->{$periods[0]}, '-t', $title, '-v', 'Tickets',
    '-l', '0', '--units-exponent', '0');
    for (@queues) {
	my $q = $_;
	my $rrd = File::Spec->catfile( RRD_DIRECTORY, "$q.rrd" );
	for (@status) {
	    push (@cmd, "DEF:raw_${q}_$_=$rrd:$_:AVERAGE");
	}
    }
    for (@status) {
	my $s = $_;
	push (@cmd, "CDEF:acc_$s=" . join (',', map { "raw_" . $_ . "_$s" } (@queues)) . ',+'x(@queues-1));
    }
    {
	my @tmp = @status;
	while (@tmp)
	{
	    my $foo = shift (@tmp);
	    my $cdef = "CDEF:total_$foo=" . join (',', map { "acc_$_" } ($foo, @tmp));
	    $cdef .= ',+'x(scalar (@tmp)) if (@tmp);
	    push (@cmd, $cdef);
	}
    }
    for (@status) {
	push (@cmd, sprintf ('AREA:total_%s%s:%-8s', $_, COLOR->{$_}, $_));
	push (@cmd,
	"GPRINT:acc_$_:MIN:%6.0lf min,",
	"GPRINT:acc_$_:AVERAGE:%6.0lf avg,",
	"GPRINT:acc_$_:MAX:%6.0lf max,",
	"GPRINT:acc_$_:LAST:%6.0lf last\\l");
    }
    RRDs::graph (@cmd) or die (RRDs::error ());
}
else {
    binmode STDOUT, ':raw :encoding(' . ENCODING . ')';

    print $cgi->header( -lang => 'de-DE', -charset => ENCODING ),
      $cgi->start_html(
        -bgcolor  => $BGCOLOR,
        -encoding => ENCODING,
        -title    => TITLE,
        -style    => { -code => <<CSS } );
      td { vertical-align: top; }
CSS

    unless (@queues) {
        opendir my $rrd_dir, RRD_DIRECTORY
          or die "opendir('${\RRD_DIRECTORY}'): $!\n";
        while ( defined( my $entry = readdir $rrd_dir ) ) {
            push @queues, $1
              if -f File::Spec->catfile( RRD_DIRECTORY, $entry )
              && $entry =~ /^(.*)\.rrd\z/;
        }
    }
    @queues = sort @queues;

    if ( @queues == 1 ) {
        my $query_prefix =
          uri_escape($FindBin::Script)
          . '?queue='
          . uri_escape(@queues)
          . ';period=';
        print $cgi->h1( 'Statistik für RT-Queue ' . encode_entities(@queues) );
	print "  <table>\n";
	for (@periods) {
	    print
	    qq(    <tr>\n),
	    qq(      <td><img src="$query_prefix) . uri_escape ($_) . qq(" /></td>\n),
	    qq(      <td><img src="$query_prefix) . uri_escape ($_) . qq(;status=open;status=stalled" /></td>\n),
	    qq(    </tr>\n);
	}
	print "  </table>\n";
    }
    elsif ( @periods == 1 ) {
        my $query_prefix =
          uri_escape($FindBin::Script)
          . '?period='
          . uri_escape(@periods)
          . ';queue=';
        print $cgi->h1('Statistik für alle Queues'), $/;
	print
	qq(  <table>\n),
	qq(    <tr>\n),
	qq(      <td><img src="$query_prefix) . join (';queue=', map { uri_escape ($_) } (@queues)) . qq(" /></td>\n),
	qq(      <td><img src="$query_prefix) . join (';queue=', map { uri_escape ($_) } (@queues)) . qq(;status=open;status=stalled" /></td>\n),
	qq(    </tr>\n);
	for (@queues)
	{
	    print
	    qq(    <tr>\n),
	    qq(      <td><img src="$query_prefix) . uri_escape ($_) . qq(" /></td>\n),
	    qq(      <td><img src="$query_prefix) . uri_escape ($_) . qq(;status=open;status=stalled" /></td>\n),
	    qq(    </tr>\n);
	}
	print "  </table>\n";
    }
    else {
        print $cgi->h1(TITLE);
        print $cgi->h2('Statistiken für einzelne Queues:'),
          $cgi->ul(
            $cgi->li(
                [
                    map $cgi->a(
                        { href => "?queue=" . uri_escape($_) },
                        encode_entities($_)
                    ),
                    @queues
                ]
            )
          ),
          $cgi->h2('Statistiken für alle Queues:'),
          $cgi->ul(
            $cgi->li(
                [
                    map $cgi->a(
                        { href => '?period=' . uri_escape($_) },
                        encode_entities($_)
                    ),
                    @periods
                ]
            )
        );
    }
    print $cgi->end_html;
}

# vim:softtabstop=4
