#------------------------------------------------------------
# Copyright (C) 2006 RoyaltyShare, Inc.   All Rights Reserved
#------------------------------------------------------------
package RPS::Product::Track;

use strict;
use warnings;
use Carp;
use Data::Dumper;

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

use lib '/app/tools/rps/lib';
use RPS::DB::Item::Album;
use RPS::Product::BonusTrackHash;
use Common::FormObject;
use RPS::Product::Product;
use RPS::Catalog::DistributionCache;

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

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

    return $self;
}

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

    my $dbItem = RPS::DB::Item::ProductTrack->Lookup( product_id => $productID, track_id => $trackID );
    $self->_propertiesFromDBItem( $hrProperties, $dbItem );
}

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

    $hrProperties->{product_id}     = $dbItem->product_id;
    $hrProperties->{track_id}       = $dbItem->track_id;
    $hrProperties->{disc_number}    = $dbItem->disc_number;
    $hrProperties->{disc_track}     = $dbItem->disc_track;
    $hrProperties->{is_bonus_track} = $dbItem->is_bonus_track;
    $hrProperties->{album_only}     = $dbItem->album_only;

    $hrProperties->{included} = 1;

    $self->{_inDB} = 1;    # !!! Using an extra flag to denote that this was actually loaded from the db.
}

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

    $self->{ProductID}  = Common::FormObject::Scalar->new( value => $props->{product_id} );
    $self->{TrackID}    = Common::FormObject::Scalar->new( value => $props->{track_id} );
    $self->{DiscNumber} = Common::FormObject::Scalar->new( value => $props->{disc_number} );
    $self->{DiscTrack}  = Common::FormObject::Scalar->new( value => $props->{disc_track} );
    $self->{IsBonusTrack} = Common::FormObject::Scalar::Boolean->new( value => $props->{is_bonus_track} );
    $self->{AlbumOnly}    = Common::FormObject::Scalar::Boolean->new( value => $props->{album_only} );
    $self->{Included}     = Common::FormObject::Scalar::Boolean->new( value => $props->{included} );

    # thse are readOnly to the form, but they get set by TrackList
    #
    $self->{Title}            = Common::FormObject::Scalar::String->new();
    $self->{Duration}         = Common::FormObject::Scalar->new();
    $self->{TrackOrder}       = Common::FormObject::Scalar->new();
    $self->{MediaType}        = Common::FormObject::Scalar->new();
    $self->{ParentalAdvisory} = Common::FormObject::Scalar::String->new();
    $self->{PriceCategory}    = Common::FormObject::Scalar::String->new();
}

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

    if ( $self->loadSubs() ) {
        $self->{BonusTrackList} =
          RPS::Product::BonusTrackHash->new( productID => $props->{product_id}, trackID => $props->{track_id} );
    }
}

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

    $hrProperties->{included} = 1;

    $self->{_inDB} = 0;
}

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

    if ( !$self->Included() && !$self->IsBonusTrack() ) {

        # let's delete it
        #

        # First we need to clean out the album validation status first.
        my $product = new RPS::Product::Product( productID => $self->ProductID );
        my $cache = new RPS::Catalog::DistributionCache;

        $cache->clearAlbumStatus( albumID => $product->AssetID )
          if ( $product && $product->AssetID );

        # Now we can delete the record.
        $self->delete();
        return;
    }

    my $dbItem;
    if ( !$self->{_inDB} ) {

        # This is a new entry
        #
        $dbItem = RPS::DB::Item::ProductTrack->Create( product_id => $self->ProductID(), track_id => $self->TrackID() );
    } else {

        # This row already exists, but some of the data may have changed.
        #
        $dbItem = RPS::DB::Item::ProductTrack->Lookup( product_id => $self->ProductID(), track_id => $self->TrackID() );
    }

    $dbItem->disc_number( $self->DiscNumber() );
    $dbItem->disc_track( $self->DiscTrack() );
    $dbItem->is_bonus_track( $self->IsBonusTrack() );
    $dbItem->album_only( $self->AlbumOnly() );

    $dbItem->save();
    $self->{_inDB} = 1;

    if ( $dbItem->is_bonus_track ) {
        if ( !$self->{BonusTrackList} ) {
            $self->{BonusTrackList} = RPS::Product::BonusTrackHash->new( productID => $dbItem->product_id, trackID => $dbItem->track_id );
        }

        foreach my $bonusTrackKey ( keys %{ $self->{BonusTrackList}->getHash() } ) {
            my $bonusTrack = $self->{BonusTrackList}->getHash()->{$bonusTrackKey};
            if ( defined $bonusTrack ) {
                $bonusTrack->ProductID( $dbItem->product_id );
                $bonusTrack->TrackID( $dbItem->track_id );
            }
        }

        #$self->{BonusTrackList}->save(productID => $dbItem->product_id, trackID => $dbItem->track_id);
        $self->{BonusTrackList}->save( productID => $dbItem->product_id );
    }

}

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

    return $self->{BonusTrackList};
}

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

    if ( $self->{_inDB} ) {
        my $trkProd = RPS::DB::Item::ProductTrack->Lookup( product_id => $self->ProductID(), track_id => $self->TrackID() );
        $trkProd->delete();
        $self->{_inDB} = 0;
    }

    return 1;
}

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

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

    # disc_number and disc_track need to be validated, but only if this
    # track is 'included'
    #
    if ( $self->Included() ) {
        if ( !defined $self->DiscNumber() ) {
            $self->{DiscNumber}->setError(Common::FormObject::kErrFieldBlank);
            $valid = 0;
        } elsif ( $self->DiscNumber() < 1 ) {
            $self->{DiscNumber}->setError(Common::FormObject::kErrFieldOutOfRange);
            $valid = 0;
        }

        if ( !defined $self->DiscTrack() ) {
            $self->{DiscTrack}->setError(Common::FormObject::kErrFieldBlank);
            $valid = 0;
        } elsif ( $self->DiscTrack() < 1 ) {
            $self->{DiscTrack}->setError(Common::FormObject::kErrFieldOutOfRange);
            $valid = 0;
        }
    }

    my $metadata_valid = $self->_validateMetadata(%args);
    return $valid && $metadata_valid;
}

sub _validateMetadata {
    my $self = shift;
    my $d    = @_;

    my %args = @_;

    my $validator = $args{metadataValidator};
    my %validation_args;

    my $currentData = RPS::DB::Item::ProductTrack->Lookup( product_id => $self->ProductID, track_id => $self->TrackID )
      if ( $self->ProductID && $self->TrackID );

    my %scalar_rule_map = (
        'DiscTrack' => {
            legacy   => "disc_number",
            validate => "disc-no"
        },
        'DiscNumber' => {
            legacy   => "disc_track",
            validate => "track-number"
        },
    );

    Common::Log::Debug("Validate Product Track");
    my $valid = $self->SUPER::_validateMetadata(
        fieldMap          => \%scalar_rule_map,
        currentData       => $currentData,
        metadataValidator => $validator
    ) if ( $self->Included );

    return !$self->Included || $valid;
}

###
1;    #
###
