package GCData;

###################################################
#
#  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 GCDisplay;

{
    package GCMovies;

    use base 'Exporter';

    our @EXPORT = qw(@fieldsArray);

    our @fieldsArray = (
        'id' => {
                    hasHistory => 0,
                    initValue  => '',
                    isList     => 0,
                    isNumeric  => 0,
                    isImported => 0},
        'title' => {
                    hasHistory => 0,
                    initValue  => '',
                    isList     => 0,
                    isNumeric  => 0,
                    isImported => 1},
        'date' => {
                    hasHistory => 0,
                    initValue  => '',
                    isList     => 0,
                    isNumeric  => 0,
                    isImported => 1},
        'time' => {
                    hasHistory => 0,
                    initValue  => '',
                    isList     => 0,
                    isNumeric  => 0,
                    isImported => 1},
        'director' => {
                    hasHistory => 0,
                    initValue  => '',
                    isList     => 0,
                    isNumeric  => 0,
                    isImported => 1},
        'nat' => {
                    hasHistory => 0,
                    initValue  => '',
                    isList     => 0,
                    isNumeric  => 0,
                    isImported => 1},
        'type' => {
                    hasHistory => 1,
                    initValue  => ',,,',
                    isList     => 1,
                    isNumeric  => 0,
                    isImported => 1},
        'image' => {
                    hasHistory => 0,
                    initValue  => '',
                    isList     => 0,
                    isNumeric  => 0,
                    isImported => 1},
        'actors' => {
                    hasHistory => 0,
                    initValue  => '',
                    isList     => 1,
                    isNumeric  => 0,
                    isImported => 1},
        'orig' => {
                    hasHistory => 0,
                    initValue  => '',
                    isList     => 0,
                    isNumeric  => 0,
                    isImported => 1},
        'synopsis' => {
                    hasHistory => 0,
                    initValue  => '',
                    isList     => 0,
                    isNumeric  => 0,
                    isImported => 1},
        'url' => {
                    hasHistory => 0,
                    initValue  => '',
                    isList     => 0,
                    isNumeric  => 0,
                    isImported => 1},
        'seen' => {
                    hasHistory => 0,
                    initValue  => '',
                    isList     => 0,
                    isNumeric  => 0,
                    isImported => 0},
        'format' => {
                    hasHistory => 0,
                    initValue  => 'DVD',
                    isList     => 0,
                    isNumeric  => 0,
                    isImported => 0},
        'number' => {
                    hasHistory => 0,
                    initValue  => 1,
                    isList     => 0,
                    isNumeric  => 1,
                    isImported => 0},
        'place' => {
                    hasHistory => 1,
                    initValue  => '',
                    isList     => 0,
                    isNumeric  => 0,
                    isImported => 0},
        'rating' => {
                    hasHistory => 0,
                    initValue  => 5,
                    isList     => 0,
                    isNumeric  => 1,
                    isImported => 0},
        'comment' => {
                    hasHistory => 0,
                    initValue  => '',
                    isList     => 0,
                    isNumeric  => 0,
                    isImported => 0},
        'audio' => {
                    hasHistory => 1,
                    initValue  => '',
                    isList     => 1,
                    isNumeric  => 0,
                    isImported => 1},
        'subt' => {
                    hasHistory => 1,
                    initValue  => '',
                    isList     => 1,
                    isNumeric  => 0,
                    isImported => 1},
        'borrower' => {
                    hasHistory => 0,
                    initValue  => 'none',
                    isList     => 0,
                    isNumeric  => 0,
                    isImported => 0},
        'lendDate' => {
                    hasHistory => 0,
                    initValue  => '',
                    isList     => 0,
                    isNumeric  => 0,
                    isImported => 0},
        'history' => {
                    hasHistory => 0,
                    initValue  => '',
                    isList     => 0,
                    isNumeric  => 0,
                    isImported => 0},
        'age' => {
                    hasHistory => 0,
                    initValue  => '',
                    isList     => 0,
                    isNumeric  => 1,
                    isImported => 1},
        'video' => {
                    hasHistory => 1,
                    initValue  => '',
                    isList     => 0,
                    isNumeric  => 0,
                    isImported => 0},
        'collection' => {
                    hasHistory => 1,
                    initValue  => '',
                    isList     => 0,
                    isNumeric  => 0,
                    isImported => 0},
        'rank' => {
                    hasHistory => 0,
                    initValue  => 0,
                    isList     => 0,
                    isNumeric  => 1,
                    isImported => 0},
        'trailer' => {
                    hasHistory => 0,
                    initValue  => '',
                    isList     => 0,
                    isNumeric  => 0,
                    isImported => 0},
    );


    sub new
    {
        my ($proto, $parent) = @_;
        my $class = ref($proto) || $proto;
        my $self  = {};

        #Informations for a field
        # { Has History?, Initial value, Is List?, Is Numeric?, Is Imported? }

        my @fields;
        my %fieldsInfo;
        my @fieldsHistory;
        my $i = 0;
        foreach (@fieldsArray)
        {
            $i++;
            next if !($i % 2);
            push @fields, $_;
            $fieldsInfo{$_} = $fieldsArray[$i];
            push @fieldsHistory, $_ if $fieldsArray[$i]->{hasHistory};
        }
        $self->{fields} = \@fields;
        $self->{fieldsInfo} = \%fieldsInfo;
        $self->{fieldsHistory} = \@fieldsHistory;

        $self->{parent} = $parent;

        $self->{imagesToBeRemoved} = ();
        $self->{imagesToBeAdded} = ();
        $self->{movieArray} = [];

        #$self->{currentSortOrder} = 1;
        #$self->{currentSortField} = 'title';
        
        $self->{currentMovie} = -1;
        $self->{currentId} = -1;
        $self->{hasBeenDeleted} = 0;
        $self->{block} = 0;
        $self->{filterSearch} = new GCFilterSearch;

        bless ($self, $class);
        return $self;
    }
 
    sub getEmptyInfo
    {
        my $self = shift;
        my $info = {};
        $info->{$_} = $self->{fieldsInfo}->{$_}->{initValue} foreach (@{$self->{fields}});
        return $info;
    }

    sub setPanel
    {
        my ($self, $panel) = @_;
        $self->{panel} = $panel;
    }

    sub updateCurrentFromPanel
    {
        my ($self, $panel) = @_;
        my $previousPanel = $self->{panel};
        $self->{panel} = $panel;
        $self->updateCurrent;
        $self->{panel} = $previousPanel;
    }

    sub updateCurrent
    {
        my $self = shift;

        return if $self->{currentMovie} == -1;
        my $oldTitle = $self->{movieArray}[$self->{currentMovie}]->{title};

        my $panelId = $self->{panel}->id;
        my $previousId = $self->{movieArray}[$self->{currentMovie}]->{id};
        
        if ($panelId &&
           ($panelId != $previousId))
        {
		  $self->{movieArray}[$self->{currentMovie}]->{id} = $self->{panel}->id;
		  $self->{maxId} = $panelId if ($panelId > $self->{maxId});
		  $self->findMaxId if $previousId == $self->{maxId};
		  $self->{currentId} = $panelId;
		  $self->{toBeDisplayed}->{$panelId} = 1;
		  $self->{toBeDisplayed}->{$previousId} = 0;
        }
        $self->{panel}->id($self->{movieArray}[$self->{currentMovie}]->{id}) if $self->{panel}->id;

        my $info = $self->{movieArray}[$self->{currentMovie}];
        
        my $previous = {id => $previousId};
        for my $field (keys %{$info})
        {
            next if $field eq 'id';
            $previous->{$field} = $info->{$field};
            if ($self->{fieldsInfo}->{$field}->{hasHistory})
            {
                my $tmp = $self->{panel}->$field;
                if ($self->addHistory($field, $tmp))
                {
                    $self->{panel}->setHistory($field, $self->getHistory($field));
                    if ($field eq 'type')
                    {
                        $self->{parent}->{menubar}->setTypes($self->getHistory('type'));
                    }
                    $self->{panel}->$field($tmp);
                }
            }
            $info->{$field} = $self->{panel}->$field;
        }

        if (($previous->{collection})
         && (($previous->{collection} != $info->{collection})
          || ($self->{minRanks}->{$previous->{collection}} == $previous->{rank})
          || ($self->{maxRanks}->{$previous->{collection}} == $previous->{rank})))
        {
            #Min or max rank has to be changed for previous collection
            $self->findMinMaxForCollection($previous->{collection});
        }

        if (($info->{collection})
         && (($self->{minRanks}->{$info->{collection}} > $info->{rank})
          || ($self->{maxRanks}->{$info->{collection}} < $info->{rank})))
        {
            #Min or max rank has to be changed for new collection
            $self->findMinMaxForCollection($info->{collection});
        }
        
        $self->{minRanks}->{$info->{collection}} = $info->{rank}
            if  $info->{collection}
            && ($info->{rank} < $self->{minRanks}->{$info->{collection}});
        $self->{maxRanks}->{$info->{collection}} = $info->{rank}
            if  $info->{collection}
            && ($info->{rank} > $self->{maxRanks}->{$info->{collection}});
                
        #Propagate borrowing information
        if (($info->{collection})
         && ($self->{minRanks}->{$info->{collection}} >= $info->{rank})
         && ($info->{borrower} ne $previous->{borrower}))
        {
            for (my $i = 0; $i < $self->{nbMovies}; $i++)
            {
                next if $self->{movieArray}[$i]->{collection} ne $info->{collection};
                $self->{movieArray}[$i]->{borrower} = $info->{borrower};
                $self->{movieArray}[$i]->{lendDate} = $info->{lendDate};
            }
        }


        if (($oldTitle ne $self->{movieArray}[$self->{currentMovie}]->{title}) &&
            ($self->{currentSortField} eq 'title'))
        {
            use locale;
            my $current = $self->{movieArray}[$self->{currentMovie}];
            my $next = 0;
            my $previous = 0;
            
            $next = $self->{movieArray}[$self->{currentMovie} + 1]
                if $self->{currentMovie} < ($self->{nbMovies} - 1);
 
            $previous = $self->{movieArray}[$self->{currentMovie} - 1]
                if $self->{currentMovie} > 0;
 
            if (
                 (
                    $self->{nbMovies} < 4
                 ) ||
                 (
                   $next && $previous &&
                   (
                     ($self->compareMovies($current, $previous) < 0) ||
                     ($self->compareMovies($current, $next) > 0)
                   )
                 ) ||
                 (
                    $next &&
                    ($self->compareMovies($current, $next) > 0)
                 ) ||
                 (
                    $previous &&
                    ($self->compareMovies($current, $previous) < 0)
                 )
               )
            {
    		    $self->reloadList;
    		    return 1;
            }
        }
        if ($self->{parent}->{moviesList}->changeCurrent($previous, $info))
        {
            $self->reloadList;
            return 1;
        }
        return 0;
    }
    
    sub currentTitle
    {
        my $self = shift;

        return $self->{movieArray}[$self->{currentMovie}]->{title};
    }
    
    sub displayCurrent
    {
        my $self = shift;
        $self->displayInPanel($self->{panel});
    }
    
    sub displayInPanel
    {
        my ($self, $panel, $idx) = @_;
        
        $idx = $self->{currentMovie} if $idx == undef;
        return if $self->{currentMovie} < 0;
        
        for my $field (@{$self->{fields}})
        {
            $panel->$field($self->{movieArray}[$idx]->{$field});
        }
    }

    sub display
    {
        my $self = shift;

        return if ! $self->{nbMovies};

        my $number = shift;

        $number = 0 if $number == -1;

        $number = $self->selectToId($number);
        $self->{currentId} = $self->{movieArray}[$number]->{id};

        my $hasBeenReloaded = 0;

        if (($self->{currentMovie} > -1) && !($self->{hasBeenDeleted}))
        {
            $hasBeenReloaded = $self->updateCurrent;
        }
        else
        {
            $self->{currentMovie} = $number;
        }

        $self->{hasBeenDeleted} = 0;

        $self->{currentMovie} = $number if ! $hasBeenReloaded;
        $self->displayCurrent;
    }

    sub setFilter
    {
        my ($self, $filter, $parameter) = @_;

        my $filtered = 1;
        if ($filter eq 'seen')
        {
            if ($parameter eq 'notseen')
            {
                $self->{filterSearch}->setSeen(0);
            }
            else
            {
                $self->{filterSearch}->setSeen(-1);
            }
        }
        elsif ($filter eq 'type')
        {
            if ($parameter eq 'all')
            {
                $self->{filterSearch}->setType('');
            }
            else
            {
                $self->{filterSearch}->setType($parameter);
            }
        }
        elsif ($filter eq 'rating')
        {
            if ($parameter eq 'all')
            {
                $self->{filterSearch}->setRating(0);
            }
            else
            {
                $self->{filterSearch}->setRating($parameter);
            }
        }
        elsif ($filter eq 'age')
        {
            if ($parameter eq 'all')
            {
                $self->{filterSearch}->setAge(-1);
            }
            else
            {
                $self->{filterSearch}->setAge($parameter);
            }
        }
        elsif ($filter eq 'borrowing')
        {
            if ($parameter eq 'all')
            {
                $self->{filterSearch}->setBorrowed(-1);
            }
            else
            {
                $self->{filterSearch}->setBorrowed(($parameter eq 'yes') ? 1 : 0);
            }
        }
        elsif ($filter eq 'search')
        {
            if ($parameter eq 'all')
            {
                $filtered = 0;
                $self->{filterSearch}->clear;
            }
            else
            {
                $self->{filterSearch}->setOptions($parameter);
            }
        }

        $self->filter;
        $self->reloadList($self->{parent}, 1, $filtered);
        
        $self->displayCurrent;
    }

    sub filterTest
    {
        my ($self, $value) = @_;

		return $self->{filterSearch}->test($value);
    }

    sub filter
    {
        my $self = shift;

        my %tmpMap = {};        
        my $i;
        for ($i = 0; $i < $self->{nbMovies}; $i++)
        {
            my $id = $self->{movieArray}[$i]->{id};
            if ($self->filterTest($self->{movieArray}[$i]))
            {
                $tmpMap{$id} = 1;
            }
            else
            {
                $tmpMap{$id} = 0;
            }
        }
       $self->{toBeDisplayed} = \%tmpMap;
    }

    sub clearHistories
    {
        my $self = shift;
        
        foreach (@{$self->{fieldsHistory}})
        {
            $self->{$_.'History'} = {};
        }
    }

    sub addHistory
    {
        my ($self, $field, $value) = @_;
        my $added = 0;
        if ($self->{fieldsInfo}->{$field}->{isList})
        {
            my @values = split m/,/, $value;
            foreach (@values)
            {
                next if $_ eq '';
                if (! exists $self->{$field.'History'}->{$_})
                {
                    $self->{$field.'History'}->{ucfirst $_} = 1;
                    $added = 1;
                }
            }
        }
        else
        {
            if (($value ne '')
             && (! exists $self->{$field.'History'}->{$value}))
            {
                $self->{$field.'History'}->{ucfirst $value} = 1;
                $added = 1;
            }
        }
        return $added;
    }

    sub getHistory
    {
        my ($self, $field) = @_;

        return $self->getAudioHistory if $field eq 'audio';
        use locale;
        my @result = ('', sort keys %{$self->{$field.'History'}});
        return \@result;
    }

    sub getAudioHistory
    {
        my $self = shift;
        my (@audios, @encodings);
        my (%audios, %encodings);

        use locale;
        
        foreach (sort keys %{$self->{audioHistory}})
        {
            my @track = split ';';
            $audios{$track[0]} = 1 if ($track[0]);
            $encodings{$track[1]} = 1 if ($track[1]);
        }

        @audios = ('', sort keys %audios);
        @encodings = ('', sort keys %encodings);
        
        return (\@audios, \@encodings);
    }
    
    sub changeOrder
    {
        my ($self, $field) = @_;
        
        $field = 'title' if !$field;

        $self->{currentSortOrder} = 0 if ($field ne $self->{currentSortField});
        $self->{currentSortField} = $field;
        $self->{currentSortOrder} = 1 - $self->{currentSortOrder};
        
        $self->{options}->sortOrder($self->{currentSortOrder});
        $self->{options}->sortField($self->{currentSortField});
        
        $self->reloadList($self->{parent}, 1);
    }
    
    sub resetSortField
    {
        my $self = shift;
        $self->{currentSortField} = 'title';
    }
    
    sub restoreSort
    {
        my $self = shift;
        $self->{options}->sortOrder(1) if ! $self->{options}->exists('sortOrder');
        $self->{options}->sortField('title') if ! $self->{options}->exists('sortField');
        $self->{currentSortOrder} = $self->{options}->sortOrder;
        $self->{currentSortField} = $self->{options}->sortField;
    }
    
    sub getSortOrder
    {
        my $self = shift;
        
        return ($self->{currentSortOrder}, $self->{currentSortField});        
    }

    sub compareMovies
    {
        my ($self, $a, $b) = @_;
    
        use locale;
        return ($self->{parent}->transformTitle($a->{title}) cmp $self->{parent}->transformTitle($b->{title}))
            if $self->{currentSortField} eq 'title';
        return ($a->{id} <=> $b->{id})
            if $self->{currentSortField} eq 'id';
        return ($a->{$self->{currentSortField}} cmp $b->{$self->{currentSortField}});
    }
    
    sub getValue
    {
        my ($self, $idx, $field) = @_;
        
        return $self->{movieArray}[$idx]->{$field};
    }
    
    sub setValue
    {
        my ($self, $idx, $field, $value) = @_;
        
        $self->{movieArray}[$idx]->{$field} = $value;
        $self->{maxRanks}->{$self->{movieArray}[$idx]->{collection}} = $value
            if ($field eq 'rank')
            && ($self->{movieArray}[$idx]->{collection})
            && ($value > ($self->{maxRanks}->{$self->{movieArray}[$idx]->{collection}}));
        $self->{minRanks}->{$self->{movieArray}[$idx]->{collection}} = $value
            if ($field eq 'rank')
            && ($self->{movieArray}[$idx]->{collection})
            && (($value < ($self->{minRanks}->{$self->{movieArray}[$idx]->{collection}}))
             || (!exists $self->{minRanks}->{$self->{movieArray}[$idx]->{collection}}));
        $self->{panel}->$field($value) if $idx == $self->{currentMovie};
    }
    
    sub getMoviesList
    {
        my ($self, $filter) = @_;
        
        return $self->{movieArray} if ! $filter;
        my @results = ();
        my $j;
        for ($j = 0; $j < $self->{nbMovies}; $j++)
        {
            if ($self->{toBeDisplayed}->{$self->{movieArray}[$j]->{id}})
            {
                push @results, $self->{movieArray}[$j];
            }
        }
        return \@results;
    }
    
    sub reloadList
    {
        my ($self, $splash, $fullProgress, $filtering) = @_;

        return if $self->{block};
        
        if ($splash)
        {
            $splash->initProgress if $fullProgress;
            $splash->setMoviesTotal($self->{informations}->{count});
        }
        
        $self->{parent}->{moviesList}->reset;
        
        sub compare
        {
            return $self->compareMovies($a, $b);
        }

        if ($self->{currentSortOrder})
        {
            @{$self->{movieArray}} = sort compare @{$self->{movieArray}};
        }
        else
        {
            @{$self->{movieArray}} = reverse sort compare @{$self->{movieArray}};
        }

        my @displayedArray = ();
        my $lastDisplayed = -1;
        my $hasId = 0;
        my $currentDisplayed = 0;
        my $j;
        
        for ($j = 0; $j < $self->{nbMovies}; $j++)
        {
            $hasId = 0;
            if ($self->{currentId} == $self->{movieArray}[$j]->{id})
            {
                $hasId = 1;
            }

            if ($self->{toBeDisplayed}->{$self->{movieArray}[$j]->{id}})
            {
                $self->{parent}->{moviesList}->addMovie($self->{movieArray}[$j]);
                
                if ($hasId)
                {
				    $self->{currentMovie} = $j;
				    $currentDisplayed = $#displayedArray + 1;
                }
                push @displayedArray, $j;
                $lastDisplayed = $j;
            }
            else
            {
                if ($hasId)
                {
                    $currentDisplayed = $#displayedArray;
                    $self->{currentMovie} = $lastDisplayed;
                    $self->{currentId} = $self->{movieArray}[$lastDisplayed]->{id};
                }
            }

            $splash->setProgressForMoviesDisplay($j) if $splash;
        }

        $self->{selectToIdArray} = \@displayedArray;

        if (! scalar(@displayedArray))
		{
		    $self->{panel}->hide($filtering);
		}
        else
        {
            $self->{panel}->show;
        }

        if ($splash && $fullProgress)
        {
            $splash->endProgress;
        }
        
        $self->{currentId}  = $self->selectToId(0)
            if ($self->{currentId} == -1);

        if (! $self->{parent}->{initializing})
        {
            $self->{parent}->{moviesList}->done;
            $self->select($currentDisplayed, $self->{currentId}, 0);
            $self->{parent}->{moviesList}->showCurrent;
        }

        $self->setStatus;
    }

    sub setStatus
    {
        my $self = shift;
        
        my $number = 0;
        $number = scalar @{$self->{selectToIdArray}} if $self->{selectToIdArray};
        my $status = ' ';
        $status .= $number;
        $status .= ' '.$self->{parent}->{lang}->{StatusMovies};
        $self->{parent}->setStatus($status);
    }

    sub select
    {
		my ($self, $value, $id, $init) = @_;

		$self->{parent}->{moviesList}->select($value, $id, $init) unless  $value < 0;
    }

    sub removeCurrentMovie
    {
        my $self = shift;

        my $number = $self->{currentMovie};
        my $prevId = $self->{movieArray}[$number]->{id};

        my $image = $self->{movieArray}[$number]->{image};
        my $imagePrefix = $self->{parent}->{imagePrefix};
        if ($image =~ /(\/|\\)$imagePrefix[0-9]*\./)
        {
            $self->markToBeRemoved($image);
        }

        my $oldInfo = splice @{$self->{movieArray}}, $number, 1;

        $self->{nbMovies}--;

        if ($oldInfo->{collection} &&
           (($self->{minRanks}->{$oldInfo->{collection}} == $oldInfo->{rank}) ||
            ($self->{maxRanks}->{$oldInfo->{collection}} == $oldInfo->{rank})))
        {
            #Min or max rank has to be changed
            $self->findMinMaxForCollection($oldInfo->{collection});
        }

        $self->{panel}->hide if ! $self->{nbMovies};

        $self->{currentMovie}-- if $self->{currentMovie};
        
        my $id = $self->{movieArray}[$self->{currentMovie}]->{id};
        $self->{currentId} = $id;

        if ($self->{parent}->{moviesList}->removeMovie($number, $prevId, $oldInfo))
        {
            $self->reloadList;
        }
        else
        {
            $self->{parent}->{moviesList}->select($self->{currentMovie});
        }

        $self->{hasBeenDeleted} = 1;

        $self->displayCurrent if $self->{nbMovies};
    }

    sub addMovie
    {
        my ($self, $info) = @_;
        $self->{panel}->show if ! $self->{nbMovies};

        $self->{maxId}++;
        
        my $currentId = $self->{maxId};

        $self->{movieArray}[$self->{nbMovies}]->{id} = $currentId;
        
        for my $field (@{$self->{fields}})
        {
            next if $field eq 'id';
            if ($self->{fieldsInfo}->{$field}->{hasHistory})
            {
                $self->addHistory($field, $info->{$field});
            }
            $self->{movieArray}[$self->{nbMovies}]->{$field} = $info->{$field};
        }

        $self->{currentId} = $self->{maxId};
        $self->{toBeDisplayed}->{$self->{currentId}} = 1;

        $self->{toBeDisplayed}->{$self->{currentId}} = 1;
        $self->{parent}->{moviesList}->addMovie($self->{movieArray}[$self->{nbMovies}]);

        $self->{currentMovie} = $self->{nbMovies};
        push @{$self->{selectToIdArray}}, $self->{nbMovies};

        $self->select($self->{nbMovies}, $self->{currentId}, 0);
        $self->setStatus;
        
        $self->{nbMovies}++;        

        $self->{parent}->{moviesList}->showCurrent;
        
        return $currentId;
    }
    
    sub insertMovie
    {
        my ($self, $info) = @_;

        $self->{maxId}++;

        $self->{movieArray}[$self->{nbMovies}]->{id} = $self->{maxId};
        for my $field (@{$self->{fields}})
        {
            next if $field eq 'id';
            $self->{movieArray}[$self->{nbMovies}]->{$field} = $info->{$field};
            if ($self->{fieldsInfo}->{$field}->{hasHistory})
            {
                $self->addHistory($field, $info->{$field});
            }

        }
        
        $self->{nbMovies}++;

        #$self->{currentId} = $self->{maxId};
        $self->{toBeDisplayed}->{$self->{maxId}} = 1;
    }

    sub selectToId
    {
		my ($self, $i) = @_;
	
		return $self->{selectToIdArray}[$i];
    }

    sub setOptions
    {
        my ($self, $options, $splash) = @_;

        $self->{options} = $options;

        $self->restoreSort;

        $self->load($options->file, $splash, 0);
    }

    sub markToBeRemoved
    {
        my ($self, $image) = @_;

        push @{$self->{imagesToBeRemoved}}, $image;
    }

    sub markToBeAdded
    {
        my ($self, $image) = @_;
        push @{$self->{imagesToBeAdded}}, $image;        
    }
    
    sub removeMarkedPictures
    {
        my $self = shift;
        my $image;
        foreach $image(@{$self->{imagesToBeRemoved}})
        {
            unlink $image;
        }

        $self->{imagesToBeRemoved} = ();
    }

    sub addMarkedPictures
    {
        my $self = shift;

        $self->{imagesToBeAdded} = ();
    }
    
    sub clean
    {
        my $self = shift;
        my $image;
        foreach $image(@{$self->{imagesToBeAdded}})
        {
            unlink $image;
        }
    }

    sub rename
    {
        my ($self, $old, $new) = @_;
        
        foreach (@{$self->{movieArray}})
        {
            $_->{type} =~ s/$old,/$new,/gi;
        }
        $self->displayCurrent;
        $self->reloadList;
    }
    
    sub getMinRank
    {
        my ($self, $collection) = @_;
        
        return $self->{minRanks}->{$collection}
    }
    
    sub getMaxRank
    {
        my ($self, $collection) = @_;
        return $self->{maxRanks}->{$collection}
    }

    sub findMinMaxForCollection
    {
        my ($self, $collection) = @_;

        $self->{minRanks}->{$collection} = 1001;
        $self->{maxRanks}->{$collection} = -1;
        my $i;
        #We scan all the movies to find the new master
        # (May be optimized)
        for ($i = 0; $i < $self->{nbMovies}; $i++)
        {
            next if $self->{movieArray}[$i]->{collection} ne $collection;
            my $rank = $self->{movieArray}[$i]->{rank};
            $self->{minRanks}->{$collection} = $rank
                if $rank < $self->{minRanks}->{$collection};
            $self->{maxRanks}->{$collection} = $rank
                if $rank > $self->{maxRanks}->{$collection};
        }
    }
    
    sub findMaxId
    {
        my $self = shift;

        $self->{maxId} = -1;
        my $i;
        for ($i = 0; $i < $self->{nbMovies}; $i++)
        {
            $self->{maxId} = $self->{movieArray}[$i]->{id}
                if $self->{movieArray}[$i]->{id} > $self->{maxId};
        }
    }
    
    sub clearList
    {
        my $self = shift;
        $self->{currentMovie} = -1;
        $self->clearHistories;
        $self->{maxId} = 0;
		$self->{movieArray} = [];
		$self->{informations} = {};
		$self->{selectToIdArray} = [];
        my %tmpMap = {};
        $self->{minRanks} = {};
        $self->{maxRanks} = {};
		$self->{currentId} = -1;
		$self->{toBeDisplayed} = \%tmpMap;
        $self->{panel}->hide if $self->{panel};
        $self->{nbMovies} = 0;
        $self->{parent}->{moviesList}->clearCache if $self->{parent};
        $self->reloadList if ! $self->{parent}->{initializing};# || $self->{loading});
    }

    sub load
    {
        my ($self, $file, $splash, $fullProgress, $noReload) = @_;

        $self->clean;
        my $i = 0;
        $self->{block} = 1;
        $self->clearList;
        $self->{block} = 0;

        return if (!$file);
        my $error = 0;
        if (! -e $file)
		{
            $self->{nbMovies} = 0;
            $self->{panel}->hide if $self->{panel};
            if (! open MOVIES, ">$file")
            {
                print "Cannot create $file\n";
                $error = 1;
            }
            else
            {
                close MOVIES;
            }
		}
		if ($error || (! open MOVIES, "<$file"))
		{
		    $self->{parent}->{splash}->hide if $self->{parent}->{splash};
		    my  $dialog = Gtk2::MessageDialog->new($self->{parent},
							   [qw/modal destroy-with-parent/],
							   'error',
							   'ok',
							   $self->{parent}->{lang}->{OpenError}."\n\n$file");

            $dialog->set_position('center-on-parent');
		    $dialog->run();
		    $dialog->destroy ;
		    return;
		}
        my %tmpMap = {};
        my $gotFirstLine = 0;

        while (<MOVIES>)
        {
            chomp;
            my @values =  split m/\|/;

            if (!$gotFirstLine)
            {
                $gotFirstLine = 1;
                if ($values[0] eq 'GCfilms')
                {
                    $self->{informations}->{count} = $values[1];
                    $splash->setMoviesTotal($self->{informations}->{count}) if $splash;
                    binmode( MOVIES, ':utf8' ) if $values[2] eq 'UTF8';
                    next;
                }
            }

            my $idx = 0;
            for my $field (@{$self->{fields}})
            {
                $self->{movieArray}[$i]->{$field} = $values[$idx];
                if ($self->{fieldsInfo}->{$field}->{hasHistory})
                {
                    $self->addHistory($field, $values[$idx]);
                }
                $idx++;
            }

            if ($self->{movieArray}[$i]->{id} > $self->{maxId})
            {
                $self->{maxId} = $self->{movieArray}[$i]->{id};
            }
            
            if ($self->filterTest($self->{movieArray}[$i]))
            {
                $tmpMap{$values[0]} = 1;
            }
            else
            {
                $tmpMap{$values[0]} = 0;
            }

            $splash->setProgressForMoviesLoad($i, $self->{informations}->{count}) if $splash;

            my ($collection, $rank) = ($self->{movieArray}[$i]->{collection},
                                       $self->{movieArray}[$i]->{rank});

            $i++;
            
            next if ! $collection;
            
            $self->{minRanks}->{$collection} = 1001 if ! exists $self->{minRanks}->{$collection};
            $self->{minRanks}->{$collection} = $rank if ($rank < $self->{minRanks}->{$collection});
            $self->{maxRanks}->{$collection} = -1 if ! exists $self->{maxRanks}->{$collection};
            $self->{maxRanks}->{$collection} = $rank if ($rank > $self->{maxRanks}->{$collection});
        }
        close MOVIES;
        $self->{nbMovies} = $i;
		$self->{toBeDisplayed} = \%tmpMap;
	
		if (! $i)
		{
		    $self->{panel}->hide;
		}
		
        $self->reloadList($splash, $fullProgress) unless $noReload;
    }

    sub save
    {
        my $self = shift;

        $self->updateCurrent if ($self->{currentMovie} > -1);
        $self->addMarkedPictures;
        $self->removeMarkedPictures;

        if (!open DATA, ">".$self->{options}->file)
        {
            my  $dialog = Gtk2::MessageDialog->new($self->{parent},
                [qw/modal destroy-with-parent/],
                'error',
                'ok',
                $self->{parent}->{lang}->{SaveError});

            $dialog->set_position('center-on-parent');
            $dialog->run();
            $dialog->destroy ;
            return 0;
        }
        
        binmode(DATA, ':utf8' );

        printf DATA "GCfilms|%d|UTF8\n",$self->{nbMovies};

        my $line;
        my $i;
        for ($i = 0; $i < $self->{nbMovies}; $i++)
        {
            $line = '';
            $self->{movieArray}[$i]->{image} 
              = $self->{parent}->transformPicturePath($self->{movieArray}[$i]->{image});
            $line .= $self->{movieArray}[$i]->{$_}."|" foreach (@{$self->{fields}});
            $line =~ s/.$//;

            printf DATA "$line\n";
        }
        close DATA;
        
        return 1;
    }
}

1;
