# +-----------------------------------------------------------------------+
# | pLoader - a Perl photo uploader for Piwigo                            |
# +-----------------------------------------------------------------------+
# | Copyright(C) 2008-2010 Piwigo Team                  http://piwigo.org |
# +-----------------------------------------------------------------------+
# | This program 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                                          |
# |                                                                       |
# | 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; if not, write to the Free Software           |
# | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
# | USA.                                                                  |
# +-----------------------------------------------------------------------+
package Uploader::GUI::DlgCommon;
use strict;
use Wx qw/wxDP_ALLOWNONE wxDefaultPosition wxDefaultSize/;
use Wx::Calendar;
use Wx::Locale qw/:default/;
use Data::Dumper;
use base qw/
               Class::Accessor::Fast
           /; 

__PACKAGE__->mk_accessors(     
    qw/
        properties
        frame_callback
      /
);

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

    # to connect the right event handler to each control
    my $ctrl_handlers = {
        'Wx::TextCtrl' => sub { my ( $ctrl ) = @_; Wx::Event::EVT_TEXT( $ctrl, $ctrl, sub { $self->OnTextCtrl(@_) } ); },
        'Wx::Choice'   => sub { my ( $ctrl ) = @_; Wx::Event::EVT_CHOICE( $ctrl, $ctrl, sub { $self->OnChoice(@_) } ); },
        'Wx::RadioBox' => sub { my ( $ctrl ) = @_; Wx::Event::EVT_RADIOBOX( $ctrl, $ctrl, sub { $self->OnRadioBox(@_) } ); },
        'Wx::CheckBox' => sub { my ( $ctrl ) = @_; Wx::Event::EVT_CHECKBOX( $ctrl, $ctrl, sub { $self->OnCheckBox(@_) } ); },
        'Wx::SpinCtrl' => sub { my ( $ctrl ) = @_; Wx::Event::EVT_SPINCTRL( $ctrl, $ctrl, sub { $self->OnSpinCtrl(@_) } ); },
        'Wx::ComboBox' => sub { my ( $ctrl ) = @_;
                              Wx::Event::EVT_COMBOBOX( $ctrl, $ctrl, sub { $self->OnComboBox(@_) } );
                              Wx::Event::EVT_TEXT( $ctrl, $ctrl, sub { $self->OnComboBoxText(@_) } );
                          },
        'Wx::DatePickerCtrl' => sub { my ( $ctrl ) = @_; Wx::Event::EVT_DATE_CHANGED( $ctrl, $ctrl, sub { $self->OnDatePicker(@_) } ); },
        'Uploader::GUI::wxCategoryTreeCtrl' => sub { my ( $ctrl ) = @_;
                                                   Wx::Event::EVT_TREE_SEL_CHANGED(
                                                       $ctrl,
                                                       $ctrl,
                                                       sub { 
                                                           $self->OnCategoryTreeSelChanged(@_); 
                                                       }
                                                   );
                                               },
    };
    
    map {
        my $ctrl =$self->FindWindow($_);

        if(defined $ctrl){
            $ctrl_handlers->{ ref $ctrl}->($ctrl) if exists $ctrl_handlers->{ ref $ctrl};

            $ctrl->SetValidator(
                $self->properties->{$_}->{validator}
            ) if exists $self->properties->{$_}->{validator};
        }
    }
    keys %{$self->properties};
    

}

# what does happen when the text changes
sub OnCheckBox {
    my ( $self, $ctrl, $event ) = @_;
    
    my $id = $ctrl->GetId;
    # change the property value
    $self->properties->{$id}->{value}->(
        $event->IsChecked
    ) if exists $self->properties->{$id}->{value};

    # exec the callback
    $self->properties->{$id}->{frame_callback}->($self, $ctrl, $event) if exists
        $self->properties->{$id}->{frame_callback};    

    $event->Skip;
}

# what does happen when selection changes


sub OnComboBoxText {
    my ( $self, $ctrl, $event ) = @_;

    # text changed by user, not selection
    if( $ctrl->GetValue ne $ctrl->GetStringSelection){
       my $id = $ctrl->GetId;
        # change the property value
        $self->properties->{$id}->{value}->(
            $ctrl->GetValue
        ) if exists $self->properties->{$id}->{value};

        # exec the callback
        $self->properties->{$id}->{frame_callback}->($self, $ctrl, $event) if exists
            $self->properties->{$id}->{frame_callback};    
    }

}


