package Lire::ReportSection;

use strict;

use Carp;

use Lire::Report::Section;
use Lire::DlfSchema;
use Lire::Utils qw/check_object_param check_param/;
use Lire::I18N qw/dgettext/;

use Locale::TextDomain 'lire';

=pod

=head1 NAME

Lire::ReportSection - API to report configuration's section

=head1 SYNOPSIS

    use Lire::ReportConfig;
    use Lire::ReportSection;

    my $report_cfg = new Lire::ReportConfig( "www" );
    my $section = new Lire::ReportSection( "www", "General" );
    $report_cfg->add_section( $section );

=head1 DESCRIPTION

This class offers an object oriented API to report configuration's
section. It offers methods to access and modify the section's
attribute.

=head1 CONSTRUCTOR

=head2 new( $superservice, [$title] )

Creates a new Lire::Section object which will contains report
specifications of the $superservice superservice. The section's title
will be set to the value of $title.

=cut

sub new {
    my ( $class, $super, $title ) = @_;

    check_param( $super, 'superservice', 
                 sub { Lire::DlfSchema->has_superservice( $_[0] ) },
                 'invalid superservice' );

    return bless { '_superservice'    => $super,
                   '_filters'         => [],
                   '_title'           => $title || "Section",
                   '_reports'         => [],
                 }, $class;
}

=pod

=head1 OBJECT METHODS

=head2 superservice()

Returns this section's superservice.

=cut

sub superservice {
    my ( $self ) = @_;

    return $self->{'_superservice'};
}

=pod

=head2 title([$title])

Return's the current section's title.

When the $title parameter is used, it will set the section's title to
a new value.

=cut

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

    if ( defined $title ) {
        $self->{'_title'} = $title;
    }

    return dgettext( "lire-$self->{'_superservice'}", $self->{'_title'} );
}

=pod 

=head2 filters()

Returns this section's filter specifications as an array of
Lire::FilterSpec objects. Those filter specifications will be used by
all of this section's report specifications in addition to the filter
specification they may already be using.


=cut

sub filters {
    my ( $self ) = @_;

    return @{ $self->{'_filters'} };
}

=pod 

=head2 add_filter($filter_spec)

Adds the $filter_spec filter specification to this section's list. The
$filter_spec parameter must be an instance of Lire::FilterSpec or one
of its descendants.

This method will die if the filter specification's schema isn't
compatible with this section's superservice.

=cut

sub add_filter {
    my ( $self, $filter_spec ) = @_;

    check_object_param( $filter_spec, 'filter_spec', 'Lire::FilterSpec' );

    # Make sure all the report's schema are compatible
    # with with this filter
    my $schema = $filter_spec->schema()->id();
    foreach my $r ( $self->reports() ) {
        croak "filter ", $filter_spec->id(), "'s schema is incompatible ",
          "with report ", $r->id(), "\n"
            unless $r->schema()->is_schema_compatible( $schema );
    }
    push @{$self->{'_filters'}},$filter_spec;

    return;
}

=pod 

=head2 reports()

Returns this section's report specifications as an array of
Lire::ReportSpec objects.

=cut

sub reports {
    my ( $self ) = @_;

    return @{ $self->{'_reports'} };
}

=pod 

=head2 add_report( $report_spec )

Adds the $report_spec report specification to this section. This
method will die if the report specification's schema isn't compatible
with this section's superservice.

=cut

sub add_report {
    my ( $self, $report ) = @_;

    check_object_param( $report, 'report', 'Lire::ReportSpec' );

    croak "can't add a ReportSpec without a subreport_id"
      unless $report->subreport_id();

    croak ( "report is of wrong superservice: ", $report->superservice() ,
            " != ", $self->superservice() )
      if $self->superservice() ne $report->superservice();

    # Make sure the report's schema is compatible
    # with all the filters' schema
    my $schema = $report->schema();
    foreach my $f ( $self->filters() ) {
        croak "report ", $report->id(), "'s schema is incompatible with filter ",
          $f->id(), "\n"
            unless $schema->is_schema_compatible( $f->schema()->id() );
    }
    push @{$self->{'_reports'}},$report;

    return;
}

# create_report_section
# called by Lire::ReportConfig::create_report()

sub create_report_section {
    my ( $self, $report ) = @_;

    check_object_param( $report, 'report', 'Lire::Report' );

    my $section = new Lire::Report::Section( $self->title() );
    $report->add_section( $section );

    if ( $self->filters() ) {
        my @filters = map { $_->expanded_display_title() } $self->filters();
        my $desc = "<para>" . __n( "Applied filter in this section: ",
                                   "Filters applied in this section:",
                                   scalar @filters );
        $desc .= "\n" if @filters > 1;
        if ( @filters == 1 ) {
            $desc .= $filters[0];
        } else {
            $desc .= " <itemizedlist spacing=\"compact\">\n";
            foreach my $filter ( @filters ) {
                $desc .= " <listitem>\n  <para>$filter</para>\n </listitem>\n";
            }
            $desc .= " </itemizedlist>\n";
        }
        $desc .= "</para>\n";
        $section->description( $desc );
    }

    foreach my $spec ( $self->reports() ) {
        my $subreport = $spec->create_subreport();
        $section->add_subreport( $subreport );
    }

    return $section;
}

# Factory method for the Configuration API.
sub new_from_config {
    my ( $self, $value ) = @_;

    my $def = $value->Lire::Config::Dictionary::as_value();
    my $section = new Lire::ReportSection( $def->{'superservice'},
                                           $def->{'title'} );
    foreach my $filter ( @{$def->{'filters'}} ) {
        $section->add_filter( $filter );
    }

    foreach my $spec ( @{$def->{'specs'}} ) {
        $section->add_report( $spec );
    }

    return $section;
}

# keep perl happy
1;

__END__

=pod

=head1 SEE ALSO

 Lire::ReportConfig(3pm), Lire::ReportSpec(3pm), Lire::FilterSpec(3pm)
 Lire::Report::Section(3pm), Lire::Config::ReportSectionSpec(3pm)

=head1 AUTHOR

  Francis J. Lacoste <flacoste@logreport.org>

=head1 VERSION

$Id: ReportSection.pm,v 1.25 2006/07/23 13:16:29 vanbaal Exp $

=head1 COPYRIGHT

Copyright (C) 2002, 2004 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. 

=cut
