package Yaala::Parser;

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

use Exporter;
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->{'start'})) { $EXTRA->{'start'} = 0; }
if (!defined ($EXTRA->{'end'}  )) { $EXTRA->{'end'}   = 0; }
if (!defined ($EXTRA->{'days'} )) { $EXTRA->{'days'}  = {}; }

%DATAFIELDS = (
	'date'		=> 'key:date',
	'hour'		=> 'key:hour',
	'client'	=> 'key:host',
	'server'	=> 'key:host',
	'peer'		=> 'key:host',
	'protocol'	=> 'key',
	'method'	=> 'key',
	'mime'		=> 'key',
	'httpstatus'	=> 'key:numeric',
	'resultcode'	=> 'key',
	'hierarchycode'	=> 'key',
	'ident'		=> 'key',
	'bytes'		=> 'agg:bytes',
	'elapsed'	=> 'agg:time',
	'requests'	=> '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: Squid.pm,v 1.11 2003/12/07 16:46:50 octo Exp $';
print STDERR $/, __FILE__, ": $VERSION" if ($::DEBUG);

return (1);

sub parse
{
	my $line = shift or return undef;
	#if ($line =~ m#^(\S+)\s+(\d+)\s(\S+)\s([^/]+)/(\d+)\s(\d+)\s(\S+)\s(\S+)\s(\S+)\s([^/]+)/(\S+)\s(.*)$#)
	if ($line =~ m#^(\S+)\s+(\d+) (\S+) ([^/]+)/(\d+) (\d+) (\S+) (\S+) (\S+) ([^/]+)/(\S+) (.*)$#)
	{
		my ($epoch, $duration, $client, $result_code, $http_code,
			$size, $method, $url, $ident, $hierarchy_code,
			$origin_host, $mime) = 
		($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);

		if ($epoch < $$LASTDATE)
		{
			print STDERR $/, __FILE__, ": Skipping.. ($epoch < $$LASTDATE)" if ($::DEBUG & 0x0200);
			return (undef);
		}
		else { $$LASTDATE = $epoch; }

		return undef if ($url eq '*');

		my $hour  = sprintf ("%02u", (localtime ($epoch))[2]);
		my $day   = sprintf ("%02u", (localtime ($epoch))[3]);
		my $month = sprintf ("%02u", (localtime ($epoch))[4] + 1);
		my $year  = sprintf ("%04u", (localtime ($epoch))[5] + 1900);

		my $date = sprintf ("%04u-%02u-%02u", $year, $month, $day);

		$EXTRA->{'total'}++;
		$EXTRA->{'days'}{$date}++;
		$EXTRA->{'start'} = $epoch if (($epoch < $EXTRA->{'start'}) or !$EXTRA->{'start'});
		$EXTRA->{'end'}   = $epoch if ($epoch > $EXTRA->{'end'});

		my ($protocol, $server, $path);
		if ($url =~ m#^([^:]+)://([^:/]+)(?::\d+)?(/[^\?]*)#)
		{
			($protocol, $server, $path) = ($1, $2, $3);
		}
		elsif ($url =~ /^([\w\d\-\.]+):443$/)
		{
			($protocol, $server, $path) = ('https', $1, '');
		}
		else
		{
			print STDERR $/, __FILE__, ": Unable to parse URL: ``$url''" if ($::DEBUG);
			return (0);
		}

		if ($ident eq '-') { $ident = '*UNKNOWN*'; }
		
		my %combined=(
			    'client'	    => $client,
			    'resultcode'    => uc ($result_code),
			    'httpstatus'    => $http_code,
			    'method'	    => $method,
			    'mime'	    => $mime,
			    'bytes'	    => $size,
			    'server'	    => $server,
			    'protocol'	    => uc ($protocol),
			    'hierarchycode' => uc ($hierarchy_code),
			    'ident'	    => uc ($ident),
			    'peer'	    => $origin_host,
			    'date'	    => $date,
			    'hour'	    => $hour,
			    'elapsed'	    => $duration,
			    'requests'	    => 1,
			    );
		store (\%combined);
	}
	elsif ($::DEBUG)
	{
		chomp ($line);
		print STDERR $/, __FILE__, ": Unable to parse: ``$line''";
	}
}

sub extra 
{
	my $start = scalar (localtime ($EXTRA->{'start'}));
	my $end   = scalar (localtime ($EXTRA->{'end'}));
	my $days  = scalar (keys (%{$EXTRA->{'days'}}));
	my $average = 0;
	if ($days) { $average = sprintf ("%.1f", ($EXTRA->{'total'} / $days)); }

	$::EXTRA->{'Total requests'} = $EXTRA->{'total'};
	$::EXTRA->{'Reporting period'} = "$days Days";
	$::EXTRA->{'Average requests per day'} = $average;
	$::EXTRA->{'Start date'} = $start;
	$::EXTRA->{'End date'} = $end;
}
