package Lire::AsciiDlf::Timeslot;

use strict;

use vars qw/ $VERSION @ISA %DAYS %MONTHS $WEEK_FMT
	     @SLOT_UNIT @MAX_SLOTS @SLOT_INDEX @SLOT_FMT /;

use Lire::Config;
use Lire::Timeslot;
use Lire::AsciiDlf::NestableAggregator;
use Lire::DataTypes qw/ :time /;
use Lire::Report::Entry;

use POSIX qw/ strftime /;
use Time::Local;

use Carp;

BEGIN {
    ($VERSION)	= '$Revision: 1.10 $' =~ m!Revision: ([.\d]+)!;
    @ISA = qw/ Lire::Timeslot  Lire::AsciiDlf::NestableAggregator /;

    # We don't want to use the strftime because of possible
    # locale charsets problems
    my $i = 0;
    %MONTHS = map { $i++ => $_ } qw/ January February March
				     April   May      June
				     July    August   September
				     October November December /;

    $i = 0;
    %DAYS = map { $i++ => $_ } qw/  Sunday   Monday Tuesday  Wednesday
				    Thursday Friday Saturday /;

    if ($Lire::Config::LR_WEEK_STARTS_ON eq 'mon') {
	$WEEK_FMT = '%W';
    } else {
	$WEEK_FMT = '%U';
    }

    @SLOT_UNIT  = qw/1M 1w 1d 1h 1m 1s/;
    @MAX_SLOTS  = qw/12 53 7  24 60 60/;
    @SLOT_INDEX = qw/4  wk 6  2  1  0/;
    @SLOT_FMT	= qw/mo wk dw %H:00 00:%M 00:00:%S/;
}

sub init_report {
    my ($self,$dlf_info) = @_;

    $self->{field_idx} =
      $self->{report_spec}->schema->field( $self->field )->pos();

    my $unit = $self->unit;
    if ( $unit =~ /^\$/ ) {
	$unit = substr $unit, 1;
	$unit = $self->{report_spec}->param( $unit )->value;
    }
    my $unit_sec = duration2sec( $unit );

    # Determine if we have a valid duration value for a timeslot
    my $unit_ok = 0;
    for (my $i=0; $i < @SLOT_UNIT; $i++ ) {
	my $sec = duration2sec( $SLOT_UNIT[$i] );
	if ( $unit_sec >= $sec && !( $unit_sec % $sec ) ) {
	    croak "$unit is a too big muliple of $SLOT_UNIT[$i]. ",
	      "Max is $MAX_SLOTS[$i]"
		if $unit_sec > $MAX_SLOTS[$i] * $sec;

	    $self->{slot_index} = $SLOT_INDEX[$i];
	    $self->{time_fmt}	= $SLOT_FMT[$i];
	    $self->{multiplier} = $unit_sec / $sec;

	    croak "$unit isn't a valid divisor of $MAX_SLOTS[$i]"
	      if $MAX_SLOTS[$i] % $self->{multiplier};

	    $unit_ok = 1;
	    last;
	}
    }
    croak "invalid timeslot value: must be an even multiple of 1M, 1wk, 1d, 1h, 1m or 1s"
      unless $unit_ok;

    $self->SUPER::init_report( $dlf_info );

    $self;
}

sub init_group_data {
    return [];
}

sub update_group_data {
    my ( $self, $dlf, $timeslots ) = @_;

    my $time = $dlf->[$self->{field_idx}];

    my $idx;
    if ( $self->{slot_index} eq 'wk' ) {
	$idx = strftime( $WEEK_FMT, localtime( $time ) );
	$idx--;
	$idx = 52 if $idx < 0;
    } else {
	$idx = (localtime $time)[$self->{slot_index}];
    }
    $idx = int($idx / $self->{multiplier});

    croak( "fatal error: negative index for $time, $self->{slot_index}, $self->{multiplier}" )
      if $idx < 0;

    my $data = $timeslots->[$idx];
    unless ( defined $data ) {
	$data = [];

	my $i = 0;
	foreach my $op ( @{$self->ops} ) {
	    $data->[$i++] = $op->init_group_data();
	}

	$timeslots->[$idx] = $data;
    }


    my $i = 0;
    foreach my $op ( @{$self->ops} ) {
	$op->update_group_data( $dlf, $data->[$i++] );
    }

    $self;
}

sub end_group_data {
    my ( $self, $timeslots ) = @_;

    # Finalize each timeslice
    # Either create empty one or call end_group_data on them
    my $last_idx;
    if ( $self->{slot_index} eq 'wk' ) {
	$last_idx  = 52;
    } else {
	$last_idx  = ( 59, 59, 23, 0, 11, 0, 6 )[$self->{slot_index}];
    }
    $last_idx = int($last_idx / $self->{multiplier});

    my $i = 0;
    while ( $i <= $last_idx) {
	if ( $timeslots->[$i]) {
	    my $data = $timeslots->[$i];
	    my $j = 0;
	    foreach my $op ( @{$self->ops} ) {
		$op->end_group_data( $data->[$j++] );
	    }
	} else {
	    # Create empty set
	    my $data =[];
	    my $j = 0;
	    foreach my $op ( @{$self->ops} ) {
		$data->[$j] = $op->init_group_data();
		$op->end_group_data( $data->[$j++] );
	    }

	    $timeslots->[$i] = $data;
	}
	$i++;
    }

    $self;
}

sub create_entries {
    my ( $self, $group, $timeslots ) = @_;

    $timeslots ||= $self->{data};

    for ( my $i=0; $i < @$timeslots; $i++ ) {
	my $tslice = $timeslots->[$i];
	my $entry = new Lire::Report::Entry;

	# FIXME: Special backward-compatibility hack.
	# This should be done in the stylesheet.
	if ( $self->{time_fmt} eq 'mo' ) {
	    $entry->add_name( $MONTHS{$i}, "M$i", $self->{multiplier} );
	} elsif ( $self->{time_fmt} eq 'dw' ) {
	    $entry->add_name( $DAYS{$i}, "D$i", $self->{multiplier} );
	} elsif ( $self->{time_fmt} eq 'wk' ) {
	    my $wk = sprintf( '%02d', $i + 1);
	    $entry->add_name( "Week $wk", "W$i", $self->{multiplier} );
	} else {
	    my $fmt = $self->{time_fmt};
	    my @time = localtime;
	    for (my $u=0; $u < $self->{slot_index}; $u++ ) {
		$time[$u] = 0;
	    }
	    $time[$self->{slot_index}] = $i * $self->{multiplier};
	    $entry->add_name( strftime( $fmt, @time ), 
			      "$self->{slot_index}-$i", $self->{multiplier} ); 
	}

	my $j = 0;
	foreach my $op ( @{$self->ops} ) {
	    $op->add_entry_value( $entry, $tslice->[$j++] );
	}

	$group->add_entry( $entry );
    }

    $self;
}


# keep perl happy
1;

__END__

=pod

=head1 NAME

Lire::AsciiDlf::Timeslot -

=head1 SYNOPSIS


=head1 DESCRIPTION

=head1 VERSION

$Id: Timeslot.pm,v 1.10 2002/06/18 14:38:01 flacoste Exp $

=head1 COPYRIGHT

Copyright (C) 2001 Stichting LogReport Foundation LogReport@LogReport.org


This file is part of Lire.

Lire is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program (see COPYING); if not, check with
http://www.gnu.org/copyleft/gpl.html or write to the Free Software 
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.

=head1 AUTHOR

Francis J. Lacoste <flacoste@logreport.org>

=cut
