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

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

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

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{masterID})
	{
		$self->_propertiesFromDB(\%properties, $args{masterID});
	}
	else
	{
		$self->_propertiesFromDefaults(\%properties);
	}

    $self->_initProperties(\%properties);
    $self->_initSubs(\%properties);

    return $self;
}


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

	my $dbItem = RPS::DB::Item::Master->Lookup(master_id => $masterID);
	$self->_propertiesFromDBItem($hrProperties, $dbItem);
}


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

    $hrProperties->{master_id}      = $dbItem->master_id;
    $hrProperties->{song_id}        = $dbItem->song_id;
    $hrProperties->{title}          = $dbItem->title;
    $hrProperties->{isrc}           = $dbItem->isrc;
    $hrProperties->{duration}       = $dbItem->duration;
    $hrProperties->{date_recorded}  = $dbItem->date_recorded;
    $hrProperties->{date_created}   = $dbItem->date_created;
    $hrProperties->{date_modified}  = $dbItem->date_modified;
    $hrProperties->{created_by}     = $dbItem->created_by;
    $hrProperties->{modified_by}    = $dbItem->modified_by;
    $hrProperties->{artist_id}      = $dbItem->artist_id;
}


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

	$self->{MasterID}       = Common::FormObject::Scalar->new(value => $props->{master_id});
	$self->{SongID}         = Common::FormObject::Scalar->new(value => $props->{song_id});
	$self->{Title}          = Common::FormObject::Scalar::String->new(value => $props->{title}, required => 1);
	$self->{ISRC}           = Common::FormObject::Scalar::String->new(value => $props->{isrc}, maxlength => 20);
	$self->{Duration}       = Common::FormObject::Scalar->new(value => Common::FormObject::_secondsToMMSS($props->{duration}));
	$self->{DateRecorded}   = Common::FormObject::Scalar::Date->new(value => $props->{date_recorded});

	$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 fetch the artist name, given the artist id.
	#
	my $artistName;
	if ($props->{artist_id})
	{
		my $artistDBItem = RPS::DB::Item::Artist->Lookup(artist_id => $props->{artist_id});
		$artistName = $artistDBItem->name if($artistDBItem);
	}
	$self->{ArtistName} = Common::FormObject::Scalar::String->new(value => $artistName, required => 1);
	$self->{ArtistID} = Common::FormObject::Scalar->new(value => $props->{artist_id});


	# we need to determine if this master is linked to more
	# than one track, if so it will not be editable on the album page
	#
	my $linkedTracks = 0;
	if($props->{master_id})
	{
		my $tracks = RPS::DB::Item::Track->GetTracksByMasterID($props->{master_id});
		$linkedTracks = (defined $tracks) ? $tracks->size : 0;
	}
	$self->{LinkedTracks} = Common::FormObject::Scalar->new(value => $linkedTracks, readOnly => 1);
}


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

	# subclasses
	#
	if($self->loadSubs())
	{
		if( defined($props->{song_id}) && $props->{song_id} > 0)
		{
			$self->{Song} = RPS::Song::Song->new(songID => $props->{song_id});
		}
		else
		{
			$self->{Song} = RPS::Song::Song->new();
		}
	}
}


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


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

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

	# Duration has a required format
	#
	if($self->Duration() !~ /^(\d?\d)?\:\d?\d$/)
	{
		$self->{Duration}->setError(Common::FormObject::kErrFieldInvalid);
		$valid = 0;
	}

    if (! $self->_validateMetadata( @args ))
    {
        $valid = 0;
    }

	return $valid;
}


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

    my $validator = $args{metadataValidator};

	my $currentData = RPS::DB::Item::Master->Lookup(master_id => $self->MasterID)
        if( $self->MasterID );

    my %scalar_rule_map = (
        ISRC => { legacy   => "isrc",
                  validate => "isrc" },
        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;
	}

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

    my $song_valid = 1;
    $song_valid = $self->{Song}->_validateMetadata( fieldMap          => \%scalar_rule_map,
                                                    currentData       => $currentData,
                                                    metadataValidator => $validator )
        if( $self->{Song} );

    return $valid && $song_valid;
}

sub isEmpty
{
	my $self = shift @_;

	return 0;
}


sub save
{
    my $self = shift @_;

	# -------------------------------
	# Handle the Master artist here
	# -------------------------------

	# Translate artist name to artist id, creating the artist if necessary.
	#
	my $artistObj;
	$artistObj = RPS::DB::Item::Artist->Lookup(name => $self->ArtistName());
	if(!defined $artistObj)
	{
		$artistObj = RPS::DB::Item::Artist->Create(name => $self->ArtistName());
		$artistObj->save();
	}

	# -------------------------------
	# Handle the Song
	# -------------------------------
	$self->{Song}->save();
	my $songID = $self->{Song}->SongID();

	# -------------------------------
	# Save myself (Master)
	# -------------------------------
	#
	my $masterDBObj;
	if ($self->MasterID())
	{
		$masterDBObj = RPS::DB::Item::Master->Lookup(master_id => $self->MasterID());
	}
	else
	{
		$masterDBObj = RPS::DB::Item::Master->Create();
	}

	$masterDBObj->title($self->Title());
	$masterDBObj->isrc($self->ISRC());
	$masterDBObj->duration(Common::FormObject::_MMSSToSeconds($self->Duration()));
	$masterDBObj->date_recorded($self->DateRecorded());

    # foreign keys
	#
	$masterDBObj->artist_id($artistObj->artist_id);
	$masterDBObj->song_id($songID);

	$masterDBObj->save();

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


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

	# Is this Master used on more than one track?
	# if yes, then skip, else delete the Master
	#
	if($self->LinkedTracks() == 1)
	{
		my $dbItem = RPS::DB::Item::Master->Lookup(master_id => $self->MasterID());
		$dbItem->delete();

		# delete the Song
		#
		$self->{Song}->delete();
	}

	return 1;
}

1;
