package GCPlugins::GCmusics::GCMusicBrainz;

###################################################
#
#  Copyright 2005-2010 Christian Jodar
#
#  This file is part of GCstar.
#
#  GCstar 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.
#
#  GCstar 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 GCstar; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
###################################################

use strict;
use utf8;

use GCPlugins::GCmusics::GCmusicsCommon;

{
    package GCPlugins::GCmusics::GCPluginMusicBrainz;

    use base 'GCPlugins::GCmusics::GCmusicsPluginsBase';
    use XML::Simple;
    use Locale::Country;

    sub parse
    {
        my ($self, $page) = @_;
        my $xml;
        my $xs = XML::Simple->new;
        if ($self->{parsingList})
        {
            $xml = $xs->XMLin($page,
                              ForceArray => ['release', 'event'],
                              KeyAttr => {'release' => ''});
            my $release;
            foreach $release ( @{ $xml->{'release-list'}->{release} } )
            {
                $self->{itemIdx}++;
                $self->{itemsList}[$self->{itemIdx}]->{url} = 'http://musicbrainz.org/album/'.$release->{id}.'.html';
                $self->{itemsList}[$self->{itemIdx}]->{title} = $release->{title};
                $self->{itemsList}[$self->{itemIdx}]->{artist} = $release->{artist}->{name};
                    
                my $releaseDate='9999-12-31';
                for my $releaseEvent (@{$release->{'release-event-list'}->{event}})
                {
                    if ($releaseEvent->{date} lt $releaseDate)
                    {
                        # Find the earliest release event
                        $releaseDate = $releaseEvent->{date};
                    }
                }
                
                $self->{itemsList}[$self->{itemIdx}]->{release} = $releaseDate
                    if $releaseDate ne '9999-12-31';    
            }
        }
        else
        {
            $xml = $xs->XMLin($page,
                              ForceArray => ['track', 'event', 'relation', 'relation-list','tag'],
                              KeyAttr => {'track' => ''});
            $self->{curInfo}->{title} = $xml->{release}->{title};
            $self->{curInfo}->{web} = 'http://musicbrainz.org/release/'.$xml->{release}->{id}.'.html';
            $self->{curInfo}->{artist} = $xml->{release}->{artist}->{name};
            $self->{curInfo}->{ratingpress} = int($xml->{release}->{rating}->{content}) * 2;
            $self->{curInfo}->{producer} = '';
            $self->{curInfo}->{composer} = '';

            # Step through the relations
            for my $relation (@{$xml->{release}->{'relation-list'}})
            {
                if ($relation->{'target-type'} eq 'Artist')
                {
                    # Artist type relations
                    for my $rel (@{$relation->{relation}})
                    {
                        # Search for producer or composer relations                        
                        $self->{curInfo}->{producer} .= $rel->{artist}->{name}.', '
                            if $rel->{type} eq 'Producer';
                        $self->{curInfo}->{composer} .= $rel->{artist}->{name}.', '
                            if $rel->{type} eq 'Composer';                    
                    }
                }
                elsif ($relation->{'target-type'} eq 'Url')
                {   
                    # Look for url type relations. Currently only jamendo works, but we should also cover the archive.org
                    # relations         
                    for my $rel (@{$relation->{relation}})
                    {   
                        # Alternate cover art sites             
                        if (($rel->{target} =~ m/jamendo.com/) && (!$self->{curInfo}->{cover}))
                        {
                            # Cover art should be on jamendo
                            $rel->{target} =~ /\/([0-9]+)$/;
                            my $id = $1;
                            if ($self->{bigPics})
                            {
                                $self->{curInfo}->{cover} = "http://img.jamendo.com/albums/$id/covers/1.0.jpg";
                            }
                            else
                            {
                                $self->{curInfo}->{cover} = "http://img.jamendo.com/albums/$id/covers/1.200.jpg";
                            }
                        }
                    }
                }
            }

            $self->{curInfo}->{producer} =~ s/, $//;
            $self->{curInfo}->{composer} =~ s/, $//;

            my $releaseDate;
            my $releaseLabel;
            my $releaseCountry;
            my $releaseFormat;
            my $releaseDateFromCompare='9999-12-12';
            for my $releaseEvent (@{$xml->{release}->{'release-event-list'}->{event}})
            {
                my $releaseDateToCompare;
                # Check if musicbrainz only has the year, if so, set things up so we'll prefer
                # releases with the month & day over year-only releases
                if (length($releaseEvent->{date}) == 4)
                {
                    $releaseDateToCompare = $releaseEvent->{date}."-12-31";
                }
                else
                {
                    $releaseDateToCompare = $releaseEvent->{date};                
                }

                if (($releaseDateToCompare lt $releaseDateFromCompare) ||
                        (($releaseDateToCompare eq $releaseDateFromCompare) && 
                            (($releaseEvent->{country} eq 'US') || ($releaseEvent->{country} eq 'GB'))))
                {
                    # Find the earliest release event, which has a month & day
                    # Big call, but we're probably more correct choosing a US or UK release if there's two
                    # release events with the same date, so prioritise them
                    $releaseDate = $releaseEvent->{date};
                    $releaseLabel = $releaseEvent->{label}->{name}
                        if $releaseEvent->{label};
                    $releaseCountry = code2country($releaseEvent->{country});
                    $releaseFormat = $releaseEvent->{format};
                    $releaseDateFromCompare = $releaseDateToCompare;
                }
            }
            
            $self->{curInfo}->{release} = $releaseDate;
            $self->{curInfo}->{label} = $releaseLabel;
            $self->{curInfo}->{origin} = $releaseCountry;
            $self->{curInfo}->{format} = $releaseFormat;
 
            for my $track(@{$xml->{release}->{'track-list'}->{track}})
            {
                $self->addTrack($track->{title}, $track->{duration} / 1000);
            }
            $self->{curInfo}->{tracks} = $self->getTracks;
            $self->{curInfo}->{running} = $self->getTotalTime;

            for my $genre(@{$xml->{release}->{'tag-list'}->{tag}})
            {                   
                # Capitalize first letter of each word
                $genre->{content} =~ s/\b(\w+)\b/ucfirst($1)/ge; 
                # Only add genres if they have more then 1 vote, strips out a lot of 
                # weird/wrong tags
                push @{$self->{curInfo}->{genre}}, [$genre->{content}]
                        if ($genre->{count} > 1);
            }
            
            # If amazon artwork exists, use it
            if (($xml->{release}->{asin}) && (!$self->{curInfo}->{cover}))
            {
                if ($self->{bigPics})
                {
                    $self->{curInfo}->{cover} = 'http://images.amazon.com/images/P/'.$xml->{release}->{asin}.'.01.LZZZZZZZ.jpg'
                }
                else
                {
                    $self->{curInfo}->{cover} = 'http://images.amazon.com/images/P/'.$xml->{release}->{asin}.'.01.MZZZZZZZ.jpg'
                }
            }                    
        }
    }

    sub convertDate
    {
        my ($self, $date) = @_;
        $date =~ /([0-9]{4})-?([0-9]{2})?-?([0-9]{2})?/;
        return $3 .($3 ? '/' : '').$2.($2 ? '/' : '').$1;
    }

    sub new
    {
        my $proto = shift;
        my $class = ref($proto) || $proto;
        my $self  = $class->SUPER::new();
        bless ($self, $class);

        $self->{hasField} = {
            title => 1,
            artist => 1,
            release => 1,
            tracks => 1
        };

        return $self;
    }

    sub preProcess
    {
        my ($self, $html) = @_;

        return $html;
    }
    
    sub decodeEntitiesWanted
    {
        return 0;
    }

    sub getSearchUrl
    {
		my ($self, $word) = @_;
	
        my $key = ($self->{searchField} eq 'artist') ? 'artist' : 'title';
        return "http://musicbrainz.org/ws/1/release/?type=xml&$key=$word";
    }
    
    sub getItemUrl
    {
		my ($self, $url) = @_;
        return $url if $url;
        return "http://musicbrainz.org/";
    }

    sub changeUrl
    {
        my ($self, $url) = @_;
        $url =~ s|http://musicbrainz.org/album/(.*?)\.html|http://musicbrainz.org/ws/1/release/$1?type=xml&inc=artist+tracks+release-events+artist-rels+url-rels+ratings+labels+tags|;
        $url =~ s|http://musicbrainz.org/release/(.*?)\.html|http://musicbrainz.org/ws/1/release/$1?type=xml&inc=artist+tracks+release-events+artist-rels+url-rels+ratings+labels+tags|;
        return $url;
    }

    sub getName
    {
        return 'MusicBrainz';
    }
    
    sub getAuthor
    {
        return 'Tian';
    }
    
    sub getLang
    {
        return 'EN';
    }

    sub getCharset
    {
        my $self = shift;
    
        return "UTF-8";
    }
    
    sub getSearchCharset
    {
        my $self = shift;

        # Need urls to be double character encoded
        return "utf8";
    }

    sub convertCharset
    {
        my ($self, $value) = @_;
        return $value;
    }

    sub getNotConverted
    {
        my $self = shift;
        return [];
    }

    sub getSearchFieldsArray
    {
        return ['title', 'artist'];
    }
    
    sub isPreferred
    {
        # Return status of 2 means plugin is default regardless of user's language
        return 2;
    }
}

1;
