package GCMainWindow;

###################################################
#
#  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 utf8;
    
use strict;
use Gtk2;

{
    package GCMovieWindow;
    use base "Gtk2::Dialog";
    use GCGraphicComponents;

    sub show
    {
        my $self = shift;

        $self->SUPER::show();
        my $code = $self->run;
        return $code;
    }

    sub new
    {
        my ($proto, $parent, $title) = @_;
        my $class = ref($proto) || $proto;
        my $self  = $class->SUPER::new('',
                              undef,
                              [qw/no-separator destroy-with-parent/],
                              @GCDialogs::okCancelButtons);
        bless ($self, $class);
        
        $self->set_modal(1);
        $self->set_title('GCfilms - '.$title);

        my $options = new GCOptionLoader;
        $options->lockPanel(0);
        $options->order(0);
        $options->formats($parent->{options}->formats);
        $options->file($parent->{options}->file);
        $self->{panel} = new GCFormPanel($parent, $options, 0);

        #Init combo boxes
        foreach(@{$parent->{movies}->{fieldsHistory}})
        {
            $self->{panel}->setHistory($_, $parent->{movies}->getHistory($_));
        }

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

        $self->vbox->add($scrollPanelMovie);

        $self->vbox->show_all;
        $self->{panel}->setShowOption($parent->getDialog('DisplayOptions')->{show}, 1);
        
        #Adjust some settings
        $self->{panel}->{frameAction}->hide;
        $self->{panel}->{expanderLang}->set_expanded(0);
        $self->{panel}->disableAutoUpdate;

        $self->set_default_size($parent->{options}->movieWindowWidth,$parent->{options}->movieWindowHeight);
        $self->set_position('center-on-parent');
        
        return $self;
    }
}

{
    package GCRandomMovieWindow;
    use base "Gtk2::Dialog";
    use GCGraphicComponents;

    sub show
    {
        my $self = shift;

        $self->SUPER::show();
        #$self->show_all;
        my $code = $self->run;
        return $code;
    }

    sub new
    {
        my ($proto, $parent, $title, $width, $height) = @_;
        my $class = ref($proto) || $proto;
        my $self  = $class->SUPER::new('',
                              undef,
                              [qw/no-separator destroy-with-parent/],
                              @GCDialogs::okCancelButtons);
        bless ($self, $class);
        
        $self->set_modal(1);
        $self->set_title('GCfilms - '.$title);

        my $options = new GCOptionLoader;
        $options->lockPanel(1);
        $options->order(0);
        $options->formats($parent->{options}->formats);
        $options->file($parent->{options}->file);
        $self->{panel} = new GCFormPanel($parent, $options, 1);
        $self->{panel}->{expanderLang}->set_expanded(0);

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

        $self->{nextButton} = Gtk2::Button->new_from_stock('gtk-go-forward');
        $parent->{tooltips}->set_tip(($self->action_area->get_children)[0],
                                     $parent->{lang}->{RandomOkTip});
        $parent->{tooltips}->set_tip($self->{nextButton},
                                     $parent->{lang}->{RandomNextTip});

        $self->add_action_widget($self->{nextButton}, 'no');
        $self->vbox->add($scrollPanelMovie);

        $self->vbox->show_all;
        $self->{panel}->setShowOption($parent->getDialog('DisplayOptions')->{show}, 1);

        $self->set_default_size($parent->{options}->movieWindowWidth,$parent->{options}->movieWindowHeight);
        #$self->set_position('center-always');
        
        return $self;
    }
}

