package tests::ConfigPluginTest;

use strict;

use Lire::Config::TypeSpec;
use Lire::Config::Plugin;

use IO::Scalar;

use tests::ConfigValuesTest;
use base qw/tests::ConfigValueTest/;

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

    $self->{'spec'} = new Lire::Config::ConfigSpec();
    $self->{'plugin_spec'} =
      new Lire::Config::PluginSpec( 'name' => 'plugin' );
    $self->{'spec'}->add( $self->{'plugin_spec'} );
    foreach my $name ( qw/option_1 option_2 option_3/ ) {
        my $opt = new Lire::Config::OptionSpec( 'name' => $name );
        $self->{'plugin_spec'}->add( $opt ) ;
    }
    my $option_1 = new Lire::Config::RecordSpec( 'name' => 'option_1_properties' );
    $option_1->add( new Lire::Config::StringSpec( 'name' => 'string1' ) );
    $self->{'spec'}->add( $option_1 );
    my $option_2 = new Lire::Config::RecordSpec( 'name' => 'option_2_properties' );
    $option_2->add( new Lire::Config::StringSpec( 'name' => 'string2' ) );
    $option_2->add( new Lire::Config::IntegerSpec( 'name' => 'int' ) );
    $self->{'spec'}->add( $option_2 );

    return $self;
}

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

    $self->{'cfg'}{'_lr_config_spec'} = $self->{'spec'};
    $self->{'plugin'} = new Lire::Config::Plugin( 'spec' => $self->{'plugin_spec'} );


    return;
}

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

    $self->SUPER::tear_down();

    return;
}

sub type {
    return "Lire::Config::Plugin";
}

sub spec {
    return $_[0]{'plugin_spec'};
}

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

    $self->SUPER::test_new();

    my $empty_dict = new Lire::Config::RecordSpec( 'name' => $self->{'plugin_spec'}->name() . "_no_properties" );
    $self->assert_null( $self->{'plugin'}{'_plugin'},
                        '_plugin non-null' );
    $self->assert_deep_equals( $empty_dict->instance(),
                               $self->{'plugin'}->{'_properties'} );

    my $plugin = $self->{'plugin_spec'}->instance( 'value' => 'option_1' );
    $self->assert_str_equals( 'option_1', $plugin->{'_plugin'} );
    $self->assert_deep_equals( $plugin, $plugin->new() );

    my $other = $plugin->new( 'value' => 'option_2' );
    $self->assert_str_equals( 'option_2', $other->{'_plugin'} );
}

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

    $self->{'plugin'}->set_plugin( 'option_1' );
    $self->assert_str_equals( 'option_1', $self->{'plugin'}{'_plugin'} );
    my $option_1_props = $self->{'spec'}->get( 'option_1_properties' );
    $self->assert_deep_equals( $option_1_props->instance(),
                               $self->{'plugin'}{'_properties'} );

    my $old_props = $self->{'plugin'}{'_properties'};
    $self->{'plugin'}->set_plugin( 'option_1' );
    $self->assert_str_equals( $old_props, $self->{'plugin'}{'_properties'} );

    $self->{'plugin'}->set_plugin( 'option_2' );
    $self->assert_str_equals( 'option_2', $self->{'plugin'}{'_plugin'} );
    my $option_2_props = $self->{'spec'}->get( 'option_2_properties' );
    $self->assert_deep_equals( $option_2_props->instance(),
                               $self->{'plugin'}{'_properties'} );

    $self->{'plugin'}->set_plugin( 'option_3' );
    $self->assert_str_equals( 'option_3', $self->{'plugin'}{'_plugin'} );
    $self->assert_deep_equals( $self->{'plugin'}->spec()->get_properties_spec( undef )->instance(),
                               $self->{'plugin'}{'_properties'} );
}

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

    local $SIG{'__WARN__'} = sub { $self->annotate( join "", $@ ) };
    my $plugin = $self->{'plugin'};
    $self->assert_deep_equals( { 'plugin' => undef,
                                 'properties' => {},
                               },
                               $plugin->as_value(),
                             );

    $plugin->set_plugin( 'option_1' );
    $self->assert_deep_equals( { 'plugin' => 'option_1',
                                 'properties' => { 'string1' => '' },
                               },
                               $plugin->as_value(),
                             );
}

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

    $self->{'plugin'}->set_plugin( 'option_1' );

    $self->check_save_xml_default( $self->{'plugin'}->clone() );
    $self->check_save_xml_obsolete( $self->{'plugin'}->clone() );

    $self->{'plugin'}->get( 'string1' )->set( 'test' );
    my $fh = new IO::Scalar();
    $self->{'plugin'}->save_xml( $fh, 0 );
    my $buf = $fh->sref();
    $self->assert_equals( <<EOXML, $$buf );
<param name="plugin" value="option_1">
  <param name="string1">test</param>
</param>
EOXML

    $self->{'plugin'}->set_plugin( 'option_3' );
    $$buf = '';
    $self->{'plugin'}->save_xml( $fh, 1 );
    $self->assert_equals( <<EOXML, $$buf );
  <param name="plugin" value="option_3">
  </param>
EOXML
    $self->{'plugin'}{'_plugin'} = undef;
    $fh = new IO::Scalar();
    $self->{'plugin'}->save_xml( $fh, 1 );
    $buf = $fh->sref();
    $self->assert_str_equals( '', $$buf );
}

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

    my $plugin = $self->{'plugin'};
    $plugin->set_plugin( 'option_1' );
    $self->assert( $plugin->has_properties(),
                   'option_1 *does not* have properties!' );
    $plugin->set_plugin( 'option_3' );
    $self->assert( ! $plugin->has_properties(),
                   'option_3 *has* properties!' );
    $plugin->set_plugin( 'option_2' );
    $self->assert( $plugin->has_properties(),
                   'option_2 *does not* have properties!' );
}

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

    $self->SUPER::test_is_equals();

    my $plugin = $self->{'plugin'};
    my $option = $self->{'spec'}->get( 'option_2_properties' )->get( 'string2' )->instance( 'value' => 'A string' );
    my $other = $plugin->clone();
    $plugin->set_plugin( 'option_2' );
    $plugin->set( $option );

    $self->assert( ! $plugin->is_equals( $other ), '! is_equals()' );
    $other->set_plugin( 'option_2' );
    $self->assert( ! $plugin->is_equals( $other ), '! is_equals()' );
    $other->set( $option->clone() );
    $self->assert( $plugin->is_equals( $other ), 'is_equals()' );
}

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

    my $plugin = $self->{'plugin'};
    $self->assert( !$plugin->is_valid(), '!is_valid()' );

    $plugin->set_plugin( 'option_3' );
    $self->assert( $plugin->is_valid(), 'is_valid()' );

    $plugin->set_plugin( 'option_2' );
    $self->assert( !$plugin->is_valid(), '!is_valid()' );
    $plugin->get( 'int' )->set( 10 );
    $self->assert( $plugin->is_valid(), 'is_valid()' );
}

1;


syntax highlighted by Code2HTML, v. 0.9.1