package tests::UIFileWidgetTest;

use strict;

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

use Lire::Config::TypeSpec;
use Lire::Test::CursesUIDriver;
use Curses::UI;
use File::Basename qw/ dirname basename /;

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

    $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' );

    my $spec = new Lire::Config::ConfigSpec();
    $spec->add( new Lire::Config::FileSpec( 'name' => 'file_param' ) );
    $self->{'file_param'} = $spec->get( 'file_param' )->instance( 'value' => '/etc/passwd' );
    $self->{'spec'} = $spec;

    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( 'file_widget',
                                                       'Lire::UI::FileWidget' ) } );
    $self->assert_dies( qr{'value' parameter should be a 'Lire::Config::Scalar' instance, not 'HASH},
                      sub { my $widget = $win->add( 'file_widget',
                                                    'Lire::UI::FileWidget',
                                                    'Value' => {} ) } );

    my $refresh_widget = undef;
    no warnings 'redefine';
    local *Lire::UI::FileWidget::_refresh_warn_label = sub { $refresh_widget = shift };

    my $widget = $win->add( 'file_widget', 'Lire::UI::FileWidget',
                            'value' => $self->{'file_param'} );
    $self->assert_isa( 'Lire::UI::FileWidget', $widget );
    my $file_field = $widget->getobj( 'file_field' );
    $self->assert_isa( 'Curses::UI::TextEntry', $file_field );
    $self->assert_str_equals( '/etc/passwd', $file_field->text() );
    $self->assert_str_equals( \&Lire::UI::FileWidget::_on_change_cb,
                              $file_field->{'-onchange'} );

    $self->assert_str_equals( $widget, $refresh_widget,
                              "'_refresh_warn_label' wasn't called" );

    my $warn_label = $widget->getobj( 'warn_label' );
    $self->assert_isa( 'Curses::UI::Label', $warn_label );
    $self->assert_str_equals( '', $warn_label->{'-text'} );

    my $browse_btn = $widget->getobj( 'browse_btn' );
    $self->assert_isa( 'Curses::UI::Buttonbox', $browse_btn );
    $self->assert_str_equals( '[Browse]',
                              $browse_btn->{'-buttons'}[0]{'-label'} );
    $self->assert_str_equals( \&Lire::UI::FileWidget::_browse_cb,
                              $browse_btn->{'-buttons'}[0]{'-onpress'} );


    return;
}

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

    my $widget = $self->{'window'}->add( 'test_widget', 'Lire::UI::FileWidget',
                                         'value' => $self->{'file_param'} );
    my $file_field = $widget->getobj( 'file_field' );
    my $warn_label = $widget->getobj( 'warn_label' );
    $self->{'file_param'}->set( '/etc/group' );
    $widget->refresh_view();
    $self->assert_str_equals( '/etc/group', $file_field->text() );
    $self->assert_str_equals( '', $warn_label->text() );
    $self->{'file_param'}->set( '/no/such/file' );
    $widget->refresh_view();
    $self->assert_str_equals( '/no/such/file', $file_field->text() );
    $self->assert_str_equals( 'Invalid filename', $warn_label->text() );
}

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::FileWidget',
                            'value' => $self->{'file_param'},
                            'onvaluechanged' => sub { $called = 'called' } );

    my $file_field = $widget->getobj( 'file_field' );
    my $or_value = $file_field->text();
    $file_field->text( '/etc/group' );
    Lire::UI::FileWidget::_on_change_cb( $file_field );
    $self->assert_str_not_equals( $or_value, $self->{'file_param'}->get() );
    $self->assert_str_equals( '/etc/group', $self->{'file_param'}->get() );
    $self->assert_str_equals( 'called', $called );

    $file_field->text( '/no_such_file' );
    Lire::UI::FileWidget::_on_change_cb( $file_field );
    $self->assert_str_equals( '/no_such_file', $self->{'file_param'}->get() );
    my $warn_label = $widget->getobj( 'warn_label' );
    $self->assert_str_equals( 'Invalid filename', $warn_label->{'-text'} );

    $file_field->text( '/etc/passwd' );
    Lire::UI::FileWidget::_on_change_cb( $file_field );
    $self->assert_str_equals( '', $warn_label->{'-text'} );

    return;
}

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

    my $dlg = '< undef >';
    my $filename = $self->{'file_param'}->get();

    $self->{'driver'}->add_event_loop_handler(
       sub {
           $dlg = $_[1];
           $self->assert_str_equals( dirname( $filename ), $dlg->{'-path'} );
           $self->assert_str_equals( basename( $filename ), $dlg->{'-file'} );
           $dlg->getobj('pathvalue')->text( '/dev' );
           $dlg->getobj('filevalue')->text( 'null' );
           $dlg->getobj('buttons')->{'-selected'} = 0;
       } );

    my $widget = $self->{'window'}->add( 'test_widget', 'Lire::UI::FileWidget',
                                         'value' => $self->{'file_param'} );
    Lire::UI::FileWidget::_browse_cb( $widget->getobj( 'browse_btn' ) );
    $self->assert_isa( 'Curses::UI::Dialog::Filebrowser', $dlg );
    $self->assert_str_equals( '/dev/null', $self->{'file_param'}->get() );

    $self->{'driver'}->add_event_loop_handler(
       sub {
           $dlg = $_[1];
           $dlg->getobj('pathvalue')->text( '/dev' );
           $dlg->getobj('filevalue')->text( 'zero' );
           $dlg->getobj('buttons')->{'-selected'} = 1;
       } );
    Lire::UI::FileWidget::_browse_cb( $widget->getobj( 'browse_btn' ) );
    $self->assert_str_equals( '/dev/null', $self->{'file_param'}->get() );
}

1;


syntax highlighted by Code2HTML, v. 0.9.1