package WSParser;


@ISA = qw(Exporter);

@EXPORT = ();
@EXPORT_OK = qw(
	parse_onca_response
	       );

%EXPORT_TAGS = ();

require Exporter;

use strict;
use XML::Parser;

###############################################################

my $products;
my $new_product;
my $current_element;
my %element_counts;
my $value;

my $product_tag = "Details"; # tag delimiting each product
my $common_start = "ProductInfo.Details."; # all elements w/in a product begin with this

###############################################################

# normally, something like ProductInfo.Details.BrowseList.BrowseNode
# would get parsed under "BrowseList.BrowseNode" in the hash.
# If the property might have multiple elements per product, just add
# the property to the plural_elements hash below.  This will have each
# element parsed so that the first occurrence shows up as
# "BrowseList.BrowseNode-1",
# the second as "BrowseList.BrowseNode-2", etc.

my %plural_elements;
$plural_elements{'ProductInfo.Details.BrowseList.BrowseNode'}   = 1;
$plural_elements{'ProductInfo.Details.Reviews.CustomerReview'}  = 1;
$plural_elements{'ProductInfo.Details.Similarities.Similarity'} = 1;
$plural_elements{'ProductInfo.Details.Authors.Author'} = 1;
$plural_elements{'ProductInfo.Details.Starring.Actor'} = 1;


###############################################################
# parse the response into an array of hashes, one hash per item
###############################################################

sub parse_onca_response_into_aoh
{
    my $xml_response = shift;
    $products        = shift;

    my $p1 =
    new XML::Parser(Handlers =>
        {Start => \&handle_start,
         End   => \&handle_end,
         Char  => \&handle_char});

    $p1->parse($xml_response);
}

###############################################################
# parse the response into a hash of hashes, one hash per item.
# outer hash is indexed by ASIN
###############################################################

sub parse_onca_response_into_hoh
{
    my $xml_response  = shift;
    my $products_hash = shift;
    my @temp_array;

    parse_onca_response_into_aoh($xml_response, \@temp_array);

    for (my $ix = 0; $ix <= $#temp_array; $ix++)
    {
        $products_hash->{$products->[$ix]->{'Asin'}} = $products->[$ix];
    }
}


############################################################
# code to handle parsing of the elements
############################################################

sub handle_start
{
    my ($a, $arg) = @_;

    if ($current_element ne '') { $current_element .= '.'; }
    $current_element .= $arg;
    $element_counts{$current_element}++;

    if ($plural_elements{$current_element})
    {
        $current_element .= "-$element_counts{$current_element}";
    }
}

sub handle_end
{
    my ($a, $arg) = @_;

    # strip undesired characters
    $value =~ s/\n//g;
    $value =~ s/^ *//g;

    # translate encoded characters
    $value =~ s/\&lt;/</g;
    $value =~ s/\&gt;/>/g;
    if ($arg eq $product_tag)
    {
        # we're done w/ one product.
        # push it onto our list and set our
        # structures up for the next one

        push @{$products}, $new_product;
        $new_product = {};
        foreach my $key (keys %element_counts)
        {
            $element_counts{$key} = 0;
        }
    }
    else
    {
        # add an attribute to the current product hash
        # strip off the common start to simplify our keys
        my $element = $current_element;
        if ($current_element =~ /^$common_start(.*)/)
        {
            $element = $1;
        }

        $new_product->{$element} = $value;
    }
    $value = "";

    # erase one level of depth in our element name
    if ($current_element =~ /(.*)\./)
    {
        $current_element = $1;
    }
    else { $current_element = ''; }
}

sub handle_char
{
    my ($a, $arg) = @_;

    $value .= $arg;
}


1;
