#------------------------------------------------------------
# Copyright (C) 2006 RoyaltyShare, Inc.   All Rights Reserved
#------------------------------------------------------------
package RPS::Song::Song;
use strict;
use warnings;

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

use lib '/app/tools/rps/lib';
use RPS::DB::Item::Song;
use RPS::DB::Item::Master;
use RPS::DB::Item::Composer;

use Common::FormObject;
use base 'Common::FormObject';


sub _init
{
	my ($self, %args) = @_;

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

    my %properties;
	if ($args{_dbItem})
	{
		$self->_propertiesFromDBItem(\%properties, $args{_dbItem});
	}
	elsif ($args{songID})
	{
		$self->_propertiesFromDB(\%properties, $args{songID});
	}
	else
	{
		$self->_propertiesFromDefaults(\%properties);
	}

    $self->_initProperties(\%properties);

    return $self;
}

sub _propertiesFromDB
{
	my ($self, $hrProperties, $songID) = @_;

	my $dbItem = RPS::DB::Item::Song->Lookup(song_id => $songID);
	$self->_propertiesFromDBItem($hrProperties, $dbItem);
}


sub _propertiesFromDBItem
{
	my ($self, $hrProperties, $dbItem) = @_;

	$hrProperties->{song_id}        = $dbItem->song_id;
	$hrProperties->{title}          = $dbItem->title;
	$hrProperties->{composer_id}    = $dbItem->composer_id;
	$hrProperties->{iswc}           = $dbItem->iswc;
	$hrProperties->{public_domain}  = $dbItem->public_domain;

	$hrProperties->{date_created}   = $dbItem->date_created;
	$hrProperties->{date_modified}  = $dbItem->date_modified;
	$hrProperties->{created_by}     = $dbItem->created_by;
	$hrProperties->{modified_by}    = $dbItem->modified_by;
}


sub _initProperties
{
	my ($self, $props) = @_;

	$self->{SongID}         = Common::FormObject::Scalar->new(value => $props->{song_id});
	$self->{Title}          = Common::FormObject::Scalar::String->new(value => $props->{title}, required => 1);
	$self->{ComposerID}     = Common::FormObject::Scalar->new(value => $props->{composer_id});
	$self->{ISWC}           = Common::FormObject::Scalar::String->new(value => $props->{iswc}, maxlength => 20);
	$self->{PublicDomain}   = Common::FormObject::Scalar->new(value => $props->{public_domain});

	$self->{CreatedDate}    = Common::FormObject::Scalar::DateTime->new(value => $props->{date_created}, readOnly => 1);
	$self->{ModifiedDate}   = Common::FormObject::Scalar::DateTime->new(value => $props->{date_modified}, readOnly => 1);
	$self->{CreatedBy}      = Common::FormObject::Scalar::UserName->new(value => $props->{created_by}, readOnly => 1);
	$self->{ModifiedBy}     = Common::FormObject::Scalar::UserName->new(value => $props->{modified_by}, readOnly => 1);

	# we need to determine if this song is linked to more
	# than one master, if so it will not be editable on the album page
	#
	my $linkedMasters = 0;
	if($props->{song_id})
	{
		my $masters = RPS::DB::Item::Master->GetMastersBySongID($props->{song_id});
		$linkedMasters = (defined $masters) ? $masters->size() : 0;
	}
	$self->{LinkedMasters} = Common::FormObject::Scalar->new(value => $linkedMasters, readOnly => 1);

	# We need to fetch the composer name, given the composer id.
	#
	my $composerName;
	my $composerID = $props->{composer_id};
	if ($composerID)
	{
		my $composerDBItem = RPS::DB::Item::Composer->Lookup(composer_id => $composerID);
		$composerName = $composerDBItem->name if($composerDBItem);
	}
	$self->{ComposerName} = Common::FormObject::Scalar::String->new(value => $composerName);
}



sub _propertiesFromDefaults
{
	my ($self, $hrProperties) = @_;
}


sub isEmpty
{
	my $self = shift @_;

	return 0;
}

sub validate
{
	my $self = shift @_;

	my $valid = $self->SUPER::validate();

	# new Songs get their Title from the Master, but existing
	# Songs must have something set
	#

# we're removing the automagic between Master and Song title
#
#	if($self->SongID() && ! $self->Title())
#	{
#		$self->{Title}->setError(Common::FormObject::kErrFieldBlank);
#		$valid = 0;
#	}

	return $valid;
}

sub _validateMetadata {
    my $self = shift;
	my %args = @_ if( @_ % 2 == 0 );

    my $validator = $args{metadataValidator};

	my $currentData = RPS::DB::Item::Song->Lookup(song_id => $self->SongID)
        if( $self->SongID );

    my %scalar_rule_map = (
        Title => { legacy => "title",
                   validate => "track-title" },
    );

	unless( $validator ) {
		Common::Log::Debug( "No validator passed to " . ref($self) . "::_validateMetadata, skipping validation!!!!!" );
		use Common::Assert;
        return 1;
	}

    return $self->SUPER::_validateMetadata( fieldMap          => \%scalar_rule_map,
                                            currentData       => $currentData,
                                            metadataValidator => $validator );
}


sub save
{
    my $self = shift @_;

	# -------------------------------
	# Handle the Master composer here
	# -------------------------------

	# Translate composer name to composer id, creating the composer if necessary.
	#
	my $composerObj;
	if($self->ComposerName())
	{
		$composerObj = RPS::DB::Item::Composer->Lookup(name => $self->ComposerName());
		if(!defined $composerObj)
		{
			$composerObj = RPS::DB::Item::Composer->Create(name => $self->ComposerName());
			$composerObj->save();
		}
	}

	# -------------------------------
	# Save myself
	# -------------------------------
	my $songDBObj;
	if ($self->SongID())
	{
		$songDBObj = RPS::DB::Item::Song->Lookup(song_id => $self->SongID());
	}
	else
	{
		$songDBObj = RPS::DB::Item::Song->Create();
	}

	$songDBObj->title($self->Title());
	$songDBObj->composer_id($composerObj->composer_id) if(defined $composerObj);
	$songDBObj->iswc($self->ISWC());
	$songDBObj->public_domain($self->PublicDomain());

	$songDBObj->save();

	# reload object
	#
	$self->_init(_dbItem => $songDBObj);
}


sub delete
{
	my ($self) = @_;

	# Is this Song used on other Masters?
	# if yes, then skip, else delete the Song
	#
	if($self->LinkedMasters() == 1)
	{
		# ok, there's only one master using this song, so delete it!
		#
		my $dbItem = RPS::DB::Item::Song->Lookup(song_id => $self->SongID());
		$dbItem->delete();
	}

	return 1;
}


sub isValidComposer
{
	my ($self, $album_id) = @_;

    my $dbItem = RPS::DB::Item::Song->Lookup(song_id => $self->SongID())
        if( $self->SongID() );

    # If the data hasn't changed then do not validate
    return 1
        if( $dbItem && $dbItem->composer_id == $self->ComposerID() );

    die( "album_id required" ) unless( $album_id );

#    my $req_composer = RPS::DB::Item::Genre::isComposerRequired( album_id => $album_id );

#    if( $req_composer && ! $self->ComposerName() ) {
#       $self->{ComposerName}->setError( 1 );
#       $self->{ComposerName}->setErrorString( "required for this genre" );
#	    return undef;
#    }

    return 1;
}


1;
