package AmazonMusicImage;

use strict;
use SOAP::Lite;#  +trace => 'debug';


sub new {
   my ($class, %args) = @_;
   my $self = bless {
      DEBUG => $args{"debug"},
      THRESHOLD => $args{"threshold"} || .60
   }, $class;
   if($self->{"THRESHOLD"} < .01 ||
      $self->{"THRESHOLD"} > 1.0) {
      warn "Illegal value for threshold. Defaulting to .60\n";
      $self->{"THRESHOLD"} = .60;
   }
   warn "Debug is turned on\nThreshold is set to: ", 
   $self->{"THRESHOLD"}, "\n"  if$self->
   {
      "DEBUG"
   };
   return $self;
}

sub clean {
#Gets rid of things like "Disc 1" from 
#the beginning or end of the album title
#That's just how I name multi disc sets -- 
#so you can change this freely to suit your
#environment
   my ($self, $album) = @_;
   return unless $album;

#First remove anything between (). 
#Use this one with caution. It Works For Me(TM)
   $album =~ s/\(.*\)//;
   $album =~ s/\(\)//;
   $album =~ s/\(.*//;
#Remove from front
   $album =~ s/^dis[ck]\W*\d+\W*//gi;
#And now from back
   $album =~ s/\W*dis[ck]\W*\d+\W*$//gi;

#Let's clean up any inconsistent punctuation
   $album =~ s/(,|\.|\;|:|\')//;

   return $album;
   ;
}

sub get_url{
#    if (!$image) {
#      $url = $a->get_url($tag, size=>"Medium", var=>"$various");
#      $image = get_image($url) if $url;
#    }
#    if (!$image) {
#      $url = $a->get_url($tag, size=>"Small", var=>"$various");
#      $image = get_image($url) if $url;
#    }
   my ($self,$artist,$album,$song,$various) = @_;
   my @allsize = ( 'Large', 'Medium', 'Small' );

   $album = $self->clean($album);
   return undef unless $album;
   my $keyword = ($various == 1) ? "$album": "$album $artist";
   if ($self->{"DEBUG"}){
      warn "Doing search for $keyword\n";
   }

   my $HOST   = "http://soap.amazon.com/onca/soap2";
   my $NS     = "http://soap.amazon.com";
   my $TOKEN         = "";
   my $ASSOCIATES_ID = "";
   my $MODE          = "music";
   my $PAGE          = 1;

   my $soap = SOAP::Lite
   ->readable(1)
   ->uri($NS)
   ->proxy($HOST);


   my $som = undef;

   eval{
      $som = $soap->KeywordSearchRequest(
                     SOAP::Data->name("ArtistSearchRequest")
                     ->value(\SOAP::Data->value( SOAP::Data->name("keyword" => "$keyword"),
                                                 SOAP::Data->name("page"    => $PAGE),
                                                 SOAP::Data->name("mode"    => $MODE),
                                                 SOAP::Data->name("tag"     => $ASSOCIATES_ID),
                                                 SOAP::Data->name("type"    => "heavy"),
                                                 SOAP::Data->name("devtag"  => $TOKEN),)));
   };

   warn "No match found in search\n" && return undef unless defined($som);

   for my $t ($som->valueof('//KeywordSearchRequestResponse/return/Details/Details')){
#Do some cleaning up on the album name first
      $t->{"ProductName"} = $self->clean($t->{"ProductName"});

      my @iurls;

      foreach my $size(@allsize) {
         if ($t->{"ImageUrl$size"}) {
            push(@iurls,$t->{"ImageUrl$size"});
         }
      }

      if ( ! @iurls ) {
         warn "No image found in search\n" && return undef unless defined($som);
      }
      if ($self->{"DEBUG"}){
         print "\n";
   #In case there's no artist name -- set it to something sane
         my $debug_artist = (exists $t->{"Artists"}) ? 
         @{$t->{"Artists"}}[0] : "Unknown";
         warn "Testing against: ", ($various == 1)? "":"$debug_artist - ", $t->{"ProductName"}, "\n";
      }
   #Let's sanitize mp3 tags for spaces
      map (s/^\s*//g, ($artist, $album));
      map (s/\s*$//g, ($artist, $album));

   #We lc() everything for comparison so case doesn't mess us up

   #warn "-",lc(@{$t->{"Artists"}}[0]),"-\n";
   #print "-",lc($artist),"-\n";
   #print "-",lc($t->{"ProductName"}),"-\n";
   #print "-",lc($album),"-\n";


   #Does everything match up?
      if ((lc(@{$t->{"Artists"}}[0]) eq lc($artist)) &&
          (lc($t->{"ProductName"}) eq lc($album))){
         if ($self->{"DEBUG"}){
            warn "Got a full match for $artist - $album\n";
         }
         return  @iurls;
      }

   #Artist/Album name isn't exact at this point
   #If the first song on the album is the same as the first song out of our
   #music dir, then we can guess that this is
   #the same album
      my $track = @{$t->{"Tracks"}}[0];
      if ($track){
   #Get rid of any punctuation first
   #It's too inconsistently used
         $track->{"TrackName"} = $self->clean($track->{"TrackName"});
         $song =~ $self->clean("$song");
         if (lc($track->{"TrackName"}) eq lc($song)){
            if ($self->{"DEBUG"}){
               warn "Got a song match for $artist - $album.\n";
            }
            return  @iurls;
         }
      }

   #Does the album title alone match up and is this a various
   #artist album?
      if ($various == 1){
         if ($self->{"DEBUG"}){
            warn "Checking for $album as a Various Artist album\n";
         }
         if (lc($t->{"ProductName"}) eq lc($album)){
            if ($self->{"DEBUG"}){
               warn "Got an album match for $album\n";
            }
            return  @iurls;
         }
      }


   #If we got this far there wasn't a match or there wasn't a track
   #listing for us to match up song titles with
   #We resort to a poor man's statistical analysis to see if we're even close

   #First we tokenize everything we know about the album/artist
      my (@my_tokens, @amazon_tokens, %seen);
      push (@my_tokens, split(/\s+/, $artist)) if ($various == 0);
      if ($self->{"DEBUG"}){
         warn "Not using artist name in statistical check\n" if ($various == 1);
      }
      push (@my_tokens, split(/\s+/, $album));
      my $am_artists = join(' ', @{$t->{"Artists"}});
      push (@amazon_tokens, split(/\s+/, $am_artists));
      push (@amazon_tokens, split(/\s+/, $t->{"ProductName"}));

      warn "MY TOKENS ARE: @my_tokens\n";

   #Now let's count the tokens and ignore common ones:
   #"a" and "the" and any nonwords
      map ($seen{lc($_)}++, grep(!/(\ba\b|the|\W)/i, @my_tokens));
      map ($seen{lc($_)}++, grep(!/(\ba\b|the|\W)/i, @amazon_tokens));

   #map {print "Key: $_, Value: ", $seen{$_},"\n"} keys %seen;

   #How many tokens did we see more than once?
      my $total = scalar(keys %seen);
      my $mult = grep(!/1/, values %seen);

   #If we passed the threshold, let's call it close enough
      my $thresh = $self->{"THRESHOLD"} ;
      if ($self->{"DEBUG"}){
         warn "Statistical match is: ",sprintf("%.3f",$mult/$total),"\n";
      }
      if ($mult/$total >= $thresh){
         if ($self->{"DEBUG"}){
            warn "Got a statistical match for $keyword\n";
            warn "Matched on: $am_artists - ", $t->{"ProductName"}, "\n";
         }
         return  @iurls;
      }
   }
#We got nothing if we got this far
   if ($self->{"DEBUG"}){
      warn "Got nothing for $keyword\n";
   }
   return undef;
}
1;
