package Yaala::Parser;

use strict;
use warnings;
use vars qw(%DATAFIELDS);

use Exporter;
use Yaala::Parser::WebserverTools qw(%MONTH_NUMBERS);
use Yaala::Data::Persistent qw#init#;
use Yaala::Config qw#get_config#;

@Yaala::Parser::EXPORT_OK = qw(parse extra %DATAFIELDS);
@Yaala::Parser::ISA = ('Exporter');

our $LASTDATE = init ('$LASTDATE', 'scalar');
our $EXTRA = init ('$EXTRA', 'hash');

if (!$$LASTDATE) { $$LASTDATE = 0; }
if (!defined ($EXTRA->{'total'})) { $EXTRA->{'total'} = 0; }
if (!defined ($EXTRA->{'days'} )) { $EXTRA->{'days'}  = {}; }

%DATAFIELDS = (
	host		=> 'key:host',
	user		=> 'key',
	access_mode	=> 'key',
	
	date		=> 'key:date',
	hour		=> 'key:hour',
	
	file		=> 'key',
	completion_status => 'key',
	direction	=> 'key',
	transfer_type	=> 'key',
	transfer_time	=> 'key:numeric',
	special_action	=> 'key',

	bytes		=> 'agg:bytes',
	count		=> 'agg'
);

# This needs to be done at runtime, since Data uses Setup which relies on
# %DATAFIELDS to be defined  -octo
require Yaala::Data::Core;
import Yaala::Data::Core qw#store#;

my $VERSION = '$Id: Xferlog.pm,v 1.4 2003/12/07 16:49:56 octo Exp $';
print STDERR $/, __FILE__, ": $VERSION" if ($::DEBUG);

return (1);

sub parse
{
	my $line = shift;
	my @fields = split(m/\s+/, $line);
	my ($hour, $minute, $second) = split (m/:/, $fields[3]);

	if (scalar (@fields) != 18)
	{
		print STDERR $/, __FILE__, ': There were ',
		scalar (@fields), ' when 18 where expected..'
		if ($::DEBUG);
	}

	{
		my $tmp = int (sprintf ("%04u%02u%02u%02u%02u%02u",
				$fields[4], $MONTH_NUMBERS{$fields[1]}, $fields[2],
				$hour, $minute, $second));

		if ($tmp < $$LASTDATE)
		{
			print STDERR $/, __FILE__, ": Skipping.. ($tmp < $$LASTDATE)" if ($::DEBUG & 0x0200);
			return (undef);
		}
		else { $$LASTDATE = $tmp; }
	}
	
	my $date = sprintf ("%04u-%02u-%02u", $fields[4], $MONTH_NUMBERS{$fields[1]}, $fields[2]);

	my $file = $fields[8];
	my $bytes = $fields[7];
	
	my $transfer_time = $fields[5];

	my $host = $fields[6];
	my $user = $fields[13];

	my $transfer_type = ($fields[9] eq 'a' ? 'ascii' : 'binary');
	my $completion_status = ($fields[17] eq 'c' ? 'complete' : 'incomplete');
	
	my $special_action;
	if ($fields[10] eq '_')
	{
		$special_action = "none";
	}
	elsif ($fields[10] eq 'C')
	{
		$special_action = 'compressed';
	}
	elsif ($fields[10] eq 'U')
	{
		$special_action = 'uncompressed';
	}
	elsif ($fields[10] eq 'T')
	{
		$special_action = "tar'ed";
	}
	else
	{
		print STDERR $/, __FILE__, ': Unknown special_action: ',
		$fields[10] if ($::DEBUG);
		return (0);
	}
	
	my $direction;
	if ($fields[11] eq 'i')
	{
		$direction = 'incoming';
	}
	elsif ($fields[11] eq 'o')
	{
		$direction = 'outgoing';
	}
	elsif ($fields[11] eq 'd')
	{
		$direction = 'deleted';
	}
	else
	{
		print STDERR $/, __FILE__, ': Unknown direction: ',
		$fields[11] if ($::DEBUG);
		return (0);
	}
	
	my $access_mode;
	if ($fields[12] eq 'a')
	{
		$access_mode = 'anonymous';
	}
	elsif ($fields[12] eq 'g')
	{
		$access_mode = 'guest';
	}
	elsif ($fields[12] eq 'r')
	{
		$access_mode = 'real';
	}
	else
	{
		print STDERR $/, __FILE__, ': Unknown access-method: ',
		$fields[12] if ($::DEBUG);
		return (0);
	}
	
	$EXTRA->{'total'}++;
	$EXTRA->{'days'}{$date}++;
	
	# 14: service-name
	# 15: authentication-method
	# 16: authentication-user-id

	my %data_set = (
		host		=> $host,
		user		=> $user,
		access_mode	=> $access_mode,
	
		date		=> $date,
		hour		=> $hour,
	
		file		=> $file,
		completion_status => $completion_status,
		direction	=> $direction,
		transfer_type	=> $transfer_type,
		transfer_time	=> $transfer_time,
		special_action	=> $special_action,

		bytes		=> $bytes,
		count		=> 1
	);
	store (\%data_set);
}

sub extra
{
	$::EXTRA->{'Requests Total'} = $EXTRA->{'total'};
	
	my $days = scalar (keys (%{$EXTRA->{'days'}}));

	$::EXTRA->{'Reporting period'} = "$days days";

	$::EXTRA->{'Average requests per day'} = sprintf ("%.1f", $EXTRA->{'total'} / $days);
}
