#------------------------------------------------------------
# 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;
