#!/usr/bin/perl -w

# This program shows how to use the SOAP::Lite package (available from http://www.soaplite.org),
# to make an AWS request and to process the response. 
# The program was tested with version 0.50 of SOAP::Lite and should also work with more recent versions

use strict;
use W3C::SPDL::Lite;

my $susbscription_id = "0FWYBWB91M5S26YBE382";
# my $aws_wsdl = "http://webservices.amazon.com/AWSECommerceService/2004-11-10/AWSECommerceService.wsdl";
my $aws_wsdl = "file:///home/eric/sources/public/perl/modules/W3C/SPDL/descriptions/AWSECommerceService-SPDL.wsdl";

main();

# Expects keywords as command line arguments
sub main {
  # read from command line
  my (@keywords) = @ARGV or die "Usage: itemsearch_soap <KEYWORDS [Space seperated list]> \n";

  # Create a string from the keywords
  my $keywords = join " ", @keywords;
  
  # Make the request and receive a SOAP::SOM object in return
  my $som = make_request($keywords);

  # Ensure that the request succeeded
  die_if_error($som);

  # If there are no results then print message and exit
  if (get_total_results($som) == 0) {
    print "There are no results for this query.\n";
    exit;
  }

  # Iterate through all child nodes of element Items and parse all the Item nodes
  my $node_num = 1;
  while($som->match("//Items/[$node_num]")) {
    $node_num++;

    # If element ItemAttributes is not under this [node number = $node_num] child node of Items, then this node is not an Item node, thus skip
    next unless $som->match("//Items/[$node_num]/ItemAttributes");  
 
    my @authors = $som->valueof("//Items/[$node_num]/ItemAttributes/Author");
    my $item = $som->valueof("//Items/[$node_num]");
    parse_item($item, \@authors);
  }

}

# Function takes the Keywords
# It returns a SOAP::SOM object for the response
sub make_request {
  my ($keywords) = @_ or die "Incorrect number of arguments passed to make_request \n";

  # constructing request complex type. Thus want following xml output
  # <Request>
  #     <Keywords>$keywords</Keywords>
  #     <SearchIndex>Books</SearchIndex>
  # </Request>
  # $request_compolex_type is a reference to everything within the <Request> tag
  my $request_complex_type = \SOAP::Data->value(
					    SOAP::Data->name('Keywords')
					              ->value($keywords),
					    SOAP::Data->name('SearchIndex')
					              ->value('Books'));

  # constructing the entire ItemSearch request. Thus want following xml output
  # <SubscriptionId>$subscription_id</SubscriptionId>
  # <Request>
  #     <Keywords>$keywords</Keywords>
  #     <SearchIndex>Books</SearchIndex>
  # </Request>
  my $itemsearch_request = SOAP::Data->value(
				     SOAP::Data->name('SubscriptionId')
					       ->value($susbscription_id),
  				     SOAP::Data->name('Request')
					       ->value($request_complex_type));


  # create new SOAP::Lite instance
  my $aws_handle = W3C::SPDL::Lite->service("$aws_wsdl");

  # invoking AWS::ItemSearch
  $aws_handle->ItemSearch($itemsearch_request); 
  my $som = $aws_handle->call();  # When using a wsdl, SOAP::Lite returns the actual data from the server,
                                  # not the SOAP::SOM object. The call() method returns the SOM object
                                  # for the previous response.
  return $som;
}

# Function takes an 'Item' node and an array of author names, and prints the Title, Author(s) and ASIN of the Item
sub parse_item {
  my ($item, $authors) = @_;  
  print "Title: $item->{ItemAttributes}->{Title} \n";
  if(@$authors > 1) {
    print "Authors: ";
  }else {
    print "Author: ";
  }
  print ( (join ", ", @$authors) , "\n");  

  print "ASIN: $item->{ASIN} \n\n";

  # print a line
  print "-" x 80, "\n";
}

# Function checks if the response is valid. If it isn't, then it prints an error message and dies
sub die_if_error {
  my $som = shift;
  my $is_valid = $som->valueof("//IsValid");
  if ($is_valid eq "False") {
    die "Error: ", $som->valueof('//Error/Message'), "\n";
  }
}

# Function returns the total number of results found for the query
sub get_total_results {
  my $som = shift;
  return $som->valueof("//TotalResults");
}

