package Onis::Plugins::Longterm;

use strict;
use warnings;

use Exporter;

use Onis::Config (qw(get_config));
use Onis::Html (qw(get_filehandle));
use Onis::Language (qw(translate));
use Onis::Data::Core (qw(register_plugin get_main_nick get_most_recent_time nick_to_ident nick_to_name));
use Onis::Data::Persistent ();

=head1 NAME

Onis::Plugins::Longterm

=cut

@Onis::Plugins::Longterm::EXPORT_OK = (qw(get_longterm));
@Onis::Plugins::Longterm::ISA = ('Exporter');

register_plugin ('TEXT', \&add);
register_plugin ('ACTION', \&add);
register_plugin ('OUTPUT', \&output);

our $LongtermLastSeen = Onis::Data::Persistent->new ('LongtermLastSeen', 'nick', 'day');
our $LongtermCache    = Onis::Data::Persistent->new ('LongtermCache', 'key', qw(time0 time1 time2 time3));
our $LongtermData     = {};

=head1 CONFIGURATION OPTIONS

=over 4

=item B<vertical_images>: I<image0>, I<image1>, I<image2>, I<image3>;

Sets the images to use for vertical graphs.

=cut

our @VImages = get_config ('vertical_images');
if (scalar (@VImages) != 4)
{
	@VImages = qw#images/ver0n.png images/ver1n.png images/ver2n.png images/ver3n.png#;
}

=item B<longterm_days>: I<31>;

Sets the number of days displayed by this plugin.

=cut

our $DisplayDays = 31;
if (get_config ('longterm_days'))
{
	my $tmp = get_config ('longterm_days');
	$tmp =~ s/\D//g;
	$DisplayDays = $tmp if ($tmp);
}

=back

=cut

my $VERSION = '$Id$';
print STDERR $/, __FILE__, ": $VERSION" if ($::DEBUG);

return (1);

sub add
{
	my $data = shift;
	my $nick = $data->{'nick'};
	my $time = $data->{'epoch'};
	my $hour = int ($data->{'hour'} / 6);
	my $chars = length ($data->{'text'});
	my $day   = int ($time / 86400);
	my $index = ($day * 4) + $hour;

	my ($lastseen) = $LongtermLastSeen->get ($nick);
	$lastseen ||= $day;
	
	for (my $i = $lastseen; $i < $day; $i++)
	{
		my $last = $i - $DisplayDays;
		$LongtermCache->del ($nick . ':' . $last);

		if ($i != $lastseen)
		{
			$LongtermCache->put ($nick . ':' . $i, qw(0 0 0 0));
		}
	}

	my @data = $LongtermCache->get ($nick . ':' . $day);
	@data = (qw(0 0 0 0)) unless (@data);
	$data[$hour] += $chars;
	$LongtermCache->put ($nick . ':' . $day, @data);

	$LongtermLastSeen->put ($nick, $day);
}

sub calculate
{
	my $now_epoch = get_most_recent_time ();
	my $now = int ($now_epoch / 86400);
	return unless ($now);

	my $old = 1 + $now - $DisplayDays;

	my $del = {};

	for ($LongtermLastSeen->keys ())
	{
		my $nick = $_;
		my ($last) = $LongtermLastSeen->get ($nick);

		if ($last < $old)
		{
			$del->{$nick} = $last;
			$LongtermLastSeen->del ($nick);
		}
	}
	
	for ($LongtermCache->keys ())
	{
		my $key = $_;
		my ($nick, $day) = split (m/:/, $key);

		if (defined ($del->{$nick}) or ($day < $old))
		{
			$LongtermCache->del ($key);
			next;
		}

		my $idx = $day - $old;
		my $main = get_main_nick ($nick);
		my @data = $LongtermCache->get ($key);
		
		if (!defined ($LongtermData->{$main}))
		{
			$LongtermData->{$main} = [];
			$LongtermData->{$main}[$_] = [0, 0, 0, 0] for (0 .. ($DisplayDays - 1));
		}
		if (!defined ($LongtermData->{'<TOTAL>'}))
		{
			$LongtermData->{'<TOTAL>'} = [];
			$LongtermData->{'<TOTAL>'}[$_] = [0, 0, 0, 0] for (0 .. ($DisplayDays - 1));
		}

		$LongtermData->{$main}[$idx][$_] += $data[$_] for (0 .. 3);
		$LongtermData->{'<TOTAL>'}[$idx][$_] += $data[$_] for (0 .. 3);
	}
}

sub output
{
	calculate ();
	return (undef) unless (%$LongtermData);

	my $now_epoch = get_most_recent_time ();
	my $now = int ($now_epoch / 86400);
	return unless ($now);

	my $old = 1 + $now - $DisplayDays;

	my $data = $LongtermData->{'<TOTAL>'};

	my @weekdays = (qw(sun mon tue wed thu fri sat sun));

	my $fh = get_filehandle ();
	
	my $max = 0;
	my $total = 0;

	for (my $i = 0; $i < $DisplayDays; $i++)
	{
		for (my $j = 0; $j < 4; $j++)
		{
			$max = $data->[$i][$j] if ($max < $data->[$i][$j]);
			$total += $data->[$i][$j];
		}
	}
	
	print $fh qq#<table class="plugin longterm">\n  <tr class="bars">\n#;
	for (my $i = 0; $i < $DisplayDays; $i++)
	{
		for (my $j = 0; $j < 4; $j++)
		{
			my $num = $data->[$i][$j];
			my $height = sprintf ("%.2f", (95 * $num / $max));
			my $img = $VImages[$j];

			print $fh qq#    <td class="bar vertical">#,
			qq(<img src="$img" alt="" class="first last" style="height: ${height}%;" /></td>\n);
		}
	}
	print $fh qq(  </tr>\n  <tr class="counter">\n);
	for (my $i = 0; $i < $DisplayDays; $i++)
	{
		my $sum = $data->[$i][0] + $data->[$i][1] + $data->[$i][2] + $data->[$i][3];
		my $percent = sprintf ("%.1f", 100 * $sum / $total);

		print $fh qq(    <td colspan="4" class="counter">$percent%</td>\n);
	}
	print $fh qq(  </tr>\n  <tr class="numeration">\n);
	for (my $i = 0; $i < $DisplayDays; $i++)
	{
		my $epoch = ($old + $i) * 86400;
		my ($day, $wd) = (localtime ($epoch))[3,6];
		my $class = $weekdays[$wd];
		
		print $fh qq(    <td colspan="4" class="numeration $class">$day.</td>\n);
	}
	print $fh "  </tr>\n</table>\n\n";
}

=head1 EXPORTED FUNCTIONS

=over 4

=item B<get_longterm> (I<$nick>)

Returns the longterm-statistics for I<$nick>. The numbers are array-counters.
The format is as follows:

  [
    [0, 0, 0, 0], # oldest day
    ...,
    [0, 0, 0, 0], # yesterday
    [0, 0, 0, 0]  # today
  ]

=cut

sub get_longterm
{
	my $nick = shift;

	if (!defined ($LongtermData->{$nick}))
	{
		return ([]);
	}

	return ($LongtermData->{$nick});
}

=back

=head1 AUTHOR

Florian octo Forster E<lt>octo at verplant.orgE<gt>

=cut


syntax highlighted by Code2HTML, v. 0.9.1