package Opals::BookCover;

require Exporter;
@ISA       = qw(Exporter);

@EXPORT_OK = qw(
    bookCover_getUrl
    bookCover_amazon
    bookCover_google
    bookCover_syndetics
    bookCover_opals
    bookCover_upload
);


# Version number
$VERSION   = 0.01;      

use strict;
use Encode;

use LWP::UserAgent;
use HTTP::Request::Common;
use Business::ISBN;

use Time::gmtime;

use Digest::SHA qw(
    hmac_sha256_base64
);

use URI::Escape;

use  Opals::Utility qw(
    util_getXmlRecord
    );
sub bookCover_getUrl{ 
    my($isbnList,$accesskey,$secretKey)=@_;
    # $AWS: Amazon Webservice user id
   
    my $ret;
    my $userAgent = LWP::UserAgent->new(agent => 'perl post');
    
   # Amazon Web service allows maximum 10 items  per request
   # devide isbn list to a chunks of ten
   #

    my @isbnArr = split /,/, $isbnList;
    my @isbnSubListArr=();
    my $c=-1;
    for(my $i=0; $i < scalar(@isbnArr); $i++){
        if($i%10 ==0) {$c++}
        if(length(@isbnArr[$i]) ==13 && @isbnArr[$i] =~ m/^978/g){
            my $isbn=Business::ISBN->new(@isbnArr[$i]);
            @isbnArr[$i]=$isbn->as_isbn10->as_string([])

        }
        @isbnSubListArr[$c] .=@isbnArr[$i] .",";
    }

      foreach my $isbnSubList(@isbnSubListArr){
        my $url =createAWS_url($isbnSubList,$accesskey,$secretKey);
        my $request = HTTP::Request->new(GET => $url);              
        my $response = $userAgent->request($request );
        my $xmlStr=$response->as_string;
       $xmlStr =~ s/<\/Item>/<\/Item>\r/g;
        while($xmlStr =~ s/[\s]*<Item>([^\r]*)<\/Item>//){
            my $itemXml =$1;
            if($itemXml =~ s/<ASIN>(.*)<\/ASIN>//){
                #my $isbn=$1;
                my $isbn=Business::ISBN->new($1);
                $itemXml =~ s/<\/SmallImage>/<\/SmallImage>\r/g;
                $itemXml =~ s/<\/MediumImage/<\/MediumImage>\r/g;
                $itemXml =~ s/<\/LargeImage/<\/LargeImage>\r/g;
                if($itemXml =~ s/<SmallImage>([^\r]*)<\/SmallImage>//){
                    if($1 =~ m/<URL>(.*)<\/URL>/){
                        if($isbn && $isbn->as_isbn10->as_string([])){
                            $ret->{$isbn->as_isbn10->as_string([])}->{"small"} =$1;
                        }
                        if($isbn && $isbn->as_isbn13->as_string([])){
                            $ret->{$isbn->as_isbn13->as_string([])}->{"small"} =$1;
                        }
                    }
                }
               if($itemXml =~ s/<MediumImage>([^\r]*)<\/MediumImage>//){
                    if($1 =~ m/<URL>(.*)<\/URL>/){
                        if($isbn && $isbn->as_isbn10->as_string([])){
                            $ret->{$isbn->as_isbn10->as_string([])}->{"medium"} =$1;
                        }
                        if($isbn && $isbn->as_isbn13->as_string([])){
                            $ret->{$isbn->as_isbn13->as_string([])}->{"medium"} =$1;
                        }
                    }
               }
               if($itemXml =~ s/<LargeImage>([^\r]*)<\/LargeImage>//){
                    if($1 =~ m/<URL>(.*)<\/URL>/){
                        if($isbn && $isbn->as_isbn10->as_string([])){
                            $ret->{$isbn->as_isbn10->as_string([])}->{"large"} =$1;
                        }
                        if($isbn && $isbn->as_isbn13->as_string([])){
                            $ret->{$isbn->as_isbn13->as_string([])}->{"large"} =$1;
                        }
                    }
               }
            }            
        }
    }

    return $ret;

     
}
#-----------------------------------------------------------------------------
# Tue, May 26, 2009 @ 15:06:43 EDT
# create AWS url which includes signature for authentication 
# reference at http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/
#
#-----------------------------------------------------------------------------
sub createAWS_url{
  my ($isbnList,$accesskey,$secretKey)=@_;

    my $tm = gmtime;
    my $timestamp = sprintf("%04d-%02d-%02dT%02d:%02d:%02dZ", $tm->year+1900, ($tm->mon)+1, $tm->mday,$tm->hour,$tm->min,$tm->sec);
    $timestamp =uri_escape($timestamp);
    $isbnList =~ s/,$//g;
    $isbnList =uri_escape($isbnList);
    
    my $params=
    "AWSAccessKeyId=$accesskey".
    "&ItemId=$isbnList" .
    "&Operation=ItemLookup".
    "&ResponseGroup=Images" .
    "&Service=AWSECommerceService&Timestamp=$timestamp";

     my $str2Sign="GET\n".
    "webservices.amazon.com\n" .
    "/onca/xml\n$params";


    my $url= "http://webservices.amazon.com/onca/xml?$params" ;
    my $signature="";
    if($secretKey && $secretKey ne ''){
        $signature=hmac_sha256_base64($str2Sign, $secretKey);
        while (length($signature) % 4) { #padding
                    $signature .= '=';
        }
    }
    #$signature  = uri_escape($signature);
    $signature =~ s/\+/%2B/g;
    $signature =~ s/\=/%3D/g;
    if($signature ne ''){
        $url .="&Signature=$signature";
    }
    return $url;      
     
}