sub OnComboBox {
    my ( $self, $ctrl, $event ) = @_;
     
    my $id = $ctrl->GetId;

    $ctrl->{_multi_selection_mode} = $self->properties->{$id}->{multi_selection_mode}->()
        if exists $self->properties->{$id}->{multi_selection_mode};

    my $selection = exists $self->properties->{$id}->{string_selection} ? $ctrl->GetValue : $ctrl->GetSelection;

    my $value = $self->properties->{$id}->{pre_process}->( $selection ) if exists
        $self->properties->{$id}->{pre_process};    

    if( exists $self->properties->{$id}->{value} ){
        $value = $self->properties->{$id}->{value}->(
            $value,
            $selection,
        );
        # the item selected in the list is not the real value
        # we place here the actual value
        # to use in EVT_IDLE event, and overwrite the text field with it
        $ctrl->{_value} = $value;
    }

    # exec the callback
    $self->properties->{$id}->{frame_callback}->($self, $ctrl, $event) if exists
        $self->properties->{$id}->{frame_callback};    
}


# what does happen when the text changes
sub OnTextCtrl {
    my ( $self, $ctrl, $event ) = @_;
    
    my $id = $ctrl->GetId;
    # change the property value
    $self->properties->{$id}->{value}->(
        $event->GetString
    ) if exists $self->properties->{$id}->{value};

    # exec the callback
    $self->properties->{$id}->{frame_callback}->($self, $ctrl, $event) if exists
        $self->properties->{$id}->{frame_callback};    
    
}

sub OnSpinCtrl {
    my ( $self, $ctrl, $event ) = @_;
    
    my $id = $ctrl->GetId;
    # change the property value
    $self->properties->{$id}->{value}->(
        $event->GetInt
    ) if exists $self->properties->{$id}->{value};

    # exec the callback
    $self->properties->{$id}->{frame_callback}->($self, $ctrl, $event) if exists
        $self->properties->{$id}->{frame_callback};    
    
    $event->Skip;
}

sub OnRadioBox {
    my ( $self, $ctrl, $event ) = @_;
    
    my $id = $ctrl->GetId;

    # if a preprocess value is required
    my $value = $event->GetSelection;
    $value = $self->properties->{$id}->{pre_process}->( $value ) if exists
        $self->properties->{$id}->{pre_process};    
    # change the property value. use the index selection
    $self->properties->{$id}->{selection}->(
        $value
    ) if exists $self->properties->{$id}->{selection};

    # exec the callback
    $self->properties->{$id}->{frame_callback}->($self, $ctrl, $event) if exists
        $self->properties->{$id}->{frame_callback};    
    
    $event->Skip;

}

sub OnChoice {
    my ( $self, $ctrl, $event ) = @_;
    
    my $id = $ctrl->GetId;

    # if a preprocess value is required
    my $value = exists $self->properties->{$id}->{string_selection} ? $event->GetString : $event->GetSelection;
    $value = $self->properties->{$id}->{pre_process}->( $value ) if exists
        $self->properties->{$id}->{pre_process};    
    # change the property value. use the index selection
    $self->properties->{$id}->{selection}->(
        $value
    ) if exists $self->properties->{$id}->{selection};

    # change the property value. use the string
    $self->properties->{$id}->{string_selection}->(
        $value
    ) if exists $self->properties->{$id}->{string_selection};

    # exec the callback
    $self->properties->{$id}->{frame_callback}->($self, $ctrl, $event) if exists
        $self->properties->{$id}->{frame_callback};    
    
    $event->Skip;
}


sub OnDatePicker {
    my ( $self, $ctrl, $event ) = @_;
    
    my $id = $ctrl->GetId;

    # change the property value
    $self->properties->{$id}->{value}->(
        $event->GetDate->FormatISODate
    ) if exists $self->properties->{$id}->{value};
    # exec the callback
    $self->properties->{$id}->{frame_callback}->($self, $ctrl, $event) if exists
        $self->properties->{$id}->{frame_callback};    
    
    $event->Skip;
}


my $change_value = {
    'Wx::SpinCtrl' => sub { my ($ctrl, $value ) = @_; $ctrl->SetValue($value)},
    'Wx::TextCtrl' => sub { my ($ctrl, $value ) = @_; $ctrl->ChangeValue($value)},
    'Wx::CheckBox' => sub { my ($ctrl, $value ) = @_; $ctrl->SetValue($value)},
    'Wx::DatePickerCtrl' => sub { my ($ctrl, $value ) = @_;
                                  my $date = Wx::DateTime->new;    
                                  my ($yyyy, $mm, $dd, $hh, $mi, $ss ) = split(/[:\/\\\-\.\s]/, $value);
                                  $date->ParseDate(
                                    sprintf("%s/%s/%s", $yyyy, $mm, $dd)
                                  );
                                  if(-1 eq $value){
                                      $date->SetToCurrent;
                                  }
                                  $ctrl->SetValue($date);
                            },
    'Wx::ComboBox' => sub { 
                          my ($ctrl, $value ) = @_; 
                          $ctrl->SetValue($value) ; 
                      },
};


