package GCPlugins::GCPluginsBase;

###################################################
#
#  Copyright 2005-2007 Tian
#
#  This file is part of GCstar.
#
#  GCstar 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.
#
#  GCstar 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 GCstar; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
###################################################

use strict;
use utf8;

{
    package GCPluginParser;
    use base qw(HTML::Parser);
    use LWP::Simple qw($ua);
    use HTTP::Cookies::Netscape;
    use URI::Escape;
    use HTML::Entities;
    use Encode;

    sub new
    {
        my $proto = shift;
        my $class = ref($proto) || $proto;
        my $self  = $class->SUPER::new();

        $ua->agent('Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041111 Firefox/1.0');
        $self->{ua} = $ua;
        
        $self->{itemIdx} = -1;
        $self->{itemsList} = ();
        
        bless ($self, $class);
        return $self;
    }

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

        return $self->{itemIdx} + 1;
    }

    sub getItems
    {
        my ($self) = @_;
        return @{$self->{itemsList}};
    }

    sub load
    {
        my $self = shift;
        
        $self->checkProxy;
        $self->checkCookieJar;
         
        $self->{itemIdx} = -1;
        $self->{isInfo} = 0;
        $self->{itemsList} = ();

        #my $word = uri_escape_utf8($self->{title});
        my $title2 = encode($self->getCharset, $self->{title});
        my $word = uri_escape($title2);
        $word =~ s/%20/+/g;

        my $post;
        my $html;

        # For multi-pass plugins, the plugin will have set the url to load for 
        # the next pass as nextUrl. If this doesn't exist, we're either on the 
        # first pass, or only using a one-pass plugin, so call getSearchUrl
        # to find the url to retrieve
        if ($self->{nextUrl})
        {
            $html = $self->loadPage($self->{nextUrl});
        }
        else
        {
            $html = $self->loadPage($self->getSearchUrl($word));    
        }

        $self->{parsingList} = 1;
        $html = $self->preProcess($html);
        decode_entities($html)
            if $self->decodeEntitiesWanted;
        $self->{inside} = undef;
        $self->parse($html);
        
        my @noConversion = @{$self->getNotConverted};
        foreach my $item (@{$self->{itemsList}})
        {
            foreach (keys %{$item})
            {
                next if $_ eq 'url';
                $item->{$_} = $self->convertCharset($item->{$_})
                    if ! GCUtils::inArrayTest($_, @noConversion);
            }
        }
        
    }
    
    sub loadPage
    {
        my ($self, $url, $post) = @_;
        $self->{loadedUrl} = $url;
        my $response;
        if ($post)
        {
            $response = $ua->post($url, $post);
            #$response = $self->{ua}->post($url, $post);
        }
        else
        {
            $response = $ua->get($url);
            #$response = $self->{ua}->get($url);
        }
        my $result;
        eval {
            $result = $response->decoded_content;
        };
        return $result || $response->content;
    }
    
    sub capWord
    {
        my ($self, $msg) = @_;
        
        use locale;
        
        (my $newmsg = lc $msg) =~ s/(\s|,|^)(\w)(\w)(\w*?)/$1\U$2\E$3$4/gi;
        return $newmsg;
    }

    sub getSearchFieldsArray
    {
        return [''];
    }

    sub getSearchFields
    {
        my ($self, $model) = @_;
        
        my $result = '';
        $result .= $model->getDisplayedLabel($_).', ' foreach (@{$self->getSearchFieldsArray});
        $result =~ s/, $//;
        return $result;
    }

    sub hasField
    {
        my ($self, $field) = @_;
    
        return $self->{hasField}->{$field};
    }

    sub getExtra
    {
        return '';
    }

    sub getCharset
    {
        my $self = shift;
    
        return "ISO-8859-1";
    }
    
    sub getNotConverted
    {
        my $self = shift;
        return [];
    }

    sub decodeEntitiesWanted
    {
        return 1;
    }

    sub getDefaultPictureSuffix
    {
        return '';
    }

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

        my $result = $value;
        if (ref($value) eq 'ARRAY')
        {
            foreach my $line(@{$value})
            {
                my $i = 0;
                map {$_ = decode($self->getCharset, $_)} @{$line};
            }
        }
        else
        {
            eval {
                $result = decode($self->getCharset, $result);
            };
        }
        return $result;
    }
    
    sub getItemInfo
    {
        my $self = shift;

        eval {
            $self->init;
        };
        my $idx = $self->{wantedIdx};
        my $url = $self->getItemUrl($self->{itemsList}[$idx]->{url});
        $self->loadUrl($url);
        return $self->{curInfo};
    }
        
    sub changeUrl
    {
        my ($self, $url) = @_;
        
        return $url;
    }
    
    sub loadUrl
    {
        my ($self, $url) = @_;
        $self->checkProxy;
        my $realUrl = $self->changeUrl($url);
        
        my $html = $self->loadPage($realUrl);
        $self->{parsingList} = 0;
        #$html = $self->convertCharset($html);
        $html = $self->preProcess($html);
        decode_entities($html)
            if $self->decodeEntitiesWanted;

        $self->{curInfo} = {};

        $self->{curInfo}->{$self->{urlField}} = $url;
        $self->{inside} = undef;
        $self->parse($html);

        my @noConversion = @{$self->getNotConverted};
        foreach (keys %{$self->{curInfo}})
        {
            next if $_ eq $self->{urlField};
            $self->{curInfo}->{$_} = $self->convertCharset($self->{curInfo}->{$_})
                if ! GCUtils::inArrayTest($_, @noConversion);
            if (ref($self->{curInfo}->{$_}) ne 'ARRAY')
            {
                $self->{curInfo}->{$_} =~ s/\|/,/gm;
                $self->{curInfo}->{$_} =~ s/\r//gm;
                $self->{curInfo}->{$_} =~ s/[ \t]*$//gm;
            }
        }
        $self->{curInfo}->{$self->{urlField}} .= $GCModel::linkNameSeparator.$self->getName;
        return $self->{curInfo};
    }

    sub setProxy
    {
		my ($self, $proxy) = @_;
		
		$self->{proxy} = $proxy;
    }
    
    sub checkProxy
    {
        my $self = shift;
        $ua->proxy(['http'], $self->{proxy});
        #$self->{ua}->proxy(['http'], $self->{proxy});
    }
    
    sub setCookieJar
    {
        my ($self, $cookieJar) = @_;
        $self->{cookieJar} = $cookieJar;  
    }

    sub checkCookieJar
    {
        my $self = shift;
        $ua->cookie_jar(HTTP::Cookies::Netscape->new(
          'file' => "$self->{cookieJar}"));
    }

    # Used to set the number of passes the plugin requires
    sub getNumberPasses
    {
        # Most plugins only need to search once, so default to one pass
        return 1;
    }
}

1;
