{
	package GCPlugins;
    
###################################################
#
#  Copyright 2005 Tian
#
#  This file is part of GCfilms.
#
#  GCfilms 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; either version 2 of the License, or
#  (at your option) any later version.
#
#  GCfilms 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 GCfilms; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
###################################################

    use strict;
    
    use base 'Exporter';
    our @EXPORT = qw(%pluginsMap @pluginsNameArray);
    
    our %pluginsMap;
    our @pluginsNameArray;

    use Cwd;
    use File::Basename;
    use FindBin qw($RealBin);
    my $oldCwd = getcwd;
    chdir $RealBin;
    foreach (glob "../lib/gcfilms/GCPlugins/*.pm")
    {
        my $plugin = basename($_, '.pm')."\n";
        next if $plugin =~ /GCPluginsBase/;
        eval "use GCPlugins::$plugin";
        (my $class = $plugin) =~ s/^GC/GCPlugin/;
        my $obj;
        eval "\$obj = new GCPlugins::$class";
        die "Fatal error with plugin $plugin : $@" if $@;
        $pluginsMap{$obj->getName} = $obj;
    }
    @pluginsNameArray = sort keys %pluginsMap;
    chdir $oldCwd;
    
    {
        package GCPluginJob;
        
        use Storable qw(store_fd fd_retrieve);
        use IO::Handle;
        
        sub new
        {
            my ($proto, $command, $data) = @_;
            my $class = ref($proto) || $proto;
            
            my $self  = {command => $command, data => $data};
            $command->autoflush(1);
            $data->autoflush(1);
                        
            bless ($self, $class);
            return $self;
        }
        
        sub run
        {
            my $self = shift;
            
            my $command = $self->{command};
            while (1)
            {
                my $plugin = fd_retrieve($command);
                $self->beginSearch($plugin);
            }
        }
        
        sub beginSearch
        {
            my ($self, $plugin) = @_;
            
            my $pid;
            if ($pid = fork)
            {
                my $command = $self->{command};
                $command->autoflush(1);
                my $cmd = readline($command);
                chomp $cmd;
                kill 9,$pid if ($cmd eq 'STOP');
                wait;
            }
            else
            {
                if ($plugin->{type} eq 'load')
                {
                    $plugin->load;
                    store_fd $plugin, $self->{data};
                }
                else
                {
                    store_fd $plugin->getMovieInfo, $self->{data};
                }
                exit;   
            }
        }
    }
 
    use Gtk2;
 
	{
	    package GCPluginsDialog;
	    
	    use base "Gtk2::Dialog";
	
	    sub show
	    {
	        my $self = shift;
	        $self->{useThisSite}->set_active(0);
	        $self->SUPER::show();
	        $self->show_all;
	        my $path = $self->{pluginsList}->get_selection->get_selected_rows;
		    $self->{pluginsList}->scroll_to_cell($path) if $path;
	        
	        my $response = $self->run;
	        $self->{plugin} = undef;
	        if ($response eq 'ok')
	        {
	            my $pluginName = '';
	            my $idx = ($self->{pluginsList}->get_selected_indices)[0];
                $pluginName = $self->{pluginsList}->{data}->[$idx]->[0 + $self->{withPics}];
	            $self->{plugin} = $pluginsMap{$pluginName};

	            if ($self->{useThisSite}->get_active)
	            {
	               $self->{parent}->{options}->plugin($pluginName);
	               $self->{parent}->checkPlugin;
	            }
	        }
	        $self->hide;
	    }
	    
	    sub new
	    {
            my ($proto, $parent) = @_;
            my $class = ref($proto) || $proto;
            my $self  = $class->SUPER::new($parent->{lang}->{PluginsTitle},
                                  $parent,
                                  [qw/modal destroy-with-parent/],
                                  @GCDialogs::okCancelButtons
                                  );
    
    	        bless ($self, $class);
    
            $self->{parent} = $parent;
            $self->{withPics} = $parent->{hasPluginsPictures};
    
            $self->{query} = new Gtk2::Entry();
            $self->vbox->pack_start($self->{query}, 0, 0, 10);
    	
            my $pluginGroup = undef;
            my $pluginsFrame = new Gtk2::Frame($parent->{lang}->{PluginsFrame});
            $pluginsFrame->set_border_width(5);
            
            if ($self->{withPics})
            {
                $self->{pluginsList} = new Gtk2::SimpleList($parent->{lang}->{PluginsLogo} => "pixbuf",
                                                            $parent->{lang}->{PluginsName} => "text",
                                                            $parent->{lang}->{PluginsLang} => "text",
                                                            $parent->{lang}->{PluginsAuthor} => "text",);
            }
            else
            {
                $self->{pluginsList} = new Gtk2::SimpleList($parent->{lang}->{PluginsName} => "text",
                                                            $parent->{lang}->{PluginsLang} => "text",
                                                            $parent->{lang}->{PluginsAuthor} => "text",);
            }
            $self->{pluginsList}->set_border_width(5);
            $self->{pluginsList}->set_rules_hint(1);
            $self->{pluginsList}->get_column(0)->set_min_width(150);
            for my $i (0..2)
            {
                $self->{pluginsList}->get_column($i)->set_resizable(1);
            }
            $self->{pluginsList}->signal_connect(row_activated => sub {
                $self->response('ok');
            });

            $self->{currentPluginList} = undef;

            $self->setPluginsList;
	
            my $scrollPanelList = new Gtk2::ScrolledWindow;
            $scrollPanelList->set_border_width(5);
            $scrollPanelList->set_policy ('never', 'automatic');
            $scrollPanelList->set_shadow_type('etched-in');
            $scrollPanelList->add($self->{pluginsList});

            $pluginsFrame->add($scrollPanelList);
            $self->vbox->pack_start($pluginsFrame, 1, 1, 10);
	        
            $self->{useThisSite} = Gtk2::CheckButton->new($parent->{lang}->{PluginsUseSite});
            $self->vbox->pack_start($self->{useThisSite}, 0, 0, 5);
	        
            $self->set_default_size(1,550);
	        
	        return $self;
	    }
	
	    sub query
	    {
	        my $self = shift;
	        $self->{query}->set_text(shift) if @_;
	        return $self->{query}->get_text;
	    }
	
	    sub plugin
	    {
	        my $self = shift;
	        
	        return $self->{plugin};
	    }
	    
	    sub setPluginsList
	    {
	        my $self = shift;
	        my $list = shift;
            my @plugins_array = sort split (",", $list) if $list;

            return if $list && ($self->{currentPluginList} eq $list);
            $self->{currentPluginList} = $list;

	        my $pluginGroup = undef;
            my $i = 0;
            my @newData;
	        foreach (sort keys %GCPlugins::pluginsMap)
	        {
	            my $plugin = $GCPlugins::pluginsMap{$_};
                if ((!$list) || ($plugin->getName eq $plugins_array[$i]))
                {
                    if ($self->{withPics})
                    {
                        my $picFile = $self->{parent}->{pluginsPicturesDir}.$plugin->getImageFile;
                        $picFile = $ENV{GCF_SHARE_DIR}.'/icons/gcfilms_32x32.png' if ! -f $picFile;
	          	 	    my $pixbuf = Gtk2::Gdk::Pixbuf->new_from_file($picFile);
    	          	 	push @newData, [$pixbuf, $plugin->getName, "\n".$plugin->getLang."\n", $plugin->getAuthor];
                    }
                    else
                    {
    	          	 	push @newData, [$plugin->getName, "\n".$plugin->getLang."\n", $plugin->getAuthor];
                    }
	          	 	
                    $i++;
                }
	        }
	        @{$self->{pluginsList}->{data}} = @newData;
	        $self->{pluginsList}->select(0);
	    }
	}
	 
    use GCDialogs;
 
    {
        #Class that is used to let user select
        #plugins he wants to use in a multi-site search.
        package GCMultiSiteDialog;

        use base "GCDoubleListDialog";
        
        sub getInitData
        {
            my $self = shift;
            
            return \@pluginsNameArray;
        }
        
        sub getData
        {
            my $self = shift;
            
            my @array = split m/,/, $self->{options}->multisite;
            return \@array;
        }
        
        sub saveList
        {
            my ($self, $list) = @_;
            
            my $value = join ',', @$list;
            $self->{options}->multisite($value);
        }
        
        sub getPlugin
        {
            my ($self, $idx) = @_;
            $self->init;
            return $self->{usedArray}->[$idx];
        }
        
        sub getPluginsNumber
        {
            my $self = shift;
            $self->init;
            return scalar @{$self->{usedArray}};
        }
                
        sub preFill
        {
            my $self = shift;
            
            my @data;
            foreach (@pluginsNameArray)
            {
                push @data, $_ if $pluginsMap{$_}->getLang eq $self->{options}->lang;
            }
            $self->setListData(\@data);
        }

        sub getUnusedLabel
        {
            my $self = shift;
            
            return $self->{parent}->{lang}->{MultiSiteUnused};
        }
        sub getUsedLabel
        {
            my $self = shift;
            
            return $self->{parent}->{lang}->{MultiSiteUsed};
        }
               
                
	    sub new
	    {
	        my ($proto, $parent) = @_;
	        my $class = ref($proto) || $proto;
	        my $self  = $class->SUPER::new(
	                                $parent,
	                                $parent->{lang}->{MultiSiteTitle}
                                );
            bless ($self, $class);

            if (! $parent->{options}->exists('multisite'))
            {
                $self->preFill;
                $self->saveList(\@{$self->{usedArray}});
                $self->{initialized} = 1;
            }

            my $langButton = new Gtk2::Button($parent->{lang}->{MultiSiteLang});
            $langButton->signal_connect('clicked' => sub {
                $self->preFill;
            });
            my $clearButton = new Gtk2::Button($parent->{lang}->{MultiSiteClear});
            $clearButton->signal_connect('clicked' => sub {
                $self->clearList;
            });            
            
            $self->{hboxAction}->pack_start($langButton,1,1,10);
            $self->{hboxAction}->pack_start($clearButton,1,1,10);
            
	        return $self;
	    }
    }
    
}

