package Config::Model::Backend::Dpkg::Autopkgtest;

use strict;
use warnings;
use Mouse;

extends 'Config::Model::Backend::Any';

with 'Config::Model::Backend::DpkgSyntax';
with 'Config::Model::Backend::DpkgStoreRole';

use 5.20.1;

use feature qw/postderef signatures/;
no warnings qw/experimental::postderef experimental::signatures/;

use Carp;
use Config::Model::Exception;
use Log::Log4perl qw(get_logger :levels);
use IO::File;

my $logger = get_logger("Backend::Dpkg::Autopkgtest");

sub suffix { return ''; }

sub read {
    my $self = shift;
    my %args = @_;

    # args is:
    # object     => $obj,         # Config::Model::Node object
    # root       => './my_test',  # fake root directory, userd for tests
    # config_dir => /etc/foo',    # absolute path
    # file       => 'foo.conf',   # file name
    # file_path  => './my_test/etc/foo/foo.conf'
    # io_handle  => $io           # IO::File object
    # check      => yes|no|skip

    return 0 unless defined $args{io_handle} ;

    $logger->info("Parsing $args{file_path}");
    # load autopkgtest control file
    my $c = $self -> parse_dpkg_file ($args{file_path}, $args{io_handle}, $args{check}, 1 ) ;

    my $node = $args{object};
    my $check = $args{check};
    my $test_list = $node->fetch_element('control');
    my $test_nb = 0;

    while (@$c ) {
        my ($section_line,$section) = splice @$c,0,2 ;
        my $test_obj = $test_list->fetch_with_id($test_nb++);

        foreach ( my $i = 0 ; $i < $#$section ; $i += 2 ) {
            my $key = $section->[$i];
            my $v_ref = $section->[ $i + 1 ];
            if ( my $found = $test_obj->find_element( $key, case => 'any' ) ) {
                my $elt = $found ;
                my $to_store = $v_ref;

                my $elt_obj = $test_obj->fetch_element($elt);
                if ($test_obj->element_type($elt) eq 'list') {
                    $self->store_section_list_element ( $logger, $elt_obj, $check, $to_store);
                }
                else {
                    $self->store_section_leaf_element ( $logger, $elt_obj, $check, $to_store);
                }
            }
            else {
                warn "Unknown parameter found in $args{file_path}: $key";
            }
        }
    }

    return 1;
}

sub write {
    my $self = shift;
    my %args = @_;

    # args is:
    # object     => $obj,         # Config::Model::Node object
    # root       => './my_test',  # fake root directory, userd for tests
    # config_dir => /etc/foo',    # absolute path
    # file       => 'foo.conf',   # file name
    # file_path  => './my_test/etc/foo/foo.conf'
    # io_handle  => $io           # IO::File object

    croak "Undefined file handle to write" unless defined $args{io_handle} ;

    my $node = $args{object} ;
    my $ioh  = $args{io_handle} ;

    my @sections;

    my $test_list = $node->fetch_element('control');
    foreach my $test_nb ( $test_list -> fetch_all_indexes ) {
        push @sections, [ $self->node_to_section($test_list->fetch_with_id($test_nb)) ];
    }
    $self->write_dpkg_file($ioh, \@sections,", " ) ;

    return 1;
}

1;

__END__

=head1 NAME

Config::Model::Backend::Dpkg::Autopkgtest - Read and write Debian Dpkg Autopkgtest information

=head1 SYNOPSIS

No synopsis. This class is dedicated to configuration class C<Dpkg::Autopkgtest>

=head1 DESCRIPTION

This module is used directly by L<Config::Model> to read or write the
content of Debian C<Autopkgtest> file.

All C<Autopkgtest> files keyword are read in a case-insensitive manner.

=head1 CONSTRUCTOR

=head2 new ( node => $node_obj, name => 'Dpkg::Autopkgtest' ) ;

Inherited from L<Config::Model::Backend::Any>. The constructor will be
called by L<Config::Model::AutoRead>.

=head2 read ( io_handle => ... )

Of all parameters passed to this read call-back, only C<io_handle> is
used. This parameter must be L<IO::File> object already opened for
read. 

It can also be undef. In this case, C<read()> will return 0.

When a file is read,  C<read()> will return 1.

=head2 write ( io_handle => ... )

Of all parameters passed to this write call-back, only C<io_handle> is
used. This parameter must be L<IO::File> object already opened for
write. 

C<write()> will return 1.

=head1 AUTHOR

Dominique Dumont, (ddumont at cpan dot org)

=head1 SEE ALSO

L<Config::Model>, 
L<Config::Model::AutoRead>, 
L<Config::Model::Backend::Any>, 

=cut