{
    package GCFrame;
    use base "Gtk2::Window";

    if ($^O =~ /win32/i)
    {
        use File::DosGlob 'glob';
    }

    use GCMoviesLists;
    use GCPlugins;
    use GCGraphicComponents;
    use GCPanel;
    use GCUtils;
    use GCOptions;
    use GCStyle;
    use GCBorrowings;
    use GCDialogs;
    use GCExtract;
    use GCExport;
    use GCImport;
    use GCSplash;
    use GCLang;
    use GCDisplay;
    use GCData;
    use GCGenres;

    use LWP;
    use URI::Escape;
    use File::Basename;
    use File::Spec;
    use IO::Handle;
    use Storable qw(store_fd fd_retrieve);

    sub beforeDestroy
    {
		my $self = shift;
		$self->leave;
		return 1;
    }

    sub leave
    {
        my $self = shift;

        $self->saveList if ($self->{options}->autosave) && ($self->{movies}->{nbMovies});
	
        $self->{options}->expandLang($self->{panel}->{expanderLang}->get_expanded ? 1 : 0)
            if ($self->{panel}->{expanderLang});

		my ($width, $height) = $self->get_size;	
		$self->{options}->width($width);
		$self->{options}->height($height);
		$self->{options}->split($self->{pane}->get_position) if ($self->{pane});
	
		$self->{options}->save;

        $self->{movies}->clean;

        if ($^O !~ /win32/i)
        {
            close $self->{searchJob}->{reader};
            close $self->{searchJob}->{writer};
            kill 9, $self->{searchJob}->{pid};
            wait;
        }
        
        $self->destroy;
    }

    sub deleteCurrentMovie
    {
        my $self = shift;
		my $response = 'yes';
	    my $confirm = 0;

		if ($self->{options}->confirm)
		{
		    my  $dialog = Gtk2::MessageDialog->new($self,
							   [qw/modal destroy-with-parent/],
							   'question',
							   'yes-no',
							   $self->{lang}->{RemoveConfirm});

            $dialog->set_position('center-on-parent');
            my $check = new Gtk2::CheckButton($self->{lang}->{OptionsDontAsk});
            $dialog->vbox->pack_start($check,0,0,5);
            $dialog->vbox->pack_start(Gtk2::HSeparator->new,0,0,5);
            $dialog->vbox->show_all;
		    $response = $dialog->run;
		    $confirm = ($check->get_active ? 0 : 1);
		    $dialog->destroy;
		}
	
		if ($response eq 'yes')
		{
		    $self->{movies}->removeCurrentMovie;
		    $self->{options}->confirm($confirm);
		}
    }

    sub newMovie
    {
			
        my ($self, $self2) = @_;
        $self = $self2 if $self2;
		
        #deverrouille l'interface a la création d'une nouvelle fiche
        $self->{options}->lockPanel(0);
        # Question métaphysique : je mémorise ou pas ?, décommenté pour mémoriser
        #$self->{panel}->changeState($self->{panel}, 0);
        $self->{menubar}->{menuEditLockMoviesItem}->set_active(0);
        
        my $info = $self->{movies}->getEmptyInfo;
        $info->{title} = $self->{lang}->{NewMovie};
        $info->{seen} = 0;
        $self->addMovie($info, 1);
    }

    sub duplicateMovie
    {
			
        my ($self, $self2) = @_;
        $self = $self2 if $self2;

        my $needReload = 0;
        my $info = $self->{panel}->getAsHash;
        if ($info->{collection})
        {
            $info->{rank} = $self->{movies}->getMaxRank($info->{collection}) + 1;
            $needReload = 1;
        }
        $self->addMovie($info, 1);
        $self->{movies}->reloadList if $needReload;
    }

    sub loadUrl
    {
        my ($self, $url) = @_;
        
        my $baseUrl;
        my $plugin;
        foreach (values %GCPlugins::pluginsMap)
        {
            ($baseUrl = $_->getMovieUrl) =~ s/http:\/\/(w{3})?//;
            $plugin = $_;
            last if $url =~ m/$baseUrl/;
        }
        return unless $url =~ m/$baseUrl/;
        $self->setWaitCursor($self->{lang}->{StatusGetInfo});
        $self->newMovie;
        my $info = $plugin->loadUrl($url);
        $self->restoreCursor;
        return if ! $info->{title};        
        $self->addMovie($info, 0);
    }
    
    sub searchMovieForPanel
    {
        my ($self, $title, $panel) = @_;

        if ($panel)
        {
            $self->{previousPanel} = $self->{panel};
            $self->{panel} = $panel;
        }
        $self->searchMovie($title, 0, 0);
        $self->{panel} = $self->{previousPanel} if ($panel);
    }
    
    sub searchMovie
    {
        my ($self, $title, $forceask, $currentPlugin) = @_;

        my $plugin;
        
        if (($self->{options}->plugin eq 'multi') && !$forceask)
        {
            my $pluginName = $self->getDialog('MultiSite')->getPlugin($currentPlugin);
            $plugin = $GCPlugins::pluginsMap{$pluginName};
            if (!$plugin)
            {
              my $dialog = Gtk2::MessageDialog->new($self,
							   [qw/modal destroy-with-parent/],
							   'error',
							   'ok',
							   $self->{lang}->{MultiSiteEmptyError});

              $dialog->set_position('center-on-parent');
		      my $response = $dialog->run;
		      $dialog->destroy;
		      return;
            
            }
        }
        elsif ($self->{options}->plugin eq 'multiask')
        {
            $self->getDialog('PluginsAsk')->setPluginsList($self->{options}->multisite);
            $self->getDialog('PluginsAsk')->query($title);
            $self->getDialog('PluginsAsk')->show;
            $plugin = $self->getDialog('PluginsAsk')->plugin;
#            $plugin->setProxy($self->{options}->proxy);
            return if !$plugin;
            $title = $self->getDialog('PluginsAsk')->query;
        }
        elsif ($forceask || ! $self->{plugin})
        {
            $self->getDialog('Plugins')->query($title);
            $self->getDialog('Plugins')->show;
            $plugin = $self->getDialog('Plugins')->plugin;
            return if !$plugin;
#            $plugin->setProxy($self->{options}->proxy);
            $title = $self->getDialog('Plugins')->query;
        }
        else
        {
            $plugin = $self->{plugin};
        }

        $plugin->setProxy($self->{options}->proxy);

        $plugin->{title} = $title;
        $plugin->{type} = 'load';
        
        if (! $self->{options}->searchStop)
        {
            $self->setWaitCursor($self->{lang}->{StatusSearch}.' ('.$plugin->getName.')');
            $plugin->load;
            $self->restoreCursor;
        }
        else
        {
            store_fd $plugin, $self->{searchJob}->{command};
            my $getInfo = 0;
            my $dialog = Gtk2::MessageDialog->new($self,
                [qw/modal destroy-with-parent/],
                'info',
                'cancel',
                $self->{lang}->{StatusSearch} . "\n" . $plugin->getName);
                
            my $progress = new Gtk2::ProgressBar;
            $dialog->vbox->pack_start($progress,1,1,10);
            $progress->set_pulse_step(0.05);
            $progress->show_all;
            my $pulseTimeout = Glib::Timeout->add(50 , sub {
                return 0 if $getInfo;
                $progress->pulse;
                return 1;
            });    
                
            my $watch = Glib::IO->add_watch(fileno($self->{searchJob}->{data}),
                                'in',
                                sub {
                                    return if !$dialog;
                                    $dialog->response('cancel');
                                    $getInfo = 1;
                                    return 0;
                                });

            $dialog->set_position('center-on-parent');
            $dialog->run if !$getInfo;
            Glib::Source->remove($watch);
            Glib::Source->remove($pulseTimeout);
            $dialog->destroy;
            my $command = $self->{searchJob}->{command};
            if ($getInfo)
            {
                $plugin = fd_retrieve($self->{searchJob}->{data});
                print $command "OK\n";
            }
            else
            {
                print $command "STOP\n";
                return;
            }
        }
            
		my $movieNumber = $plugin->getMoviesNumber();
	
		if ($movieNumber == 0)
		{
		    my $force = 0;
		    my $idx = 0;
		    if (!$forceask && ($self->{options}->plugin eq 'multi')
		     && (($currentPlugin + 1) < $self->getDialog('MultiSite')->getPluginsNumber))
		    {
		      $idx = $currentPlugin + 1;
		    }
		    else
		    {
		      my  $dialog = Gtk2::MessageDialog->new($self,
							   [qw/modal destroy-with-parent/],
							   'error',
							   'yes-no',
							   $self->{lang}->{NoMovieFound});

              $dialog->set_position('center-on-parent');
		      my $response = $dialog->run;
		      $dialog->destroy;
		      return if $response ne 'yes';
		      $force = 1;
		    }
		    
            $self->searchMovie($title,$force, $idx);
		}
		elsif ($movieNumber == 1)
		{
		    $self->getMovieInfo($plugin, 0);
		}
		else
		{
		    my $withNext = 0;
            $withNext = 1 if ($self->{options}->plugin eq 'multi')
		        && (($currentPlugin + 1) < $self->getDialog('MultiSite')->getPluginsNumber);
		    
		    my @movies = $plugin->getMovies();
		    my $resultsDialog = $self->getDialog('Results');
            $resultsDialog->setWithNext($withNext);
            $resultsDialog->setSearchPlugin($plugin);
		    $resultsDialog->setList('', @movies);
		    my $next = $resultsDialog->show;
		    if ($resultsDialog->{validated})
		    {
				my $idx = $resultsDialog->{movieIndex};
				$self->getMovieInfo($plugin, $idx);
		    }
		    elsif ($next)
		    {
		      $self->searchMovie($title,0, $currentPlugin + 1);
		    }
		}
    }

    sub getMovieInfo
    {
        my ($self, $plugin, $idx) = @_;
        
        $plugin->{wantedIdx} = $idx;
        $plugin->{type} = 'info';
        my $info;
        
        if (! $self->{options}->searchStop)
        {
            $self->setWaitCursor($self->{lang}->{StatusGetInfo});
            $info = $plugin->getMovieInfo;
            $self->restoreCursor;
        }
        else
        {
            store_fd $plugin, $self->{searchJob}->{command};
            my $getInfo = 0;
            my $dialogGet = Gtk2::MessageDialog->new($self,
                [qw/modal destroy-with-parent/],
                'info',
                'cancel',
                $self->{lang}->{StatusGetInfo});
                
            my $progress = new Gtk2::ProgressBar;
            $dialogGet->vbox->pack_start($progress,1,1,10);
            $progress->set_pulse_step(0.05);
            $progress->show_all;
            my $pulseTimeout = Glib::Timeout->add(50 , sub {
                return 0 if $getInfo;
                $progress->pulse;
                return 1;
            });
                
            my $watch = Glib::IO->add_watch(fileno($self->{searchJob}->{data}),
                                'in',
                                sub {
                                    return if !$dialogGet;
                                    $dialogGet->response('cancel');
                                    $getInfo = 1;
                                    return 0;
                                });

            $dialogGet->set_position('center-on-parent');
            $dialogGet->run if !$getInfo;
            Glib::Source->remove($watch);
            Glib::Source->remove($pulseTimeout);
            $dialogGet->destroy;
            my $command = $self->{searchJob}->{command};
            if ($getInfo)
            {
                $info = fd_retrieve($self->{searchJob}->{data});
                print $command "OK\n";
            }
            else
            {
                print $command "STOP\n";
                return;
            }
        }

        $info->{orig} = $info->{title} if (!$info->{orig}) && ($self->{options}->alwaysOriginal);
        $info->{image} = '' if $info->{image} eq 'empty';        
        
        if ($self->{options}->askImport)
        {
            $self->getDialog('ImportFields')->info($info);
            return if ! $self->getDialog('ImportFields')->show;
            $info = $self->getDialog('ImportFields')->info;
        }
        $self->addMovie($info, 0);
    }
    
    sub getUniqueImageFileName
    {
        my ($self, $suffix, $imagesDir) = @_;
    
        $imagesDir = $self->{options}->images if ! $imagesDir;
        $imagesDir =~ s+([^/])$+$1/+;

        if ( ! -e $imagesDir)
        {
            mkdir($imagesDir);
        }

        my $filePrefix = $imagesDir.$self->{imagePrefix};
        my @tmp_filenames;
        @tmp_filenames = glob $filePrefix.'*.*';
        my $sysPrefix = $filePrefix;
        $sysPrefix =~ s/\\/\\\\/g if ($^O =~ /win32/i);
        my @numbers = sort {$b <=> $a} map {
            /$sysPrefix([0-9]*)\./ && $1;
        } @tmp_filenames;
        my $mostRecent = $numbers[0];

        my $picture = $filePrefix.$mostRecent.$suffix;

        while (-e $picture)
        {
            $mostRecent++;
            $picture = $filePrefix.$mostRecent.$suffix;
        }
        return $picture;
    }
    
    sub changeInfo
    {
        my ($self, $info) = @_;

        my @genres = split /,/, $info->{type};
        my $newGenres = '';
        
        foreach (@genres)
        {
            $newGenres .= $self->getDialog('GenresGroups')->{convertor}->convert($_).',';
        }
        $newGenres =~ s/.$//;
        
        $info->{type} = $newGenres;
    }
    
    sub addMovie
    {
        my ($self, $info, $newMovie) = @_;

        $self->{movies}->updateCurrent if $newMovie;
        
        $self->changeInfo($info);

        my $ignore = $self->{ignoreString};
        my $previous;
        
        if ($newMovie)
        {
            for my $field (@{$self->{movies}->{fields}})
            {
                $self->{panel}->$field($info->{$field});
            }
            $self->{panel}->selectTitle;
            my $id = $self->{movies}->addMovie($info);
            $self->{panel}->id($id);
        }
        else
        {
            $previous = $self->{panel}->getAsHash;
            foreach my $field(@{$self->{movies}->{fields}})
            {
                next if ($field eq 'image');
                if ((! $self->{movies}->{fieldsInfo}->{$field}->{isImported})
                 || ($info->{$field} eq $ignore))
                {
                    $info->{$field} = $previous->{$field};
                }
                else
                {
                    $self->{panel}->$field($info->{$field});
                }
            }
            
            if ($info->{image} && ($info->{image} ne $ignore))
            {
                ($info->{image}, my $picture) = $self->downloadPicture($info->{image});
                
                $self->{panel}->image($info->{image});
                $self->{movies}->markToBeAdded($picture);
                $self->restoreCursor;
                
            }
            $info->{image} = $previous->{image} if $info->{image} eq $ignore;
            
            $self->{movies}->updateCurrent;
            $self->{moviesList}->changeCurrent($previous, $info) if ($self->{panel}->{autoUpdate});
            $self->{moviesList}->showCurrent;
        }
    }
    
    sub downloadPicture
    {
        my ($self, $pictureURL) = @_;
    
        $self->setWaitCursor($self->{lang}->{StatusGetImage});
        my $browser = LWP::UserAgent->new;
        $browser->proxy(['http'], $self->{options}->proxy);
        $browser->agent($self->{agent});
  
        my ($name,$path,$suffix) = fileparse($pictureURL, "\.gif", "\.jpg", "\.jpeg", "\.png");
        my $picture = $self->getUniqueImageFileName($suffix);

        $browser->get($pictureURL, ':content_file' => $picture);
        $self->restoreCursor;
            
        return ($self->transformPicturePath($picture), $picture);
    }

    sub transformPicturePath
    {
        my ($self, $path, $file) = @_;
        
        $file = $self->{options}->file if !$file;
        my $dir = undef;
        $dir = dirname($file) if $file;
        if (File::Spec->file_name_is_absolute($path))
        {
            return $path if !$self->{options}->useRelativePaths;
        }
        else
        {
            return $path if $self->{options}->useRelativePaths;
        }
        return File::Spec->rel2abs($path,$dir) if !$self->{options}->useRelativePaths;
        return File::Spec->abs2rel($path,$dir);
    }

    sub addFileHistory
    {
        my ($self, $filename) = @_;
        (my $history = $self->{options}->history) =~ s/\|?\Q$filename\E\|?/|/;
        $history =~ s/(.*?)\|[^\|]*?$/$filename\|$1/ if $history !~ /^$filename/;
        $self->{options}->history($history);
        $self->{menubar}->{menuHistoryItem}->remove_submenu();
        $self->{menubar}->{menuHistory} = Gtk2::Menu->new();
        $self->{menubar}->addHistoryMenu();
    }
    
    sub openMovie
    {
        my ($self, $filename) = @_;
        $self->saveList if ($self->{options}->autosave) && ($self->{movies}->{nbMovies});
        
        $self->addFileHistory($filename);
        $self->{options}->file($filename);
        $self->{options}->save;
        $self->{movies}->load($self->{options}->file, $self, 1);
        foreach(@{$self->{movies}->{fieldsHistory}})
        {
            $self->{panel}->setHistory($_, $self->{movies}->getHistory($_));
        }
        $self->{movies}->display($self->{movies}->select(0));
        $self->set_title('GCfilms - ['.basename($filename).']');			
    }

    sub openList
    {
        my $self = shift;
        my $fileDialog = new GCFileChooserDialog($self->{lang}->{OpenList}, $self, 'open', 1);
        $fileDialog->set_pattern_filter(['GCfilms (.gcf)', '*.gcf']);

        $fileDialog->set_filename($self->{options}->file);
        my $response = $fileDialog->run;
        if ($response eq 'ok')
        {
            my $fileName = $fileDialog->get_filename;
            $fileDialog->destroy;
            $self->openMovie($fileName);
        }
        else
        {
            $fileDialog->destroy;
        }
    }

    sub newList
    {
        my $self = shift;

        $self->saveList if ($self->{options}->autosave) && ($self->{movies}->{nbMovies});

        $self->{movies}->clearList;
        $self->{options}->file('');
        $self->set_title('GCfilms - []');
    }

    sub saveAs
    {
        my $self = shift;
        my $fileDialog = new GCFileChooserDialog($self->{lang}->{SaveList}, $self, 'save', 1, 1);
        $fileDialog->set_pattern_filter(['GCfilms (.gcf)', '*.gcf']);
        $fileDialog->set_filename($self->{options}->file);
            
        while (1)
        {
    	   	my $response = $fileDialog->run;
            if ($response eq 'ok')
            {
                my $filename = $fileDialog->get_filename;
                $self->addFileHistory($filename);
                my $previousFile = $self->{options}->file;
                $self->{options}->file($filename);
                if ($self->saveList())
                {
                    $self->{options}->save;
                    $self->set_title('GCfilms - ['.basename($filename).']');
                    last;
                }
                else
                {
                    $self->{options}->file($previousFile);
                }            
    		}
    		last if ($response ne 'ok')
        }
        $fileDialog->destroy;
    } 

    sub saveList
    {
        my ($self, $self2) = @_;
        $self = $self2 if $self2;
				my $response = 'yes';

        if ($self->{options}->file)
        {
            return $self->{movies}->save;
        }
        else
        {
	       my $dialog = Gtk2::MessageDialog->new($self,
                                                  [qw/modal destroy-with-parent/],
                                                  'info',
                                                  'yes-no',
                                                  $self->{lang}->{SaveCurrentList});

           $dialog->set_position('center-on-parent');
	       $response = $dialog->run();
	       $dialog->destroy ;
		   $self->saveAs if ($response eq 'yes');
        }
    }

    sub removeSearch
    {
        my $self = shift;
        
        $self->setFilter('search', 'all');
    }
    
    sub search
    {
        my ($self, $self2, $value) = @_;
        $self = $self2 if ($self2 ne 'all') && ($self2 ne 'displayed');
        my $type = 'all';
        $type = $value if ($self != $self2);

        $self->getDialog('Search')->show;
        
        my $info = $self->getDialog('Search')->search;
        return if ! $info;
        
        $self->{menubar}->selectAll if $type eq 'all';
        $self->setFilter('search', $info);
    }
    
    sub showBorrowed
    {
        my $self = shift;
        $self->{movies}->updateCurrent;
        $self->getDialog('Borrowed')->setList($self->{movies}->{movieArray});
        $self->getDialog('Borrowed')->show;
    }
    
    sub export
    {
        my ($self, $exporter) = @_;
        $self->getDialog('Export')->setModule($exporter);
        $self->getDialog('Export')->show;
    }

    sub import
    {
        my ($self, $importer) = @_;
        $self->getDialog('Import')->setModule($importer);
        $self->getDialog('Import')->show;
    }

    sub importWithDetect
    {
        my ($self, $file) = @_;
  
        $file =~ s/^file:\/\/\/?(.*)\W*$/$1/;
        $file =~ s/.$//ms;
        #(my $suffix = $file) =~ s/.*\.(\w+)\W*$/$1/;
        
        foreach my $importer(@GCImport::importersArray)
        {
            my $current = $importer->getSuffix;
            next if !$current;
            #if ($current eq $suffix)
            if ($file =~ /$current$/)
            {
                $self->setWaitCursor($self->{lang}->{StatusGetInfo});
                my %options;
                $options{parent} = $self;
                $options{newList} = 0;
                $options{file} = $file;
                $options{lang} = $self->{lang};
                $importer->process(\%options);
                $self->restoreCursor;
                return 1;
            }
        }
        return 0;
    }

    sub optionsError
    {
        my ($self, $type) = shift;

        my $msg;
        if ($type eq 'open')
        {
            $msg = $self->{lang}->{OptionsOpenError};
        }
        elsif ($type eq 'create')
        {
            $msg = $self->{lang}->{OptionsCreateError};
        }
        else
        {
            $msg = $self->{lang}->{OptionsSaveError};
        }
            
        my $dialog = Gtk2::MessageDialog->new($self,
                                              [qw/modal destroy-with-parent/],
                                              'error',
                                              'ok',
                                              $msg.$self->{options}->{file});

        $dialog->set_position('center-on-parent');
        $dialog->run();
        $dialog->destroy ;

        $self->destroy;
    }

    sub checkImagesDirectory
    {
        my ($self, $withDialog) = @_;
        my $error = 0;
        if ( ! -e $self->{options}->images)
        {
            $! = '';
            $error = 1 if (!mkdir($self->{options}->images));
            rmdir $self->{options}->images if ! $!;
        }
        else
        {
            $error = 1 if !( -d _ && -r _ && -w _ && -x _ )
        }

        return $error if !$withDialog;

        if ($error)
        {
            $self->{splash}->hide;
            my $fileDialog = new GCFileChooserDialog($self->{lang}->{OptionsImagesTitle}, $self, 'select-folder');
            my  $errorDialog = Gtk2::MessageDialog->new($self,
						   [qw/modal destroy-with-parent/],
						   'error',
						   'ok',
						   $self->{lang}->{ImageError});

            $errorDialog->set_position('center-on-parent');
            $fileDialog->set_filename($self->{options}->images);
            my $response;
            do
            {
                $errorDialog->run();
                $errorDialog->hide();
                $response = '';
                $response = $fileDialog->run;
                exit 1 if $response ne 'ok';
                # while ($response ne 'ok');
                $self->{options}->images($fileDialog->get_filename);
            } while ($self->checkImagesDirectory(0));
            $errorDialog->destroy;
            $fileDialog->destroy;
            $self->{splash}->show_all;
        }
        return $error;
    }

    sub setWaitCursor
    {
		my ($self, $message) = @_;
        $self->setStatus($message);
		$self->window->set_cursor(Gtk2::Gdk::Cursor->new('watch'));
		Gtk2->main_iteration while (Gtk2->events_pending);
    }
    sub restoreCursor
    {
		my $self = shift;
        $self->restoreStatus;
		$self->window->set_cursor(Gtk2::Gdk::Cursor->new('left_ptr'));
		Gtk2->main_iteration while (Gtk2->events_pending);
    }

    sub setFilter
    {
        my ($self, $filter, $parameter) = @_;
        $self->{movies}->updateCurrent;
        $self->{movies}->setFilter($filter, $parameter);
    }

    sub onSortClick
    {
        my ($widget, $self) = @_;
        $self->{moviesList}->getSortButton()->signal_connect('clicked', \&onSortClick, $self)
            if ($self->{moviesList}->setSortOrder($self->{movies}->changeOrder));
    }

    sub getDialog
    {
        my ($self, $name) = @_;

        if ($name eq 'DisplayOptions')
        {
            $self->{DisplayOptionsDialog} = new GCDisplayOptionsDialog($self, 'displayed')
                if !$self->{DisplayOptionsDialog};
        }
        elsif ($name eq 'PluginsAsk')
        {
            $self->{PluginsAskDialog} = new GCPluginsDialog($self)
                if !$self->{PluginsAskDialog};
        }
        elsif ($name eq 'About')
        {
            $self->{AboutDialog} = new GCAboutDialog($self, $self->{version})
                if ! $self->{AboutDialog};
        }
        else
        {
            my $className = 'GC'.$name.'Dialog';
            $self->{$name.'Dialog'} = new $className($self)
                if ! $self->{$name.'Dialog'};
        }

        return $self->{$name.'Dialog'};
    }

    sub selectMultiPluginsList
    {
        my $self = shift;
        
        $self->getDialog('MultiSite')->show;
    }

    sub options
    {
        my ($self, $self2) = @_;
        $self = $self2 if $self2;

        my $transform = $self->{options}->transform;
        my $articles = $self->{options}->articles;
        my $formats = $self->{options}->formats;
        my $order = $self->{options}->order;
        my $status = $self->{options}->status;
        my $toolbar = $self->{options}->toolbar;
        my $toolbarPosition = $self->{options}->toolbarPosition;

        $self->getDialog('Options')->show;

        $self->checkTransform
            if ($self->{options}->articles ne $articles) || ($self->{options}->transform != $transform);
            
        $self->checkFormats
            if (($self->{options}->formats ne $formats)
             && ($self->{options}->order eq $order));

        $self->changePanel
            if ($self->{options}->order ne $order);
       
        $self->checkDisplayed
            if ($self->{options}->status ne $status) || ($self->{options}->toolbar ne $toolbar);

        $self->checkToolbarPosition
            if ($self->{options}->toolbarPosition ne $toolbarPosition);
            
        $self->checkPlugin;
        $self->checkView;
    }
    
    sub displayOptions
    {
        my ($self, $self2) = @_;
        $self = $self2 if $self2;

        my $displayed = $self->{options}->displayed;
        $self->getDialog('DisplayOptions')->show;
        $self->checkPanel
            if ($self->{options}->displayed ne $displayed);
    }

    sub borrowers
    {
        my ($self, $self2) = @_;
        $self = $self2 if $self2;

        $self->getDialog('Borrowers')->show;
        $self->checkBorrowers;
    }

    sub genresConversion
    {
        my ($self, $self2) = @_;
        $self = $self2 if $self2;

        $self->getDialog('GenresGroups')->show;
    }
    
    sub rename
    {
        my ($self, $self2) = @_;
        $self = $self2 if $self2;

        $self->getDialog('Rename')->show;
        
        my ($old, $new) = $self->getDialog('Rename')->names;
        return if ! $old;
        $self->{movies}->rename($old,$new);
    }

    sub about
    {
        my $self = shift;
        
        $self->getDialog('About')->show;
    }

    sub showDependencies
    {
        my $self = shift;
        
        $self->getDialog('Dependencies')->show;
    }

    sub help
    {
        my ($self, $self2) = @_;
        $self = $self2 if $self2;

        $self->openUrl('http://home.gna.org/gcfilms/doc');
    }

    sub openUrl
    {
        my ($self, $url) = @_;

        return if !$url;

        my $command = $self->{options}->browser.' "'.$url.'"';
        if ($^O =~ /win32/i)
        {
            system "start $command";
        }
        else
        {
            #$command =~ s/&/\\&/g;
            system "$command &";
        }
    }

    sub extractInfo
    {
        my ($self, $file, $panel) = @_;
        
        my $infoExtractor = new GCVideoInfo($file);
        $self->getDialog('Extract')->setInfo($infoExtractor->getInfo, $panel);
        $self->getDialog('Extract')->show;
    }

    sub playTrailer
    {
        my ($self, $url) = @_;

        $url = $self->{panel}->trailer
            if $url == undef;
        return if !$url;

        my $command = $self->{options}->player.' "'.$url.'"';
        if ($^O =~ /win32/i)
        {
            system "start $command";
        }
        else
        {
            system "$command &";
        }
    }

    sub enablePlay
    {
        my ($self, $enable) = @_;

        $self->{toolbar}->{play}->set_sensitive($enable);
        $self->{menubar}->{play}->set_sensitive($enable);
        $self->{panel}->{trailerExtract}->set_sensitive($enable)
            if $self->{panel}->{trailerExtract};
    }
    
    sub showPlay
    {
        my ($self, $show) = @_;

        if ($show)
        {
            $self->{toolbar}->{play}->show;
            $self->{menubar}->{play}->show;
            $self->{menubar}->{playSeparator}->show;
        }
        else
        {
            $self->{toolbar}->{play}->hide;
            $self->{menubar}->{play}->hide;
            $self->{menubar}->{playSeparator}->hide;
        }
    }

    sub setStatus
    {
		my ($self, $status) = @_;
		$self->{status}->push(1, $status) if ($self->{status});
    }
    
    sub restoreStatus
    {
        my $self = shift;
        
        $self->{status}->pop(1);
    }

    sub display
    {
        my ($self, $idx) = @_;
        $self->{movies}->display($idx);
    }
    
    sub displayInWindow
     {
        my ($self, $idx, $random) = @_;

        my $title = $self->{movies}->{movieArray}[$idx]->{title};
        $title = $self->{movies}->currentTitle if $idx == undef;

        my $window;
        if ($random)
        {
	        $window = new GCRandomMovieWindow($self, $title);
        }
        else
        {
	        $window = new GCMovieWindow($self, $title);			
        }

        if ($self->{previousWindowPosition})
        {
            $window->move($self->{previousWindowPosition}->{x},
                          $self->{previousWindowPosition}->{y});
        }

        my @borrowers = split m/\|/, $self->{options}->borrowers;
        $window->{panel}->setBorrowers(\@borrowers);
        $window->{panel}->disableBorrowerChange;

        $self->{movies}->displayInPanel($window->{panel}, $idx);
        
        my $code = $window->show;

        if (!$random && ($code eq 'ok'))
        {
            my $previous = $self->{panel}->getAsHash;
            my $new = $window->{panel}->getAsHash;
            $self->{movies}->updateCurrentFromPanel($window->{panel});
            $self->{movies}->displayInPanel($self->{panel}, $idx);
            $self->{moviesList}->changeCurrent($previous, $new);
        }

        my ($width, $height) = $window->get_size;
        $self->{options}->movieWindowWidth($width);
        $self->{options}->movieWindowHeight($height);

        ($self->{previousWindowPosition}->{x}, $self->{previousWindowPosition}->{y})
            = $window->get_position;

        $window->destroy;
        
        return $code;

    }
   
    sub randomMovie
    {
        my ($self) = @_;
        my @tmpArray = undef;
        $self->{movies}->updateCurrent;
        
        my $message = '';
        
        #Initialize movies array.
        $self->{randomPool} = [];
        my $realId = 0;
        foreach (@{$self->{movies}->{movieArray}})
        {
            if (!$_->{seen})
            {
                $_->{realId} = $realId;
                push @{$self->{randomPool}}, $_;
            }
            $realId++;
        }
 
        if (scalar @{$self->{randomPool}} > 0)
        {
            my $code = 'no';
            my $idx = 0;
            while ($code eq 'no')
            {
        	   $idx = int rand(scalar @{$self->{randomPool}});
        	   $realId = $self->{randomPool}->[$idx]->{realId};
        	   $code = $self->displayInWindow($realId, 1);
        	   splice @{$self->{randomPool}}, $idx, 1;
        	   last if ! @{$self->{randomPool}};
            }
            $message = $self->{lang}->{RandomEnd} if $code eq 'no';
            if ($code eq 'ok')
            {
                $self->{movies}->{movieArray}[$realId]->{seen} = 1;
                $self->{panel}->seen(1)
                    if $self->{movies}->{currentMovie} == $realId;
            }
        }
    	else
    	{
    	   $message = $self->{lang}->{RandomError};
    	}

        if ($message)
        {
            my $dialog = Gtk2::MessageDialog->new($self->{parent},
    		  	                                 [qw/modal destroy-with-parent/],
                                                'info',
                                                  'ok',
                                                  $message);
            $dialog->set_position('center-on-parent');
    		$dialog->run();
	       	$dialog->destroy;
        }
        
        #Clean movies array.
        foreach (@{$self->{movies}->{movieArray}})
        {
            delete $_->{realId};
        }
    }
    
    sub initProgress
    {
        my $self = shift;
 
        $self->setProgress(0.0);
        $self->set_sensitive(0);
    }
    
    sub endProgress
    {
        my $self = shift;
        $self->setProgress(1.0);
        Glib::Timeout->add(500 , sub {
            $self->setProgress(0.0);
            return 0;
        });
        $self->set_sensitive(1);
    }
    
    sub setProgress
    {
        my ($self, $current) = @_;
        $self->{progress}->set_fraction($current);
        Gtk2->main_iteration while (Gtk2->events_pending);
    }

    sub setMoviesTotal
    {
        my ($self, $total) = @_;
        $self->{step} = GCUtils::round($total / 7);
        $self->{step} = 1 if $self->{step} < 1;
        $self->{total} = $total;
    }

    sub setProgressForMoviesLoad
    {
    }

    sub setProgressForMoviesDisplay
    {
        my ($self, $current) = @_;
        return if ($current % $self->{step});
        if ($self->{total})
        {
            my $value = $current / $self->{total};
            $value = 1.0 if $value > 1;
            $self->{progress}->set_fraction($value);
        }
        else
        {
            $self->{progress}->set_fraction(0.5);
        }
        Gtk2->main_iteration while (Gtk2->events_pending);
    }

    sub blockListUpdates
    {
        my ($self, $value) = @_;
        
        $self->{movies}->{block} = $value;
    }

    sub reloadList
    {
        my $self = shift;
        $self->{movies}->reloadList($self, 1);
    }

    sub setMoviesList
    {
        my ($self, $view, $columns, $init) = @_;
        $self->{pane}->remove($self->{moviesList}) if $self->{pane} && $self->{moviesList};
        $self->{moviesList}->destroy if $self->{moviesList};
        
        $self->{moviesList} = new GCTextList($self, $self->{lang}->{Movies}) if $view == 0;
        $self->{moviesList} = new GCImageList($self, $self->{lang}->{Movies}, $columns) if $view == 1;
        $self->{moviesList} = new GCDetailedList($self, $self->{lang}->{Movies}) if $view == 2;

        $self->{pane}->pack1($self->{moviesList},1,0) if $self->{pane};
        $self->{moviesList}->show_all;
        if ($self->{movies})
        {
            $self->{movies}->resetSortField if $view <= 1;
            $self->{movies}->restoreSort if $view == 2;
            $self->reloadList if ! $self->{initializing};
            Glib::Timeout->add(100 ,\&showCurrent, $self);
            $self->{moviesList}->setSortOrder;
        }

        #Change corresponding item in context menu        
        $self->{ignoreContextActivation} = 1;
        $self->{context}->{menuDisplayType}->set_active($view + 1);
        $self->{context}->{menuDisplayType}->get_active->set_active(1);
        $self->{ignoreContextActivation} = 0;
        #Assign context menu to movies list that will be in charge of displaying it.
        $self->{moviesList}->{context} = $self->{context};
    }
    
    sub createContextMenu
    {
        my $self = shift;
      
        # Context menu creation. It is displayed when right clicking on a list item.
        $self->{context} = new Gtk2::Menu;
        
        $self->{context}->append(Gtk2::TearoffMenuItem->new());
        
        my $itemDuplicate = Gtk2::ImageMenuItem->new_from_stock('gtk-dnd',undef);
        $itemDuplicate->signal_connect("activate" , sub {
            $self->duplicateMovie;
        });
        $self->{context}->append($itemDuplicate);

        my $itemDelete = Gtk2::ImageMenuItem->new_from_stock('gtk-delete',undef);
        $itemDelete->signal_connect("activate" , sub {
            $self->deleteCurrentMovie;
        });
        $self->{context}->append($itemDelete);
        
        my $newWindow = Gtk2::MenuItem->new_with_mnemonic($self->{lang}->{MenuNewWindow});
        $newWindow->signal_connect("activate" , sub {
                $self->displayInWindow;
        });
        $self->{context}->append($newWindow);
        
        $self->{context}->append(Gtk2::SeparatorMenuItem->new);
        
        $self->{context}->{menuDisplayType} = new Gtk2::Menu;
        $self->{context}->{menuDisplayType}->append(Gtk2::TearoffMenuItem->new());
        my %views = %{$self->{lang}->{OptionsViews}};
        my $displayGroup = undef;
		foreach (0..(scalar(keys %views) - 1))
		{
		    my $item = Gtk2::RadioMenuItem->new_with_mnemonic($displayGroup, $views{$_});
		    $item->signal_connect('activate', sub {
		        my ($widget, $self) = @_;
		        return if ($self->{ignoreContextActivation});
                if ($widget->get_active)
                {
                    my $group = $widget->get_group;
                    my $i = 0;
                    $i++ while ($views{$i} ne $widget->child->get_label);
                    $self->{options}->view($i);
	                $self->setMoviesList($self->{options}->view,
                                         $self->{options}->columns)
                        if ! $self->{initializing};
                    $self->checkView;
                    
                }
		    }, $self);
		    $self->{context}->{menuDisplayType}->append($item);
		    $displayGroup = $item->get_group;
		}
		
        $self->{context}->{itemDisplayType} = Gtk2::MenuItem->new_with_mnemonic($self->{lang}->{OptionsView});
        $self->{context}->{itemDisplayType}->set_submenu($self->{context}->{menuDisplayType});
        $self->{context}->append($self->{context}->{itemDisplayType});
        
        $self->{context}->append(Gtk2::SeparatorMenuItem->new);
        
        # Filters selection
                
        my $menuDisplay = Gtk2::Menu->new();
        my $displayItem = Gtk2::MenuItem->new_with_mnemonic($self->{lang}->{MenuDisplay});
        
        my $allMovies = Gtk2::MenuItem->new_with_mnemonic($self->{lang}->{MenuViewAllMovies});
        $allMovies->signal_connect("activate" , sub {
                $self->{menubar}->selectAll;
        });
        $menuDisplay->append($allMovies);
        
        #my $searchSelectedMovies = Gtk2::MenuItem->new_with_mnemonic($self->{lang}->{MenuSearchSelectedMovies});
        my $searchSelectedMovies = Gtk2::ImageMenuItem->new_from_stock('gtk-find',undef);
        $searchSelectedMovies->signal_connect("activate" , sub {
                $self->search('displayed');
        });
        $menuDisplay->append($searchSelectedMovies);
        
        $menuDisplay->append(Gtk2::SeparatorMenuItem->new);
        
        $self->{contextMenuSeen} = Gtk2::Menu->new();
        my $allSeen = Gtk2::RadioMenuItem->new_with_mnemonic(undef,$self->{lang}->{MenuAllMovies});
        $self->{contextMenuSeen}->append($allSeen);
        $allSeen->signal_connect("activate", sub {
            $self->contextDisplayChange(shift, 'menuSeen', 0);
        });
        my $seenGroup = $allSeen->get_group();
        my $notseen = Gtk2::RadioMenuItem->new_with_mnemonic($seenGroup,$self->{lang}->{MenuNotSeen});
        $self->{contextMenuSeen}->append($notseen);
        $notseen->signal_connect("activate", sub {
            $self->contextDisplayChange(shift, 'menuSeen', 1);
        });
        my $seenItem = Gtk2::MenuItem->new_with_mnemonic($self->{lang}->{MenuSeenOrNot});
        $seenItem->set_submenu($self->{contextMenuSeen});
        $menuDisplay->append($seenItem);

        $self->{contextMenuBorrowing} = Gtk2::Menu->new();
        my $allBorrowed = Gtk2::RadioMenuItem->new_with_mnemonic(undef,$self->{lang}->{MenuAllMovies});
        $self->{contextMenuBorrowing}->append($allBorrowed);
        $allBorrowed->signal_connect("activate", sub {
            $self->contextDisplayChange(shift, 'menuBorrowing', 0);
        });
        my $borrowedGroup = $allBorrowed->get_group();
        my $notBorrowed = Gtk2::RadioMenuItem->new_with_mnemonic($borrowedGroup,$self->{lang}->{MenuNotBorrowed});
        $self->{contextMenuBorrowing}->append($notBorrowed);
        $notBorrowed->signal_connect("activate", sub {
            $self->contextDisplayChange(shift, 'menuBorrowing', 1);
        });
        my $isBorrowed = Gtk2::RadioMenuItem->new_with_mnemonic($borrowedGroup,$self->{lang}->{MenuBorrowed});
        $self->{contextMenuBorrowing}->append($isBorrowed);
        $isBorrowed->signal_connect("activate", sub {
            $self->contextDisplayChange(shift, 'menuBorrowing', 2);
        });
        my $borrowedItem = Gtk2::MenuItem->new_with_mnemonic($self->{lang}->{MenuBorrowing});
        $borrowedItem->set_submenu($self->{contextMenuBorrowing});
        $menuDisplay->append($borrowedItem);

        $self->{contextMenuCategories} = Gtk2::Menu->new();
        my $allCat = Gtk2::RadioMenuItem->new_with_mnemonic(undef,$self->{lang}->{MenuAllCategories});
        $self->{contextMenuCategories}->append($allCat);
        $allCat->signal_connect("activate", sub {
            $self->contextDisplayChange(shift, 'menuCategories', 0);
        });
        my $catGroup = $allCat->get_group();
        my $catitem = Gtk2::MenuItem->new_with_mnemonic($self->{lang}->{MenuCategories});
        $catitem->set_submenu($self->{contextMenuCategories});
        $menuDisplay->append($catitem);
        $self->{contextMenuCategories}->{group} = $catGroup;
        $self->{context}->{menuCategories} = $self->{contextMenuCategories};

        $self->{contextMenuAge} = Gtk2::Menu->new();
        my $allMoviesAge = Gtk2::RadioMenuItem->new_with_mnemonic(undef,$self->{lang}->{MenuAllMovies});
        $self->{contextMenuAge}->append($allMoviesAge);
        $allMoviesAge->signal_connect("activate", sub {
            $self->contextDisplayChange(shift, 'menuAge', 0);
        });
        my $ageGroup = $allMoviesAge->get_group();
        my $noneAge = Gtk2::RadioMenuItem->new_with_mnemonic($ageGroup,$self->{lang}->{MenuAgeNone});
        $self->{contextMenuAge}->append($noneAge);
        $noneAge->signal_connect("activate" , sub {
            $self->contextDisplayChange(shift, 'menuAge', 1);
        });
        my $parentAge = Gtk2::RadioMenuItem->new_with_mnemonic($ageGroup,$self->{lang}->{MenuAgeParent});
        $self->{contextMenuAge}->append($parentAge);
        $parentAge->signal_connect("activate" , sub {
            $self->contextDisplayChange(shift, 'menuAge', 2);
        });
        my $chooseAge = Gtk2::RadioMenuItem->new_with_mnemonic($ageGroup,$self->{lang}->{MenuAgeLess});
        $self->{contextMenuAge}->append($chooseAge);
        $chooseAge->signal_connect("activate" , sub {
            $self->contextDisplayChange(shift, 'menuAge', 3);
        });
        my $ageItem = Gtk2::MenuItem->new_with_mnemonic($self->{lang}->{MenuAge});
        $ageItem->set_submenu($self->{contextMenuAge});
        $menuDisplay->append($ageItem);

        $self->{contextMenuRating} = Gtk2::Menu->new();
        my $allRating = Gtk2::RadioMenuItem->new_with_mnemonic(undef,$self->{lang}->{MenuAllRating});
        $self->{contextMenuRating}->append($allRating);
        $allRating->signal_connect("activate", sub {
            $self->contextDisplayChange(shift, 'menuRating', 0);
        });
        my $ratingGroup = $allRating->get_group();
        my $chooseRating = Gtk2::RadioMenuItem->new_with_mnemonic($ratingGroup,$self->{lang}->{MenuChooseRating});
        $self->{contextMenuRating}->append($chooseRating);
        $chooseRating->signal_connect("activate" , sub {
            $self->contextDisplayChange(shift, 'menuRating', 1);
        });
        my $ratingItem = Gtk2::MenuItem->new_with_mnemonic($self->{lang}->{MenuRating});
        $ratingItem->set_submenu($self->{contextMenuRating});
        $menuDisplay->append($ratingItem);
        
        $displayItem->set_submenu($menuDisplay);
        $self->{context}->append($displayItem);
        
        $self->{context}->show_all;
      
    }
    
    sub contextDisplayChange
    {
        my ($self, $widget, $menuName, $number) = @_;
        
        return if $widget && ! $widget->get_active;
        return if $self->{menubar}->{contextUpdating};

        $self->{menubar}->{contextUpdating} = 1;
        $self->{menubar}->{$menuName}->set_active($number);
        $self->{menubar}->{$menuName}->get_active->activate;
        $self->{menubar}->{contextUpdating} = 0;
    }
    
    sub showCurrent
    {
        my $self = shift;
        $self->{moviesList}->showCurrent;
    }
    
    sub allMovies
    {
        my ($self, $self2) = @_;
        $self = $self2 if $self2;

        $self->{menubar}->selectAll;        
    }
    
    sub transformTitle
    {
        my ($self, $title) = @_;

        return $title if ! $self->{options}->transform;
        
        return $title if $title !~ /^($self->{articlesRegexp})(\s+|('))(.*)/i;
        #'
        return ucfirst($4)." ($1$3)";
    }
    
    sub new
    {
        my ($proto, $options, $version, $searchJob) = @_;
        my $class = ref($proto) || $proto;
        my $self  = $class->SUPER::new('toplevel');
        bless ($self, $class);

        $options->setParent($self);
        $self->{options} = $options;
        $self->{version} = $version;
        $self->{searchJob} = $searchJob;
        
        $self->{logosDir} = $ENV{GCF_SHARE_DIR}.'/logos/';
        $self->{hasPictures} = (-f $self->{logosDir}.'splash.png');
        $self->{pluginsPicturesDir} = $ENV{GCF_SHARE_DIR}.'/plugins/';
        $self->{hasPluginsPictures} = 0;
        if (-d $self->{pluginsPicturesDir})
        {
            my @pics = glob($self->{pluginsPicturesDir}.'/*.png');
            $self->{hasPluginsPictures} = 1 if $#pics > 0;
        }

        $self->{lang} = $GCLang::langs{$self->{options}->lang};
        GCLang::addGeneratedStrings($self->{lang}, $self->{hasPictures});

        if (! $options->exists('style'))
        {
            $options->style('Gtk')     if ($^O !~ /win32/i);
            $options->style('GCfilms') if ($^O =~ /win32/i);
        }
        GCStyle::initStyles;
        my $style = $GCStyle::styles{$options->style};
        
        if ((! $options->exists('movieWindowWidth'))
         || (! $options->exists('movieWindowHeight')))
        {
            $options->movieWindowWidth(600);
            $options->movieWindowHeight(500);
        }

        $self->{style} = $style;
        
        $self->{initializing} = 1;
        $self->set_sensitive(0);

        if (($self->{options}->splash) || (! $self->{options}->exists('splash')))
        {
            $self->{splash} = new GCSplashWindow($self, $self->{version});
        }
        else
        {            
            $self->init;
            $self->loadPrevious;
            $self->initEnd;
            $self->{initializing} = 0;
            $self->set_sensitive(1);
        }

        return $self;
    }

    sub createStockItems
    {
        my $self = shift;
        
        my $baseStock;
        $baseStock->{translation_domain} = 'gtk20';
        $baseStock->{keyval} = 0;
        $baseStock->{modifier} = [  ];
        
        $baseStock->{stock_id} = 'gtk-execute';
        $baseStock->{label} = $self->{lang}->{ToolbarRandom};                
        Gtk2::Stock->add($baseStock);
        
        $baseStock->{stock_id} = 'gtk-refresh';
        $baseStock->{label} = $self->{lang}->{ToolbarAll};
        Gtk2::Stock->add($baseStock);
        
        $baseStock->{stock_id} = 'gtk-convert';
        $baseStock->{label} = $self->{lang}->{MenuImport};
        Gtk2::Stock->add($baseStock);
        
        $baseStock->{stock_id} = 'gtk-revert-to-saved';
        $baseStock->{label} = $self->{lang}->{MenuExport};
        Gtk2::Stock->add($baseStock);

        $baseStock->{stock_id} = 'gtk-dnd';
        $baseStock->{label} = $self->{lang}->{MenuDuplicate};
        Gtk2::Stock->add($baseStock);

        $baseStock->{stock_id} = 'gtk-jump-to';
        $baseStock->{label} = $self->{lang}->{PanelSearchButton};
        Gtk2::Stock->add($baseStock);

        $baseStock->{stock_id} = 'gtk-about';
        $baseStock->{label} = $self->{lang}->{AboutTitle};
        Gtk2::Stock->add($baseStock);
        
        my $addStock = Gtk2::Stock->lookup('gtk-add');
        $addStock->{keyval} = 65;
        $addStock->{modifier} = [ 'control-mask' ];
        Gtk2::Stock->add($addStock);
    }

    sub init
    {
        my $self = shift;
        my $splash = shift;

        $self->checkImagesDirectory(1);
        $self->{options}->save;
        
        $self->createStockItems;
        #GCPlugins::loadPlugins;

        $splash->setProgress(0.01) if $splash;

        Gtk2::Rc->parse($self->{style}->{rcFile});
        
        $self->{agent} = 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041111 Firefox/1.0';
        $self->{ignoreString} = 'gcf_000_ignore';
        $self->{imagePrefix} = 'gcfilms_';
        if (-f $self->{logosDir}.'no.png')
        {
            $self->{defaultImage} = $self->{logosDir}.'no.png';
        }
        else
        {
            $self->{defaultImage} = $ENV{GCF_SHARE_DIR}.'/no.jpg';
        }
        
        $self->{tooltips} = Gtk2::Tooltips->new();
        
        $self->{searchJob}->{command}->autoflush(1);
        $self->{searchJob}->{data}->autoflush(1);

        my $tmpTitle = $self->{options}->file ? basename($self->{options}->file) : '';
        $self->set_title('GCfilms - ['.$tmpTitle.']');
        my $iconPrefix = $ENV{GCF_SHARE_DIR}.'/icons/gcfilms_';
        my $pixbuf16 = Gtk2::Gdk::Pixbuf->new_from_file($iconPrefix.'16x16.png');
        my $pixbuf32 = Gtk2::Gdk::Pixbuf->new_from_file($iconPrefix.'32x32.png');
        my $pixbuf48 = Gtk2::Gdk::Pixbuf->new_from_file($iconPrefix.'48x48.png');
        my $pixbuf64 = Gtk2::Gdk::Pixbuf->new_from_file($iconPrefix.'64x64.png');
        $self->set_default_icon_list($pixbuf16, $pixbuf32, $pixbuf48, $pixbuf64);

        $self->signal_connect(delete_event => \&beforeDestroy, $self);
        $self->signal_connect(destroy => sub { Gtk2->main_quit; });
        
        #$splash->setProgress(0.02) if $splash;
        
        $self->createContextMenu;
        $self->setMoviesList($self->{options}->view, $self->{options}->columns, 1);

        $splash->setProgress(0.03) if $splash;
        
        $self->setPanel;
        
        $self->{scrollPanelMovie} = new Gtk2::ScrolledWindow;
        $self->{scrollPanelMovie}->set_policy ('automatic', 'automatic');
        $self->{scrollPanelMovie}->set_shadow_type('etched-in');
        $self->{scrollPanelMovie}->add_with_viewport($self->{panel});

        $self->{movies} = new GCMovies($self);
        $self->{movies}->setPanel($self->{panel});

        $self->{menubar} = new GCMenuBar($self);
        $self->{menubar}->set_name('GCMenubar');

        #$splash->setProgress(0.04) if $splash;

        $self->{toolbar} = GCToolBar->new($self);
        $self->{handleToolbar} = new Gtk2::HandleBox;
        
        if (-e $self->{logosDir}.'/button.png')
        {
            $self->{logoButton} = Gtk2::Button->new;
            $self->{logoButton}->set_relief('half');
            $self->{logoButton}->set_name('GCLogoButton');
            $self->{tooltips}->set_tip($self->{logoButton},
                                       $self->{lang}->{AboutTitle});
            $self->{logoButton}->signal_connect('clicked' , sub {
                $self->about;
            });
            $self->{logoOriginalPixbuf} = Gtk2::Gdk::Pixbuf->new_from_file($self->{logosDir}.'/button.png');
            $self->{logoImage} = Gtk2::Image->new;
            $self->{logoButton}->add($self->{logoImage});
        }

        $self->enablePlay(0);

        $self->{mainVbox} = new Gtk2::VBox(0, 0);
        $self->{mainHbox} = new Gtk2::HBox(0, 0);
        $self->{pane} = new Gtk2::HPaned;

        $self->{pane}->pack1($self->{moviesList},1,0);
        $self->{pane}->pack2($self->{scrollPanelMovie},1,1);
        $self->{pane}->set_position($self->{options}->split);

        $self->{mainVbox}->pack_start($self->{menubar}, 0, 0, 1);
        $self->{mainHbox}->pack_start($self->{pane},1,1,0);
        $self->{mainVbox}->pack_start($self->{mainHbox}, 1, 1, 0);

        $self->{status} = Gtk2::Statusbar->new;
        $self->{status}->set_has_resize_grip(1);
        $self->{progress} = new Gtk2::ProgressBar;
        $self->{progress}->set_size_request(100,-1);
        $self->{status}->pack_start($self->{progress}, 0, 0, 5);
        $self->{mainVbox}->pack_start($self->{status},0,0,0);

        $self->checkToolbarPosition;

        $self->add($self->{mainVbox});

        $splash->setProgress(0.05) if $splash;

        $self->set_default_size($self->{options}->width,$self->{options}->height);
       
        #$splash->setProgress(0.06) if $splash;

        $self->drag_dest_set('all', ['copy','private','default','move','link','ask']);

        $self->signal_connect(drag_data_received => \&drop_handler);

        my $target_list = Gtk2::TargetList->new();
        my $atom1 = Gtk2::Gdk::Atom->new('text/uri-list');
        my $atom2 = Gtk2::Gdk::Atom->new('text/plain');
        $target_list->add($atom1, 0, 0);
        $target_list->add($atom2, 0, 0);
        if ($^O =~ /win32/i)
        {
            my $atom3 = Gtk2::Gdk::Atom->new('DROPFILES_DND');
            $target_list->add($atom3, 0, 0);
        }
        
        $self->drag_dest_set_target_list($target_list);

        sub drop_handler {
            my ($widget, $context, $widget_x, $widget_y, $data, $info,$time) = @_;
            my $type = $data->type->name;
            if (($type eq 'text/uri-list')
             || ($type eq 'DROPFILES_DND'))
            {
                my @files = split /\n/, $data->data;
                my $numbers = scalar @files;
                $numbers-- if ($files[$#files] =~ /^\W*$/);
                if (($numbers == 1)
                 && ($files[0] =~ /\.gcf.?$/))
                {
                    #Special case when only one .gcf file is dropped
                    (my $fileName = $files[0]) =~ s/^file:\/\/\/?(.*)\W*$/$1/;
                    $fileName =~ s/.$//ms;
                    $self->openMovie($fileName);
                }
                else
                {
                    my $fileName = $self->{options}->file;
                    $self->newList;
                    foreach (@files)
                    {
                        if (!$self->importWithDetect($_))
                        {
                            my $dialog = Gtk2::MessageDialog->new($self,
							    [qw/modal destroy-with-parent/],
							    'error',
							    'ok',
							    $self->{lang}->{ImportDropError});

                            $dialog->set_position('center-on-parent');
                            my $response = $dialog->run;
                            $dialog->destroy;

                            $self->openMovie($fileName);
                            last;
                        }
                    }
                    $self->{movies}->setStatus;
                }
            }
            elsif ((my $url = $data->data) =~ m/^http:\/\//)
            {
                $self->loadUrl($url);
            }
        }

        $splash->setProgress(0.07) if $splash;
        
        $self->show_all;

        #$splash->setProgress(0.08) if $splash;

        $self->checkDisplayed;
        $self->checkPlugin;
        $self->checkBorrowers;
        $self->checkView;
        $self->checkTransform;
        $self->checkPanel;
        
        $splash->setProgress(0.09) if $splash;
        
        $self->{options}->searchStop(0) if ($^O =~ /win32/i);

    }

    sub setPanel
    {
        my $self = shift;

        $self->{options}->expandLang(1) if !$self->{options}->exists('expandLang');

        if ($self->{options}->order >= 3)
        {
            #Read Only or Web Site layout
            $self->{panel} = new GCReadOnlyPanel($self, $self->{options});
        }
        else
        {
            #Tabs, All In One or Compact layout
            $self->{panel} = new GCFormPanel($self, $self->{options}, 0);
        }
    }

    sub changePanel
    {
        my $self = shift;
        
        $self->{options}->expandLang($self->{panel}->{expanderLang}->get_expanded ? 1 : 0)
            if ($self->{panel}->{expanderLang});
        $self->{movies}->updateCurrent;
        $self->{scrollPanelMovie}->remove($self->{scrollPanelMovie}->get_child);
        $self->{panel}->destroy;
        $self->{pane}->remove($self->{scrollPanelMovie});
        $self->{scrollPanelMovie}->destroy;

        $self->setPanel;

        $self->{scrollPanelMovie} = new Gtk2::ScrolledWindow;
        $self->{scrollPanelMovie}->set_policy ('automatic', 'automatic');
        $self->{scrollPanelMovie}->set_shadow_type('etched-in');
        $self->{scrollPanelMovie}->add_with_viewport($self->{panel});
        $self->{pane}->pack2($self->{scrollPanelMovie},1,1);
        $self->{scrollPanelMovie}->show_all;
        $self->{movies}->setPanel($self->{panel});
        $self->checkBorrowers;
        $self->checkFormats;
        $self->checkPanel;

        foreach(@{$self->{movies}->{fieldsHistory}})
        {
            $self->{panel}->setHistory($_, $self->{movies}->getHistory($_));
        }
        
        $self->{movies}->displayCurrent;
    }

    sub checkToolbarPosition
    {
        my $self = shift;

        #Remove previous if exists
        if ($self->{boxToolbar})
        {
            $self->{boxToolbar}->remove($self->{toolbar});
            $self->{boxToolbar}->remove($self->{logoButton});
            $self->{boxToolbar}->destroy;
            $self->{mainHbox}->remove($self->{handleToolbar})
                if ($self->{mainHbox}->child_get($self->{handleToolbar}));
            $self->{mainVbox}->remove($self->{handleToolbar})
                if ($self->{mainVbox}->child_get($self->{handleToolbar}));
            $self->{handleToolbar}->destroy;
        };

        my $position = $self->{options}->toolbarPosition;
        
        # 0 => top
        # 1 => bottom
        # 2 => left
        # 3 => right
        
        if ($position > 1) # left or right
        {
            $self->{boxToolbar} = new Gtk2::VBox(0,0);
            $self->{toolbar}->set_orientation('vertical');
            $self->{toolbar}->set_style('icons');
            $self->{mainHbox}->pack_start($self->{handleToolbar},0,0,0);
            $self->{handleToolbar}->set_handle_position('top');
            if ($position == 2) # left
            {
                $self->{handleToolbar}->set_snap_edge('left');
                $self->{mainHbox}->reorder_child($self->{handleToolbar},0);
            }
            else # right
            {
                $self->{handleToolbar}->set_snap_edge('right');
                $self->{mainHbox}->reorder_child($self->{handleToolbar},1);
            }
        }
        else # top or bottom
        {
            $self->{boxToolbar} = new Gtk2::HBox(0,0);
            $self->{toolbar}->set_orientation('horizontal');
            $self->{toolbar}->unset_style;
            $self->{mainVbox}->pack_start($self->{handleToolbar},0,0,0 );
            $self->{handleToolbar}->set_handle_position('left');
            if ($position == 1) # bottom
            {
                $self->{handleToolbar}->set_snap_edge('bottom');
                $self->{mainVbox}->reorder_child($self->{handleToolbar},2);
            }
            else # top
            {
                $self->{handleToolbar}->set_snap_edge('top');
                $self->{mainVbox}->reorder_child($self->{handleToolbar},1);
            }
        }
        $self->{boxToolbar}->pack_start($self->{toolbar},1,1,0);
        $self->{boxToolbar}->pack_start($self->{logoButton},0,0,0);
        $self->{handleToolbar}->add($self->{boxToolbar});
        $self->{handleToolbar}->show_all;
    }

    sub checkDisplayed
    {
        my $self = shift;
        
        if ($self->{options}->status)
        {
            $self->{status}->show;
        }
        else
        {
            $self->{status}->hide;
        }

        if ($self->{options}->toolbar)
        {
            $self->{handleToolbar}->show;
            $self->{toolbar}->set_icon_size('small-toolbar') if $self->{options}->toolbar == 1;
            $self->{toolbar}->set_icon_size('large-toolbar') if $self->{options}->toolbar == 2;
            
            if ($self->{logoOriginalPixbuf})
            {
                my ($width, $height) = Gtk2::IconSize->lookup($self->{toolbar}->get_icon_size);
                my $logoPixbuf = GCUtils::scaleMaxPixbuf($self->{logoOriginalPixbuf}, $width * 1.7, $height * 1.7);
                $self->{logoImage}->set_from_pixbuf($logoPixbuf);
                $self->{logoButton}->show_all;
            }
        }
        else
        {
            $self->{handleToolbar}->hide;
        }

    }

    sub checkProxy
    {
		my $self= shift;
		
		$self->{plugin}->setProxy($self->{options}->proxy) if ($self->{plugin});
    }
    
    sub checkPlugin
    {
        my $self = shift;
        $self->{plugin} = undef;
        $self->{plugin} = $GCPlugins::pluginsMap{$self->{options}->plugin};

        $self->checkProxy;
    }
    
    sub checkBorrowers
    {
        my $self = shift;

        my @borrowers = split m/\|/, $self->{options}->borrowers;
        $self->{panel}->setBorrowers(\@borrowers);
    }
    
    sub checkView
    {
        my $self = shift;
        $self->{context}->{menuDisplayType}->set_active($self->{options}->view + 1);
        $self->{context}->{menuDisplayType}->get_active->set_active(1);
    }
    
    sub checkTransform
    {
        my $self = shift;
 
        my @array = split m/,/, $self->{options}->articles;

        my $tmpExpr = '';
        
        foreach (@array)
        {
            s/^\s*//;
            s/\s*$//;
            $tmpExpr .= "$_|";
        }
        chomp $tmpExpr;
        
        $self->{articles} = \@array;
        $self->{articlesRegexp} = $tmpExpr;
        
        $self->reloadList if ! $self->{initializing};
    }
    
    sub checkFormats
    {
        my $self = shift;
        
        my @formats = split m/,/, $self->{options}->formats;
        $self->{panel}->setFormats(\@formats);
    }
    
    sub checkPanel
    {
        my $self = shift;

        my $hasToShow = 1;
        $hasToShow = 0 if $self->{movies}->{selectToIdArray} && (! scalar @{$self->{movies}->{selectToIdArray}});

        $self->{panel}->setShowOption($self->getDialog('DisplayOptions')->{show}, $hasToShow);
        $self->showPlay($self->getDialog('DisplayOptions')->{show}->{trailer});
    }
    
    sub loadPrevious
    {
        my $self = shift;
        my $splash = shift;

        $self->{movies}->setOptions($self->{options}, $splash);
        $self->{moviesList}->setSortOrder;

        my $splashValue = 0.91;
        my $splashStep = 0.08 / (scalar @{$self->{movies}->{fieldsHistory}});
        foreach(@{$self->{movies}->{fieldsHistory}})
        {
            $self->{panel}->setHistory($_, $self->{movies}->getHistory($_));
            $splash->setProgress($splashValue) if $splash;
            $splashValue += $splashStep;
        }

        $self->{menubar}->setTypes($self->{movies}->getHistory('type'));
        $self->{menubar}->setTypes($self->{movies}->getHistory('type'),
                                   $self->{context}->{menuCategories});
        $splash->setProgress(0.99) if $splash;
        
        # Windows program starts iconify to hide console window.
        # Here we make only main window become visible.
        $self->deiconify if ($^O =~ /win32/i);
    }
    
    sub initEnd
    {
        my $self = shift;
        $self->{moviesList}->done;
        $self->{movies}->display($self->{movies}->select(0,undef,1));
    }

}

1;