{
    package GCResultsDialog;
    use base "Gtk2::Dialog";

    sub show
    {
        my $self = shift;
        for my $i (0..3)
        {
            $self->{results}->get_column($i)->set_sort_indicator(0);
        }
        $self->{order} = 1;
        $self->{sort} = '';

        $self->{validated} = 0;
        $self->SUPER::show();
        $self->show_all;
        $self->{nextButton}->hide if !$self->{withNext};
        my $code = $self->run;
        if ($code eq 'ok')
        {
            $self->{validated} = 1;
            my @idx = $self->{results}->get_selected_indices;
            $self->{movieIndex} = $idx[0];
        }
        $self->hide;
        return ($code eq 'no');
    }

    sub getMovieIndex
    {
        my $self = shift;
        return $self->{movieIndex};
    }

    sub setWithNext
    {
        my ($self, $value) = @_;
        
        $self->{withNext} = $value;
    }

    sub setSearchPlugin
    {
       my ($self, $plugin) = @_;
       
       $self->set_title($self->{parent}->{lang}->{ResultsTitle}.' ('.$plugin->getName.')');
       
       if ($plugin->getExtra)
       {
           $self->{results}->get_column(4)->set_visible(1);
           $self->{results}->get_column(4)->set_title($plugin->getExtra);
           $self->{withExtra} = 1;
       }
       else
       {
           $self->{results}->get_column(4)->set_visible(0);
           $self->{withExtra} = 0;
       }
       
       $self->{results}->get_column(1)->set_visible(1) if $plugin->hasSearchYear;
       $self->{results}->get_column(1)->set_visible(0) if ! $plugin->hasSearchYear;

       $self->{results}->get_column(2)->set_visible(1) if $plugin->hasSearchDirector;
       $self->{results}->get_column(2)->set_visible(0) if ! $plugin->hasSearchDirector;

       $self->{results}->get_column(3)->set_visible(1) if $plugin->hasSearchActors;
       $self->{results}->get_column(3)->set_visible(0) if ! $plugin->hasSearchActors;
    }

    sub new
    {
        my ($proto, $parent) = @_;
        my $class = ref($proto) || $proto;
        my $self  = $class->SUPER::new($parent->{lang}->{ResultsTitle},
                              $parent,
                              [qw/modal destroy-with-parent/],
                              @GCDialogs::okCancelButtons
                            );
        bless ($self, $class);

        $self->{withExtra} = 0;
        $self->{withNext} = 0;
        $self->{nextButton} = Gtk2::Button->new_from_stock('gtk-go-forward');
        $parent->{tooltips}->set_tip($self->{nextButton},
                                     $parent->{lang}->{ResultsNextTip});
        $self->add_action_widget($self->{nextButton}, 'no');

        $self->{parent} = $parent;

        $self->set_modal(1);
		$self->set_position('center');

        $self->{results} = new Gtk2::SimpleList($parent->{lang}->{ResultsMovieTitle} => "text",
                                                $parent->{lang}->{ResultsMovieYear} => "text",
                                                $parent->{lang}->{ResultsMovieDirector} => "text",
                                                $parent->{lang}->{ResultsMovieActors} => "text",
                                                '' => "text");
        $self->{results}->set_rules_hint(1);
        $self->{results}->set_headers_clickable(1);

        $self->{order} = 1;
        $self->{sort} = '';
        
        for my $i (0..3)
        {
            $self->{results}->get_column($i)->set_sort_indicator(0);
        }
        
        $self->{results}->get_column(0)->signal_connect('clicked' => sub {
                $self->sort('title');
            });
        $self->{results}->get_column(1)->signal_connect('clicked' => sub {
                $self->sort('year');
            });
        $self->{results}->get_column(2)->signal_connect('clicked' => sub {
                $self->sort('director');
            });
        $self->{results}->get_column(3)->signal_connect('clicked' => sub {
                $self->sort('actors');
            });

        my $scrollPanelList = new Gtk2::ScrolledWindow;
        $scrollPanelList->set_policy ('never', 'automatic');
        $scrollPanelList->set_shadow_type('etched-in');
        $scrollPanelList->add($self->{results});

                                            
        my @buttons = $self->action_area->get_children;
        my $ok_button = $buttons[1];

       $self->{results}->signal_connect(row_activated => sub {
            my ($sl, $path, $column, $ok) = @_;
            $self->response('ok');
        }, $ok_button);
    
        $self->vbox->add($scrollPanelList);
 
        return $self;
    }

    sub sort
    {
        my ($self, $type) = @_;
        
        for my $i (0..3)
        {
            $self->{results}->get_column($i)->set_sort_indicator(0);
        }
        
        sub compareTitle
        {
            use locale;
            $a->{title} cmp $b->{title};
        }       
        sub compareYear
        {
            use locale;
            $a->{year} cmp $b->{year};
        }
        sub compareDirector
        {
            use locale;
            $a->{director} cmp $b->{director};
        }
        sub compareActors
        {
            use locale;
            $a->{actors} cmp $b->{actors};
        }

        my @movies = @{$self->{movies}};
        
        if ($self->{sort} eq $type)
        {
            $self->{order} = 1 - $self->{order}
        }
        else
        {
            $self->{order} = 1;
        }
        
        my $col;
        if ($type eq 'title')
        {
            $col = 0;
            @movies = sort compareTitle @movies;
        }
        elsif ($type eq 'year')
        {
            $col = 1;
            @movies = sort compareYear @movies;
        }
        elsif ($type eq 'director')
        {
            $col = 2;
            @movies = sort compareDirector @movies;
        }
        else
        {
            $col = 3;
            @movies = sort compareActors @movies;
        }
        
        @movies = reverse @movies if ! $self->{order};
        
        $self->{results}->get_column($col)->set_sort_indicator(1);
        $self->{results}->get_column($col)->set_sort_order($self->{order} ? 'ascending' : 'descending');
        
        $self->setList('',@movies);

        $self->{sort} = $type;
    }
    
    sub setList
    {
        my ($self, $title, @movies) = @_;
        
        $self->set_title($self->get_title . ' - '.$title) if $title;
        
        $self->{movies} = \@movies;

        @{$self->{results}->{data}} = ();

        my $movie;
        foreach $movie (@movies)
        {
            (my $sTitle = $movie->{'title'}) =~ s/(.{40}).*/$1.../;
            (my $sActors = $movie->{'actors'}) =~ s/(.{40}).*/$1.../;
            (my $sExtra = $movie->{'extra'}) =~ s/(.{40}).*/$1.../;
            my @infos = [ $sTitle."\n", $movie->{'year'}."\n", $movie->{'director'}."\n", $sActors."\n", $sExtra."\n"];
            push @{$self->{results}->{data}}, @infos;
        }
        $self->{results}->select(0);
        $self->{results}->columns_autosize;
        #$self->resize(1,1);
        $self->set_default_size(200,400);
    }
    
}

