#------------------------------------------------------------
# Copyright (C) 2009 RoyaltyShare, Inc.   All Rights Reserved
#------------------------------------------------------------

package Validate::Rule::Constraint::UniqueKeyValuePairs;
use strict;

use lib '/app/tools/common/lib';
use Common::Log;
use Common::RSApp;
use Common::Assert;

use lib '/app/tools/rps/lib';
use RPS::DB::Item::ArtistRole;

use lib '/app/tools/metadata/lib';
use base 'Validate';
use base 'Validate::Rule::Constraint::KeyValueList';

use vars qw($AUTOLOAD);

###
# Define addition public accessors
###
use constant kClassAttributes => qw( message parameter fail_status );

###
# Default failure message if the OK method fails.
###
use constant kFailureMessage => "Duplicate key=value pair";

sub ok {
    my $self  = shift;
    my $value = shift;

    my $fail =
      defined( $self->{_fail_status} )
      ? $self->{_fail_status}
      : Validate::kStatusDefault;
    my $success = Validate::kStatusOK;

    return undef unless ( $self->is_configured() );

    return $success unless ($value);

    my $parentStatus = $self->SUPER::ok($value);

    return $parentStatus
      if ( defined($parentStatus) && $parentStatus == $fail );

    my @artists = $self->_dataAsList($value);

    #    $self->message(kFailureMessage);
    return $self->_noDups( \@artists ) ? $success : $fail;

}

#------------------------------------------------------------
# Private Methods
#------------------------------------------------------------

sub _noDups {
    my $self  = shift;
    my $pairs = shift;

    # We need to do case-insensitive comparisons.
    # And probably strip leading/trailing spaces.
    #
    my %pairSeen;

    for ( my $i = 0 ; $i < @{$pairs} ; $i += 2 ) {
        my $key   = lc( $pairs->[$i] );
        my $value = lc( $pairs->[ $i + 1 ] );
        $key =~ s/^\s+//;
        $key =~ s/\s+$//;
        $value =~ s/^\s+//;
        $value =~ s/\s+$//;

        my $keyValue = "$key = $value";
        if ( $pairSeen{$keyValue} ) {
            $self->message(kFailureMessage);
            return;
        }
        $pairSeen{$keyValue} = 1;
    }

    return 1;
}

#------------------------------------------------------------
# Validate::Rule _init()
# Initialize the object.
#
# - Build accessor method hash
# - set internal private data ( message, fail_status, and
#   parameter ). See the base class for parameter defintions.
#
#------------------------------------------------------------
sub _init {
    my ( $self, %args ) = @_;

    # Build a hash with our valid class attributes
    foreach ( (kClassAttributes) ) {
        $self->{_attributes}->{$_}++;
    }

    $self->message( $args{message}                    ? $args{message}     : kFailureMessage );
    $self->fail_status( defined( $args{fail_status} ) ? $args{fail_status} : Validate::kStatusDefault );
    $self->parameter( $args{parameter} ) if ( $args{parameter} );

    $self->SUPER::_init(%args);

    return $self;
}
1;