sub OnCategoryTreeSelChanged {
    my ( $self, $ctrl, $event ) = @_;

    my $id = $ctrl->GetId;

    # change the property value.
    $self->properties->{$id}->{id_selection}->(
        $event->GetEventObject->GetSelectionsIds
    ) if exists $self->properties->{$id}->{id_selection};

    #printf("OnCategoryTreeSelChanged %s\n", Dumper $self->properties->{$id}->{id_selection}->());

    # exec the callback
    $self->properties->{$id}->{frame_callback}->($self, $ctrl, $event) if exists
        $self->properties->{$id}->{frame_callback};    
    
    $event->Skip;
}


my $clear_value = {
    'Wx::TextCtrl' => sub { my ($ctrl) = @_; $ctrl->Clear},
    'Wx::CheckBox' => sub { my ($ctrl) = @_; $ctrl->SetValue(0)},
    'Wx::DatePickerCtrl' => sub { my ($ctrl) = @_; $ctrl->SetValue(Wx::DateTime->new->SetToCurrent)},
    'Uploader::GUI::wxCategoryTreeCtrl' => sub { my ( $ctrl ) = @_;
                                               $ctrl->SelectItem($ctrl->GetRootItem);
                                           },
};    

sub SetProperties {
    my ( $self ) = @_;
    
    map {
        my $ctrl =$self->FindWindow($_);
        if(defined $ctrl){
            #printf("%s\n", $ctrl);
            # checkbox, static text
            $change_value->{ref $ctrl}->(
                $ctrl,
                $self->properties->{$_}->{value}->()
            ) if exists $self->properties->{$_}->{value};
            # only works for control with items
            $ctrl->SetSelection(
                $self->properties->{$_}->{selection}->()
            ) if exists $self->properties->{$_}->{selection};

            $ctrl->SetStringSelection(
                gettext(
                    $self->properties->{$_}->{string_selection}->()
                )
            ) if exists $self->properties->{$_}->{string_selection};
        }
    }
    keys %{$self->properties};
}

sub InitLabels {
    my ( $self ) = @_;
    
    map {
        my $ctrl =$self->FindWindow($_)||$self->{$_};
        #printf("ctrl %s : %s\n", $_, $ctrl);        
        if(defined $ctrl){
            # checkbox, static text
            $ctrl->SetLabel(
               $self->properties->{$_}->{label}
            ) if exists $self->properties->{$_}->{label};

            $ctrl->GetStaticBox->SetLabel(
                $self->properties->{$_}->{staticbox_label}
            ) if exists $self->properties->{$_}->{staticbox_label};

            # radiobox
            my $labels =$self->properties->{$_}->{labels};
            $labels||=[];
            for(my $i=0; $i < scalar @$labels ; $i++){
                $ctrl->SetItemLabel($i, $labels->[$i]);
            }

            # notebook pages
            my $texts =$self->properties->{$_}->{texts};
            $texts||=[];
            for(my $i=0; $i < scalar @$texts ; $i++){
                $ctrl->SetPageText($i, $texts->[$i]);
            }

        }
    }
    keys %{$self->properties};

}

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

    map {
        my $ctrl =$self->FindWindow($_);
        #printf("ctrl %s : %s\n", $_, $ctrl);        
        if(defined $ctrl){
            # choice
            my $choices =$self->properties->{$_}->{choices};
            $choices||=[];
            map{
                $ctrl->Append($_);
            }@$choices;
        }
    }
    keys %{$self->properties};

}

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

    map {
        my $ctrl = $self->FindWindow($_);
        #printf("ctrl %s : %s\n", $_, $ctrl);        
        if(defined $ctrl){
        # checkbox, static text
            $self->properties->{$_}->{value}->(
                $ctrl->GetValue()
            ) if exists $self->properties->{$_}->{value};

            $self->properties->{$_}->{selection}->(
                $ctrl->GetSelection()            
            ) if exists $self->properties->{$_}->{selection};

            $self->properties->{$_}->{string_selection}->(
                $ctrl->GetStringSelection()            
            ) if exists $self->properties->{$_}->{string_selection};
        }
    }
    keys %{$self->properties};
}

sub ClearProperties {
    my ( $self ) = @_;
    
    map {
        my $ctrl =$self->FindWindow($_);
        if(defined $ctrl){
             # checkbox, static text
            $clear_value->{ref $ctrl}->(
                $ctrl
            ) if exists  $clear_value->{ref $ctrl};
            # only works for control with items
            $ctrl->SetSelection(
                -1            
            ) if exists $self->properties->{$_}->{selection};
        }

            $ctrl->SetStringSelection(
                -1            
            ) if exists $self->properties->{$_}->{string_selection};
    }
    keys %{$self->properties};

}
1;