{
    package GCImportFieldsDialog;
    use base "Gtk2::Dialog";

    sub info
    {
        my $self = shift;
        
        if (@_)
        {
            my $info = shift;

            $self->{info} = $info;
        
            my @children = $self->{table}->get_children;
            my $i = 0;
            foreach (@children)
            {
                $i++;
                next if $_->get_name eq 'GtkButton';
                $_->set_text('') unless $i % 2;
            }
        
            foreach (keys %{$info})
            {
                next if $_ eq 'url';
                (my $tmp = $info->{$_}) =~ s/\n/ /g;
                $tmp =~ s/(.{50}).*/$1.../m;
                #Special values for age
                if ($_ eq 'age')
                {
                    if ($tmp == 0)
                    {
                        $tmp = '';
                    }
                    elsif ($tmp == 1)
                    {
                        $tmp = $self->{parent}->{lang}->{PanelAgeUnknown};
                    }
                    elsif ($tmp == 2)
                    {
                        $tmp = $self->{parent}->{lang}->{PanelAgeNone};
                    }
                    elsif ($tmp == 5)
                    {
                        $tmp = $self->{parent}->{lang}->{PanelAgeParent};
                    }
                }
                $self->{$_}->set_text($tmp);
            }
        }
        else
        {
            my $ignore = $self->{parent}->{ignoreString};
            
            foreach my $field(@{$self->{parent}->{movies}->{fields}})
            {
                next if ! $self->{parent}->{movies}->{fieldsInfo}->{$field}->{isImported};
                next if ($field eq 'url');
                $self->{info}->{$field} = $ignore if ! $self->{$field.'Cb'}->get_active;
            }            

            return $self->{info};
        }
    }
    
    sub showImage
    {
        use File::Temp qw/ :mktemp  /;
        
        my $self = shift;
        
        $self->window->set_cursor(Gtk2::Gdk::Cursor->new('watch'));
        Gtk2->main_iteration while (Gtk2->events_pending);
        my $tmpFile = mktemp('/tmp/gcfilmsXXXXXX');
        
        my $browser = LWP::UserAgent->new;
        $browser->proxy(['http'], $self->{parent}->{options}->proxy);
        $browser->agent($self->{parent}->{agent});
        $browser->get($self->{info}->{image}, ':content_file' => $tmpFile);
        
        my $dialog = new GCImageDialog($self, $tmpFile);
        
        $self->window->set_cursor(Gtk2::Gdk::Cursor->new('left_ptr'));
        $dialog->show;
        $dialog->destroy;
        unlink $tmpFile;
    }
    
    sub show
    {
        my $self = shift;

        $self->SUPER::show();
        $self->show_all;
        $self->{image}->hide if $self->{info}->{image};
        $self->{buttonImage}->hide if ! $self->{info}->{image};
        my $response = $self->run;
        $self->hide;
        return ($response eq 'ok');
    }

    sub new
    {
        my ($proto, $parent) = @_;
        my $class = ref($proto) || $proto;
        my $self  = $class->SUPER::new($parent->{lang}->{ImportWindowTitle},
                              $parent,
                              [qw/modal destroy-with-parent/],
                              @GCDialogs::okCancelButtons
                            );

        bless ($self, $class);
        
        $self->{parent} = $parent;
 
        $self->set_modal(1);
		$self->set_position('center');
        $self->set_default_size(1,500);

        $self->{table} = new Gtk2::Table(15,2,0);
        $self->{table}->set_row_spacings(10);
        $self->{table}->set_col_spacings(10);
        $self->{table}->set_border_width(20);
        
        my $row = 0;
        
        foreach my $field(@{$self->{parent}->{movies}->{fields}})
        {
            next if ! $self->{parent}->{movies}->{fieldsInfo}->{$field}->{isImported};
            next if ($field eq 'image') || ($field eq 'url');
            $self->{$field.'Cb'} = new Gtk2::CheckButton($parent->{lang}->{Displayed}->{$field});
            $self->{$field} = new Gtk2::Entry;
            $self->{$field}->set_editable(0);
            $self->{table}->attach($self->{$field.'Cb'}, 0, 1, $row, $row + 1, 'fill', 'fill', 0, 0);
            $self->{table}->attach($self->{$field}, 1, 2, $row, $row + 1, 'fill', 'fill', 0, 0);
            $row++;
        }
        
        $self->{title}->set_width_chars(50);
        
        $self->{imageCb} = new Gtk2::CheckButton($parent->{lang}->{Displayed}->{image});
        $self->{image} = new Gtk2::Entry;
        $self->{image}->set_editable(0);
        $self->{table}->attach($self->{imageCb}, 0, 1, $row, $row + 1, 'fill', 'fill', 0, 0);
        $self->{table}->attach($self->{image}, 1, 2, $row, $row + 1, 'fill', 'fill', 0, 0);

        $self->{buttonImage} = new Gtk2::Button($parent->{lang}->{ImportViewPicture});
        $self->{buttonImage}->signal_connect('clicked' => sub {
                $self->showImage;
        });
        $self->{table}->attach($self->{buttonImage}, 1, 2, $row, $row + 1, 'fill', 'fill', 0, 0);

        $row++;

        my $button1 = new Gtk2::Button($parent->{lang}->{ImportSelectAll});
        $button1->signal_connect('clicked' => sub {
                my @children = $self->{table}->get_children;
                my $i = 0;
                foreach (@children)
                {
                    $i++;
                    next if $_->get_name eq 'GtkButton';
                   $_->set_active(1) if $i % 2;
                }
        });
        $self->{table}->attach($button1, 0, 1, $row, $row + 1, 'expand', 'fill', 0, 0);
        $row++;
        my $button2 = new Gtk2::Button($parent->{lang}->{ImportSelectNone});
        $button2->signal_connect('clicked' => sub {
                my @children = $self->{table}->get_children;
                my $i = 0;
                foreach (@children)
                {
                    $i++;
                    next if $_->get_name eq 'GtkButton';
                   $_->set_active(0) if $i % 2;
                }
        });
        $self->{table}->attach($button2, 0, 1, $row, $row + 1, 'expand', 'fill', 0, 0);


        my $scrollPanelList = new Gtk2::ScrolledWindow;
        $scrollPanelList->set_policy ('never', 'automatic');
        $scrollPanelList->set_shadow_type('etched-in');
        $scrollPanelList->add_with_viewport($self->{table});

        $self->vbox->pack_start($scrollPanelList,1,1,10);
 
        return $self;
    }
    
}

1;
