#!/usr/bin/perl -w

# If you don't have these perl modules, please try to install by following way.
# sudo perl -MCPAN -eshell 'install Net::Amazon'
# sudo perl -MCPAN -eshell 'install URI::Escape'
# sudo perl -MCPAN -eshell 'install Cache::File'
# sudo perl -MCPAN -eshell 'install Unicode::Japanese'
# sudo perl -MCPAN -eshell 'install Log::Log4perl'

# Required Modules
use URI::Escape;
use Cache::File;
use Unicode::Japanese;
use LWP::UserAgent;
use Getopt::Long;
use Log::Log4perl qw(:easy);
use Net::Amazon;

# amazon token (AWS ID)
my %opt           = ();
$opt{token}       = '';

# AWS ID from /etc
$rc = '/etc/ama2bibrc';
if (-r $rc){
    open(FIN, "<$rc");
    while (<FIN>){
	next if (m/^\#/);
	if (m/^ID:[\t ]+(.*)$/){
	    $opt{token} = $1;
	    last;
	}
    }
    close(FIN);
}

# AWS ID from user dir (~/.ama2bibrc)
$rc = "$ENV{'HOME'}/.ama2bibrc";
if (-r $rc){
    open(FIN, "<$rc");
    while (<FIN>){
	next if (m/^\#/);
	if (m/^ID:[\t ]+(.*)$/){
	    $opt{token} = $1;
	    last;
	}
    }
    close(FIN);
}

# Program info
my $author  = 'Thor Watanabe <thormac(at)gmail(dot)com>'; 
my $version = '1.0';
my $date    = '2007/06/29';
my $year    = '2005, 2007';

# Default settings
my $base_url     = 'http://www.amazon.co.jp/exec/obidos/ASIN/';
my $media        = 'books';
my $author_delim = 'and';
my $uri_encoding  = 'utf8';

# Command line options
my @opt_asins     = ();
$opt{cachetime}   = '30 min';
$opt{debug}       = 0;
$opt{encoding}    = 'utf8';
$opt{foldercache} = '/tmp/ama2bib';
$opt{gpl}         = 0;
$opt{help}        = 0;
my @opt_isbns     = ();
$opt{keywords}    = 0;
$opt{locale}      = 'jp';
$opt{maxpage}     = 3;
$opt{name}        = 0;
$opt{output}      = 0;
$opt{proxy}       = 0;
$opt{similar}     = 0;
$opt{stdout}      = 0;
$opt{version}     = 0;
$opt{wishlist}    = 0;

&get_options ();
&analyze_options ();
&open_output ();
&search_books ();
&close_output ();
exit (0);

sub print_bibtex {
    my $results = $_[0];
    my $suf = "\},\n";
    my $pre = " =\t \{";
    for $entry ($results->properties){
	my $price = $entry->ListPrice ();
	my @authors = $entry->authors ();
	
	&print_bib ("\@book\{" . $entry->Asin() . ",\n");
	&print_bib ("  author" . $pre);
	if ($entry->author ()){
	    &print_bib ($entry->author()); shift (@authors);
	    foreach $author (@authors){
		&print_bib (" $author_delim $author");
	    }
	} else {
	    &print_bib ("Creator");
	}
	&print_bib ($suf .  
	"  title" . $pre . $entry->ProductName() . $suf);
	if ($entry->edition()){
	    &print_bib ("  edition" . $pre . $entry->edition() . $suf);
	}
	&print_bib ( 
	    "  year" . $pre .      $entry->year() .         $suf .
	    "  publisher" . $pre . $entry->Manufacturer() . $suf .
	    "  ASIN" . $pre .      $entry->Asin() .         $suf .
	    "  ISBN" . $pre .      $entry->isbn() .         $suf .
	    "  EAN =\t\t \{" .     $entry->ean() .          $suf .
	    "  URL =\t\t \{".      $base_url . $entry->Asin() . "/" . $suf .
	    "  price" . $pre . $price . $suf . 
	    "\}\n");
    }
}

sub search_books {
    my $cache = Cache::File->new (
	cache_root => $opt{foldercache},
	default_expires => $opt{cachetime});
    
    my $agent = LWP::UserAgent->new ();
    
    my $ua = Net::Amazon->new (
	max_pages => $opt{maxpage}, 
	token => $opt{token}, 
	locale => $opt{locale},
	cache => $cache,
	ua => $agent);

    my $results = 0;

    if ($#opt_asins ge 0){
	my $req = Net::Amazon::Request::ASIN->new
	    (asin =>  [ @opt_asins ], mode => $media);
	$results = $ua->request ($req);
    } elsif ($#opt_isbns ge 0){
	$results = $ua->search (asin => [ @opt_isbns ], mode => $media);
    } elsif ($opt{keywords}){
	my $keywords = 
	    uri_escape (Unicode::Japanese->new
			($opt{keywords}, $uri_encoding)->get);
	$results = $ua->search (keyword => $keywords, mode => $media);
    } elsif ($opt{name}){
	my $authors = 
	    uri_escape (Unicode::Japanese->new
			($opt{name}, $uri_encoding)->get);
	$results = $ua->search (author => $authors, mode => $media);
    } elsif ($opt{wishlist}){
	my $req = Net::Amazon::Request::Wishlist->new
	    (wishlist => $opt{wishlist}, mode => $media);
	$results = $ua->request ($req);
    } elsif ($opt{similar}){
	my $req = Net::Amazon::Request::Similar->new
	    (similar => $opt{similar}, mode => $media);
	$results = $ua->request ($req);
    } else {
	&print_usage (); exit;
    }

    if (!$results){
	&print_usage ();
    } elsif ($results->is_success ()){
	&print_bibtex ($results);
    } else {
	print STDERR "Error: ", $results->message (), "\n";
    }

}

sub print_debug {
  print "\@opt_asins($#opt_asins)\t "; 
  foreach (@opt_asins){ print "\"$_\" "; }
  print "\n";
  print "\@opt_isbns($#opt_isbns)\t "; 
  foreach (@opt_isbns){ print "\"$_\" "; }
  print "\n";
  foreach (keys %opt) {
      print "\$opt{$_}\t $opt{$_}\n";
  }
  print "\n";
}

sub print_usage { 
    print 
 "ama2bib $version: convert Amazon book info to BibTeX entry\n",
 "  (using Net::Amazon - Framework for accessing amazon.com)\n",
 "  Copyright $year $author\n", 
 "  This is free software with ABSOLUTELY NO WARRANTY.\n", 
 "  for more details use with -g/--gpl option.\n", 
 "\n", 
 "usage: ama2bib [options]\n", 
 "please select an option from -a, -i, -k, -n, -s, -w exclusively.\n", 
 "  -a --asin <ASIN,...>       search books by ASIN(s)\n", 
 "  -c --cache <time>          set chache time ('30 min')\n", 
 "  -d --debug                 print debug info\n", 
 "  -e --encoding <string>     select encoding ('utf8')\n",   
 "                             [utf8 euc-jp shift_jis 7bit-jis]\n", 
 "  -f --folder <dir>          select cache directory\n", 
 "  -g --gpl                   print warranty\n", 
 "  -h --help                  print this usage and exit\n", 
 "  -i --isbn <ISBN,...>       search books by ISBN(s)\n", 
 "  -k --keywords <keywords>   search books by keyword(s)\n", 
 "  -l --locale <locale>       select locale ('jp')\n", 
 "                             [ca de fr jp uk us]\n", 
 "  -m --maxpage <num>         change max page per query (3)\n", 
 "  -n --name <author>         search books by author name\n", 
 "  -o --outfile <filename>    output file name (stdout)\n", 
 "  -p --proxy <proxy>         set proxy setting\n", 
 "  -s --similar <ASIN>        search books similar to ASIN\n",
 "  -t --token                 set your AWS ID token\n", 
 "  -v --version               print version information and exit\n",
 "  -w --wishlist <num>        list all books by wishlist number\n", 
}

sub print_version {
    print "ama2bib $version\n", 
}

sub print_warranty {
$warranty = <<'__EOF__';
This program 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.

This program 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 this program. If not, write to
    
   The Free Software Foundation, Inc.
   59 Temple Place, Suite 330
   Boston, MA 02111, USA.
__EOF__

    print $warranty;
}

sub open_output {
    if ($opt{output}){
	open (FILEOUT, ">:encoding($opt{encoding})", $opt{output}) or die;
    } else {
	binmode (STDOUT, ":encoding($opt{encoding})");
    }
}

sub print_bib {
    if ($opt{output}){
	print FILEOUT $_[0];
    } else {
	print STDOUT $_[0];
    }    
}

sub close_output {
    if ($opt{output}){
	close (FILEOUT);
    }
}

sub analyze_options {
    if ($opt{proxy}){
	$ENV{http_proxy} = $opt{proxy};
    }
    if ($opt{debug}){
	&print_debug(); 
	if ($opt{debug} ge 2){
	    Log::Log4perl->easy_init($DEBUG);
	}
    }
    if ($opt{gpl}){ 
	&print_warranty(); exit;
    }
    if ($opt{help}){
	&print_usage(); exit;
    }
    if ($opt{version}){
	&print_version(); exit;
    }
}

sub get_options {
    GetOptions (
	'asin=s'     => \@opt_asins, 
	'cache=s'    => \$opt{cachetime},
	'debug+'      => \$opt{debug},
	'encoding=s' => \$opt{encoding},
	'folder=s'   => \$opt{foldercache},
	'gpl'        => \$opt{gpl}, 
	'help'       => \$opt{help}, 
	'isbn=s'     => \@opt_isbns, 
	'keyword=s'  => \$opt{keywords}, 
	'locale=s'   => \$opt{locale}, 
	'maxpage=i'  => \$opt{maxpage},
	'name=s'     => \$opt{name}, 
	'outfile=s'  => \$opt{output},
	''           => \$opt{stdout},
	'proxy=s'    => $opt{proxy}, 
	'similar=s'  => \$opt{similar}, 
	'token=s'    => \$opt{token}, 
	'version'    => \$opt{version}, 
	'wishlist=s' => \$opt{wishlist} 
	);

    @opt_asins    = split(/,/, join (',', @opt_asins));
    @opt_isbns    = split(/,/, join (',', @opt_isbns));
}