#=======================================================
sub bookCover_amazon{
    my($recs,$awsId,$awsSecretKey)=@_;
    my $recList=(ref($recs) eq 'ARRAY')?$recs:[$recs];
    my $isbnList="";
    my $isbnFixTbl={};
    foreach my $r(@$recList){
        foreach my $i(@{$r->{'isbn'}}){
            $isbnFixTbl->{$i->{'item'}}=_fixISBN($i->{'item'});
            $isbnList .= "," . $isbnFixTbl->{$i->{'item'}};
        }
    }
    if($isbnList ne ''){
        my $bookCoverUrls = bookCover_getUrl($isbnList, $awsId, $awsSecretKey);
        foreach my $rec(@$recList){
            foreach my $i(@{$rec->{'isbn'}}){
                my $isbnfixed=$isbnFixTbl->{$i->{'item'}};
                if($bookCoverUrls->{$isbnfixed}){
                    if($bookCoverUrls->{$isbnfixed}->{'small'}){
                        $rec->{'bookcoverURL'}=$bookCoverUrls->{$isbnfixed}->{'small'};
                    }
                    last;
                }
            }
        }
    }
}
#=======================================================
sub bookCover_syndetics{
    my($recs,$size,$caption)=@_;
    my $recList=(ref($recs) eq 'ARRAY')?$recs:[$recs];

    foreach my $rec(@$recList){
        my $isbnList="";
        foreach my $i(@{$rec->{'isbn'}}){
            $isbnList .= "," if($isbnList ne '');
            $isbnList .= $i->{'item'};
        }
       $size    = 'sc' if(!defined $size || $size !~ m/sc|mc/g);
       $caption = 0    if(!defined $caption || $caption !=1);

        if($isbnList ne ''){
            $rec->{'bookcoverURL'}="/bin/search/bookcover?size=$size&isbn=$isbnList&capMore=$caption" ;
            $rec->{'booktocURL'}="http://www.syndetics.com/index.aspx?isbn=$isbnList/index.html&client=nysbsls&type=rn12";
        }
    }
}
#=======================================================
sub bookCover_google{
    my($recs,$size)=@_;
    bookCover_opals($recs,$size);
=item    
    my $recList=(ref($recs) eq 'ARRAY')?$recs:[$recs];
    my $isbn="zzzz";
    foreach my $rec(@$recList){
        $isbn="";
        $isbn = _fixISBN($rec->{'isbn_first'}) if($rec->{'isbn_first'} ne '');
        $isbn = "zzzz"  if($isbn eq '');        
        $rec->{'bookcoverURL'}="http://books.google.com/books?printsec=frontcover&frontcover&img=1&zoom=1&vid=ISBN$isbn" ;
        
    }
=cut    
}
#=======================================================
sub bookCover_opals{
    my($recs,$size)=@_;
    my $recList=(ref($recs) eq 'ARRAY')?$recs:[$recs];
    my @isbnList=();
    my @cidList=();
    foreach my $rec(@$recList){
        if(defined $rec->{'cid'} && $rec->{'cid'}>0){
            push @cidList,$rec->{'cid'};
        }
        elsif(defined $rec->{'isbn'} &&  ref($rec->{'isbn'}) eq 'ARRAY' && scalar(@{$rec->{'isbn'}})>0){
            foreach my $i(@{$rec->{'isbn'}}){
                next if(ref($i) ne 'HASH'); 
                $i->{'item'}=_fixISBN($i->{'item'});
                push @isbnList,$i->{'item'};
            }
            if(!defined $rec->{'isbn_first'} || $rec->{'isbn_first'} eq "" && scalar(@isbnList)>0){
                $rec->{'isbn_first'} =@{$rec->{'isbn'}}[0]->{'item'};
            }
        }
        elsif(defined $rec->{'rid'} && $rec->{'rid'}>0){
            my $cid=_getRecCid($rec->{'rid'});
            if(defined $cid){
                $rec->{'cid'}=$cid;
                push @cidList,$rec->{'cid'};
            }

        }
    
    }

    my $param={};
    $param->{'isbnList'}= join(",",@isbnList) if(scalar(@isbnList)>0);
    $param->{'cidList'} = join(",",@cidList) if(scalar(@cidList)>0);
    $param->{'size'}=$size if(defined $size);
       # open debug,">/tmp/bc"; print debug $param->{'isbnList'}."\n";close debug;
    my $tnList          = _getOpalsBookCover($param);
    foreach  my $rec(@$recList){
        if($rec->{'cid'} && defined $tnList->{'tnTbl_cid'} && $tnList->{'tnTbl_cid'}->{$rec->{'cid'}}){
            $rec->{'bookcoverURL'}=$tnList->{'tnTbl_cid'}->{$rec->{'cid'}};
        }
        elsif(defined $rec->{'isbn'} &&  ref($rec->{'isbn'}) eq 'ARRAY' && scalar(@{$rec->{'isbn'}})>0){
            foreach my $i(@{$rec->{'isbn'}}){
                next if(ref($i) ne 'HASH');
                my $isbn=$i->{'item'};
                my $isbn_13=formtatToIsbn13($isbn);
                if($tnList->{'tnTbl_isbn'}->{$isbn}){
                    $rec->{'bookcoverURL'}=$tnList->{'tnTbl_isbn'}->{$isbn};
                }
                else{
                    my $isbn_13=formtatToIsbn13($isbn);
                    if(defined $isbn_13 && $tnList->{'tnTbl_isbn'}->{$isbn_13}){
                        $rec->{'bookcoverURL'}=$tnList->{'tnTbl_isbn'}->{$isbn_13};
                    }
                }
                last if($rec->{'bookcoverURL'});
                
            }
        }
        # default to google thumbnail if not found on OPALS thumbnaul server.
        if(!defined $rec->{'bookcoverURL'} || $rec->{'bookcoverURL'} eq'' ){
            my $isbn_first="zzzz";
            if(defined $rec->{'isbn_first'} && $rec->{'isbn_first'} ne ""){
                $isbn_first= _fixISBN($rec->{'isbn_first'} );  
            }
            $rec->{'bookcoverURL'}="http://books.google.com/books?printsec=frontcover&frontcover&img=1&zoom=1&vid=ISBN$isbn_first" ;
        }
    }
     
}

