package tests::UIPluginWidgetTest;

use strict;

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

use Lire::Config::TypeSpec;
use Lire::Test::CursesUIDriver;
use Lire::UI;
use Lire::Test::Mock;
use Curses::UI;

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

    $self->SUPER::set_up();
    $self->set_up_spec();
    $self->set_up_config();

    $self->{'driver'} = new Lire::Test::CursesUIDriver();
    $self->{'driver'}->setup_curses_ui();

    $self->{'ui'} = new Curses::UI();
    $self->{'driver'}->set_curses_ui( $self->{'ui'} );

    $self->{'window'} = $self->{'ui'}->add( 'window', 'Window' );

    return;
}

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

    my $spec = new Lire::Config::ConfigSpec( 'name' => 'lire' );
    my $plugin_spec = new Lire::Config::PluginSpec( 'name' => 'plugin',
                                                    'class' => 'Wawa::Class' );
    $spec->add( $plugin_spec );
    foreach my $name ( qw/one two wawa/ ) {
        $plugin_spec->add( new Lire::Config::OptionSpec( 'name' => $name ) );
    }

    my $wawa_props =
      new Lire::Config::RecordSpec( 'name' => 'wawa_properties' );
    $spec->add( $wawa_props );
    $wawa_props->add( new Lire::Config::StringSpec( 'name' => 'dummy' ) );

    my $empty_plugin = new Lire::Config::PluginSpec('name' => 'empty_plugin',
                                                    'class' => 'Empty::Class');
    $spec->add( $empty_plugin );

    $self->{'spec'} = $spec;

    return;
}

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

    my $spec = $self->{'spec'};
    my $config = Lire::Config->instance();
    $self->{'config'} = $config;
    $config->{'_lr_config_spec'} = $spec;

    my $plugin = $spec->get( 'plugin' )->instance( 'value' => 'wawa');
    $config->{'plugin'} = $self->{'plugin'} = $plugin;

    my $wawa_props = $plugin->get_properties();
    $wawa_props->get( 'dummy' )->set( 'wawa string' );

    $config->{'empty_plugin'} = $spec->get( 'empty_plugin' )->instance();
    $self->{'empty_plugin'} = $config->{'empty_plugin'};

    return;
}

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

    $self->SUPER::tear_down();
    $self->{'driver'}->teardown_curses_ui();

    return;
}

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

    my $win = $self->{'window'};
    $self->assert_dies( qr/missing \'value\' parameter/,
                        sub { my $widget = $win->add('test_widget',
                                                     'Lire::UI::PluginWidget')} );
    $self->assert_dies( qr/\'value\' parameter should be a \'Lire::Config::Plugin\' instance, not \'HASH/,
                        sub { my $widget = $win->add( 'test_widget',
                                                      'Lire::UI::PluginWidget',
                                                      'Value' => {} ) } );

    $self->assert_isa( 'Lire::Config::Plugin', $self->{'plugin'} );

    my $widget = $win->add( 'testwidget', 'Lire::UI::PluginWidget',
                            'value' => $self->{'plugin'} );
    $self->assert_isa( 'Lire::UI::PluginWidget', $widget );
    $self->assert_isa( 'Curses::UI::Container', $widget );

    $self->assert_num_equals( 1, $widget->{'-releasefocus'} );

    my $list = $widget->getobj( 'list' );
    $self->assert_num_equals( 2, $list->{'-selected'} );

    $list->{'-selected'} = 1;
    $self->assert_isa( 'Curses::UI::Popupmenu', $list );
    $self->assert_str_equals( 'two', $list->get() );
    $self->assert_deep_equals( [ 'one', 'two', 'wawa' ],
                               $list->{'-values'} );
    $self->assert_num_equals( 1, $list->{'-selected'} );

    my $button = $widget->getobj( 'button' );
    $self->assert_isa( 'Curses::UI::Buttonbox', $button );
    $self->assert_str_equals( '<...>', $button->{'-buttons'}[0]{'-label'} ) ;
    $self->assert( defined $widget->getobj( 'button' ) );

    $widget = $win->add( 'empty_widget', 'Lire::UI::PluginWidget',
                         'value' => $self->{'empty_plugin'} );
    $list = $widget->getobj( 'list' );
    $self->assert_deep_equals( [ '-- empty list --' ], $list->{'-values'});
    $self->assert_num_equals( 0, $list->{'-selected'} );
    $self->assert_num_equals( 0, $list->{'-focusable'} );
    $self->assert_null( $widget->getobj( 'button' ) );

    $self->{'plugin'}->set_plugin( undef );
    $widget = $win->add( 'undefplugin', 'Lire::UI::PluginWidget',
                         'value' => $self->{'plugin'} );
    $list = $widget->getobj( 'list' );
    $self->assert_null( $list->{'-selected'} );
    $self->assert_null( $widget->getobj( 'button' ) );

    $self->{'plugin'}->set_plugin( 'one' );
    $widget = $win->add( 'nopropplugin', 'Lire::UI::PluginWidget',
                         'value' => $self->{'plugin'} );
    $self->assert_null( $widget->getobj( 'button' ) );

    return;
}

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

    my $called = 'onvaluechanged not called';
    my $widget = $self->{'window'}->add( 'widget', 'Lire::UI::PluginWidget',
                                         'value' => $self->{'plugin'},
                                         'onvaluechanged' => sub { $called = 'called' } );

    my $properties = $self->{'plugin'}->get_properties();
    my $or_dummy = $properties->get( 'dummy' );
    my $ui = new Lire::Test::Mock( 'Lire::UI', 'edit_value_dialog' => 0 );
    $widget->root()->userdata( $ui );
    $widget->_properties_cb_helper();
    $self->assert_deep_equals( [ $ui, $properties, "Properties for wawa" ],
                               $ui->get_invocation( 'edit_value_dialog' ) );
    $self->assert_str_not_equals( $properties, $ui->get_invocation( 'edit_value_dialog' )->[1] );
    $self->assert_str_equals( $or_dummy, $properties->get( 'dummy' ) );
    $self->assert_str_not_equals( 'called', $called );

    $ui->set_result( 'edit_value_dialog', 1 );
    $widget->_properties_cb_helper();
    my $new_props = $ui->get_invocation( 'edit_value_dialog', 1 )->[1];
    $self->assert_str_equals( $new_props->get( 'dummy' ),
                              $properties->get( 'dummy' ) );
    $self->assert_str_equals( 'called', $called );

    $self->{'plugin'}->set_plugin( undef );
    $widget->_properties_cb_helper();
    $self->assert_num_equals( 2, $ui->invocation_count( 'edit_value_dialog' ));

    $self->{'plugin'}->set_plugin( 'one' );
    $widget->_properties_cb_helper();
    $self->assert_num_equals( 2, $ui->invocation_count( 'edit_value_dialog' ));

    return;
}

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

    my $called = 'onvaluechanged not called';
    my $win = $self->{'window'};
    my $widget = $win->add( 'test_widget', 'Lire::UI::PluginWidget',
                            'value' => $self->{'plugin'},
                            'onvaluechanged' => sub { $called = 'called' } );
    my $list = $widget->getobj( 'list' );
    $self->assert_str_equals( 'wawa', $list->get() );
    $self->assert( defined $widget->getobj( 'button' ) );
    $list->{'-selected'} = 0;
    $list->{'-onchange'}->( $widget );
    $self->assert_str_equals( 'one', $self->{'plugin'}->get_plugin() );
    $self->assert_null( $widget->getobj( 'button' ) );
    $self->assert_str_equals( 'called', $called );

    return;
}

1;


syntax highlighted by Code2HTML, v. 0.9.1