package tests::ReportScheduleTest;

use strict;

use base qw/ Lire::Test::TestCase tests::TestStoreFixture /;

use Lire::ReportSchedule;
use Lire::ReportConfig;
use Lire::ReportSection;
use Lire::ReportSpec;
use Lire::FilterExpr;
use Lire::Test::Mock;
use Lire::Config::Index;
use Lire::PluginManager;
use Lire::OutputFormat;
use Time::Local;

#our @TESTS = qw//;

sub new {
    my $self = shift()->SUPER::new( @_ );

    $self->init();

    $self->{'spec'} = $self->lire_default_config_spec();

    return $self;
}

sub set_up {
    my $self = $_[0];
    $self->SUPER::set_up();

    $self->set_up_test_schema();
    $self->set_up_test_store();
    $self->set_up_plugin_mgr();
    $self->{'cfg'}{'_lr_config_spec'} = $self->{'spec'};
    $self->{'cfg'}{'lr_week_numbering'} = 'U';
    $self->{'cfg'}{'lr_reports_path'} = [ "$self->{'testdir'}/reports" ];
    $self->{'cfg'}{'lr_filters_path'} = [ "$self->{'testdir'}/filters" ];

    $self->{'test_cfg'} = new Lire::ReportConfig();
    $self->{'_old_index_ref'} = \%Lire::Config::Index::REGISTRY;
    my $index = new Lire::Test::Mock( 'Lire::Config::Index',
                                      'has_entry' => 1,
                                      'get_ref' => $self->{'test_cfg'},
                                    );
    Lire::Config::Index->set_index( 'store_report_configurations', $index );

    my $txt = new_proxy Lire::Test::Mock( 'Lire::OutputFormat' );
    $txt->set_result( 'name' => 'txt' );

    Lire::PluginManager->register_plugin( $txt );
    return;
}

sub tear_down {
    my $self = $_[0];
    $self->SUPER::tear_down();

    *Lire::Config::Index::REGISTRY = $self->{'_old_index_ref'};
    $self->tear_down_test_store();

    return;
}

sub test_new {
    my $self = $_[0];

    my $sched = new Lire::ReportSchedule( "daily", $self->{'test_cfg'} );
    $self->assert_isa( 'Lire::ReportSchedule', $sched );

    $self->assert_str_equals( 'daily', $sched->{'_period'} );
    $self->assert_str_equals( 'daily', $sched->period() );
    $self->assert_str_equals( $self->{'test_cfg'}, $sched->{'_cfg'} );
    $self->assert_deep_equals( [], $sched->{'_output_jobs'} );
    $self->assert_deep_equals( [], [ $sched->output_jobs() ] );
    $self->assert_dies( qr/'period' parameter should be one of 'hourly', 'daily', 'weekly', 'monthly' or 'yearly': /,
                        sub { new Lire::ReportSchedule( 'aTest', $self->{'test_cfg'} ) } );
}

sub test_add_output_job {
    my $self = $_[0];

    my $sched = new Lire::ReportSchedule( "daily", $self->{'test_cfg'} );
    my $job = bless {}, 'Lire::OutputJob';

    $self->assert_dies( qr/missing one or more 'output_job' parameters/,
                        sub { $sched->add_output_job() } );
    $sched->add_output_job( $job, $job );
    $self->assert_deep_equals( [ $job, $job ],
                               $sched->{'_output_jobs'} );
}

sub test_new_from_config {
    my $self = $_[0];

    my $job = $self->{'spec'}->get( 'report_jobs' )->get( 'report_job' )->get( 'schedules' )->get( 'schedule' )->instance();
    $job->get( 'period' )->set( 'daily' );
    $job->get( 'report_config' )->set( 'test.cfg' );
    my $output = $job->get( 'output_jobs' )->spec()->get( 'output_job' )->instance();
    $output->get( 'destination' )->set_plugin( 'file' );
    $output->get( 'destination' )->get( 'file' )->set( 'report.txt' );
    $output->get( 'format' )->set_plugin( 'txt' );
    $job->get( 'output_jobs' )->append( $output );

    my $jobObject = $job->as_value();
    $self->assert_isa( 'Lire::ReportSchedule', $jobObject );
    $self->assert_str_equals( 'daily', $jobObject->{'_period'} );
    $self->assert_str_equals( "$self->{'test_cfg'}", $jobObject->{'_cfg'} );
    $self->assert_num_equals( 1, scalar @{$jobObject->{'_output_jobs'}} );
}

sub set_up_test_cfg {
    my $self = $_[0];

    my $section = new Lire::ReportSection( 'test', 'First Section' );
    my $spec = Lire::ReportSpec->load( 'test', 'top-files' );
    $spec->subreport_id( 'top-files.0' );
    $section->add_report( $spec );
    $spec = Lire::ReportSpec->load( 'test', 'sessions-by-user_class' );
    $spec->subreport_id( 'sessions-by-user_class.0' );
    $section->add_report( $spec );
    $self->{'test_cfg'}->add_section( $section );

    $section = new Lire::ReportSection( 'test', 'Movies Section' );
    $spec = Lire::ReportSpec->load( 'test', 'top-files' );
    $spec->subreport_id( 'top-files.1' );
    $spec->filter_spec( new Lire::FilterExpr::Match( 'container' => $spec,
                                                     'value' => '$file',
                                                     're' => '\.mpg$' )
                      );
    $section->add_report( $spec );
    $self->{'test_cfg'}->add_section( $section );

    return;
}

sub test_init_report_config {
    my $self = $_[0];

    $self->set_up_test_cfg();
    my $sched = new Lire::ReportSchedule( 'daily', $self->{'test_cfg'} );

    my $mar11_2004 = timelocal( 0, 0, 0, 11, 2, 2004 );
    my $cfg = $sched->init_report_config( $mar11_2004 );
    $self->assert_isa( 'Lire::ReportConfig', $cfg );

    $self->check_filter_expr( (($cfg->sections())[0]->reports())[0],
                              '$time_start', $mar11_2004  );
    $self->check_filter_expr( (($cfg->sections())[0]->reports())[1],
                              '$session_start', $mar11_2004 );
    $self->check_filter_expr( (($cfg->sections())[1]->reports())[0],
                              '$time_start', $mar11_2004,
                              'Lire::FilterExpr::Match' );
}

sub check_filter_expr {
    my ($self, $spec, $field, $time, $extra ) = @_;

    $self->annotate( "checking ", $spec->subreport_id(), "..." );
    my $expr = $spec->filter_spec();
    $self->assert_isa( 'Lire::FilterExpr::And', $expr );

    my ($start, $end, $other ) = @{ $expr->expr() };
    $self->assert_isa( 'Lire::FilterExpr::Ge', $start );
    $self->assert_str_equals( $field, $start->arg1() );
    $self->assert_num_equals( $time, $start->arg2() );

    $self->assert_isa( 'Lire::FilterExpr::Lt', $end );
    $self->assert_str_equals( $field, $end->arg1() );
    $self->assert_num_equals( $time + 86400, $end->arg2() );

    $self->assert_isa( $extra, $other ) if $extra;

    $self->annotate( "ok\n" );

    return;
}

1;


syntax highlighted by Code2HTML, v. 0.9.1