#=======================================================
sub _getRecCid{
    my($rid)=@_;
    my $cid=undef;
    my $xml=util_getXmlRecord($rid);
    if($xml && $xml=~ m/<controlfield tag="004">(.*)<\/controlfield>/g){
        $cid=$1;
    }
    return $cid;    
}

#=======================================================

sub  _getOpalsBookCover{
    my($params)=@_;
     # my $ebs_host    = $params->{'ebs_host'};
     # http://thumbnail.hati.opalsinfo.net/bin/ws/eService?isbnList=9780000000002,9721842363542
    my $ebs_host      = "bookcover.opalsinfo.net";
    my $url            = "http://$ebs_host/bin/ws/eService" ;
    $params->{'serviceName'}="getBookcoverURL";
    
    my $response = http_post($url,$params);
    my $rsXml = $response->{'content'};
    my $ret =undef;
    my $bookCoverList=undef;
    if($rsXml =~ m/<errorCode>(.*?)<\/errorCode>/){
        $ret->{'errorCode'}=$1;
        if($ret->{'errorCode'}==0){
            if($rsXml =~ m/<bookCoverList>(.*)<\/bookCoverList>/s){
                my $itemXml=$1;
                while($itemXml =~  s/<item isbn="(.*)" oplCoverId="([\d]+)">(.*)<\/item>//){
                    my ($isbn,$cid,$url)=($1,$2,$3);
                    if($isbn ne ""){
                        $ret->{'tnTbl_isbn'}->{$isbn}=$url;
                    }
                    $ret->{'tnTbl_cid'}->{$cid}=$url;
                   
                }
            }
        }
    }

    return $ret;


}
#////////////////////////////////////////////////////////////////////////////
sub _fixISBN{
    my($isbn)=@_;
    $isbn=~ m/([\D^x^X]*)([\dxX][\dxX -]{8,}[\dxX])([\D^x^X]*)/;
    $isbn= $2;
    $isbn=~ s/[- ]//g;
    return $isbn; 
}
################################################################################
sub bookCover_upload{
   my($params)=@_;
    my $ebs_host      = "bookcover.opalsinfo.net";
    my $url           = "http://$ebs_host/bin/ws/eService" ;
    $params->{'serviceName'}="uploadBookCover";
    my $response = http_post($url, $params);
        my $rs = $response->{'content'} || return undef;
    return $rs; 
}
################################################################################
sub http_post {
    my ($postURL, $postContent) = @_;

    my $ua = LWP::UserAgent->new();
    $ua->agent('OPALS Web Service Client');
    $ua->timeout(20);

    my $result = {
        status  => 0,
        error   => '',
        content => '',
    };

    my $response = $ua->request(
        POST "$postURL",
        Content_Type => 'multipart/form-data', 
        Content => $postContent
    );

    if ($response->is_error() || !$response->is_success){
        $result->{'error'} = "connection error";
    }
    else {
        my $responseXml = $response->content;
        if ($responseXml =~ m/<status>(.*)<\/status>/i){
            $result->{'status'}= $1;
            if ($result->{'status'} ne '1'){
                if ($responseXml =~ m/<error>(.*)<\/error>/i){
                    $result->{'error'}= $1;
                }
            }
        }

        $result->{'content'} = $responseXml;
    }

    return $result;
}
################################################################################
sub formtatToIsbn13{
    my($isbn)= @_;
    $isbn=~ m/([\D^x^X]*)([\dxX][\dxX -]{8,}[\dxX])([\D^x^X]*)/;
    $isbn= $2;
    $isbn=~ s/[- ]//g;
    return $isbn if(length($isbn)== 13);
    eval{
            $isbn=~ s/^([\D]*)([0-9]+)(.*)/$2/g;
            my $isbn_obj = Business::ISBN->new($isbn) ;
            my $isbn13 = $isbn_obj->as_isbn13;
            $isbn13 = $isbn13->as_string([]);
            return $isbn13;
            } 
     or {
         return undef
      };
}


1;

