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

package RPS::RoyaltyRun::Process;
use strict;

use Data::Dumper;

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

use RPS::DB::Item::Album;
use RPS::DB::Item::Artist;
use RPS::DB::Item::Label;
use RPS::DB::Item::Master;
use RPS::DB::Item::Product;
use RPS::DB::Item::ProductType;
use RPS::DB::Item::Song;
use RPS::DB::Item::Track;

use base 'Common::Process';

sub canExecute { 1 }

sub execute {
    my $self = shift;

    if ( $self->canExecute() ) {
        eval { $self->run(@_); };

        if ($@) {
            print STDERR "$0 died\n";
            print STDERR "$@\n";
            $self->_onFailure( exception => $@ );
            exit 1;
        }
    }
}

sub run {
    my $self = shift;

    unless ( $self->_prevalidateRun() ) {
        $self->_setStateToError();
        return;
    }

    return 1;
}

sub _prevalidateRun {
    my $self = shift;

    $self->_report("Begin Pre Run Validation.");

    return $self->_prevalidateReserveLiquidationSchedule()
      && $self->_prevalidatePennyRate();
}

sub _prevalidatePennyRate {
    my $self = shift;

    my $collection = $self->_getPennyRateErrors();

    if ( defined($collection) ) {
        if ( $collection->hasNext() ) {
            while ( my $row = $collection->next() ) {
                $self->_report( "Track rate type is penny rate, but penny rate is 0: " . Dumper $row );
            }

            return;
        } else {
            $self->_report("Penny Rate test: Passed");
        }
    } else {
        $self->_report("*****  _getPennyRateErrors not overloaded. Not validating penny rate! *****");
    }

    return 1;
}

sub _prevalidateReserveLiquidationSchedule {
    my $self = shift;

    my $collection = $self->_getReserveErrors();

    if ( defined($collection) ) {
        if ( $collection->hasNext() ) {
            while ( my $row = $collection->next() ) {
                $self->_report( "Missing reserve liquidations: " . Dumper $row );
            }

            return;
        } else {
            $self->_report("Reserve Liquidation test: Passed");
        }
    } else {
        $self->_report("*****  _getReserveErrors not overloaded. Not validating liquidation schedule! *****");
    }

    return 1;
}

sub _getReserveErrors   { }
sub _getPennyRateErrors { }

# Going to add the cached metadata accessors here.
# I am going to want these in both the RunController and CreateStatement classes.

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

    if ( !$self->{_song}{$songID} ) {
        $self->{_song}{$songID} = RPS::DB::Item::Song->Lookup( song_id => $songID );
    }

    return $self->{_song}{$songID};
}

sub _getTrack {
    my ( $self, $trackID ) = @_;

    if ( !$self->{_track}{$trackID} ) {
        $self->{_track}{$trackID} = RPS::DB::Item::Track->Lookup( track_id => $trackID );
    }

    return $self->{_track}{$trackID};
}

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

    if ( !$self->{_master}{$masterID} ) {
        $self->{_master}{$masterID} = RPS::DB::Item::Master->Lookup( master_id => $masterID );
    }
    return $self->{_master}{$masterID};
}

sub _getAlbum {
    my ( $self, $albumID ) = @_;

    if ( !$self->{_album}{$albumID} ) {
        $self->{_album}{$albumID} = RPS::DB::Item::Album->Lookup( album_id => $albumID );
    }
    return $self->{_album}{$albumID};
}

sub _getTrackDuration {
    my ( $self, $trackID ) = @_;

    if ( !defined $self->{_trackDuration}{$trackID} ) {
        my $track = $self->_getTrack($trackID);
        assert($track);
        my $master = $self->_getMaster( $track->master_id );
        assert($master);
        my $duration = $master->duration;

        $self->{_trackDuration}{$trackID} = $duration;
    }

    return $self->{_trackDuration}{$trackID};
}

sub _getProduct {
    my ( $self, $productID ) = @_;
    assert($productID);

    if ( !$self->{_product}{$productID} ) {
        $self->{_product}{$productID} = RPS::DB::Item::Product->Lookup( product_id => $productID );
        assert( $self->{_product}{$productID}, "Unable to fetch a product using id $productID" );
    }

    return $self->{_product}{$productID};
}

sub _getLabel {
    my ( $self, $labelID ) = @_;
    assert($labelID);

    if ( !$self->{_label}{$labelID} ) {
        $self->{_label}{$labelID} = RPS::DB::Item::Label->Lookup( label_id => $labelID );
        assert( $self->{_label}{$labelID}, "Unable to fetch a label using id $labelID" );
    }

    return $self->{_label}{$labelID};
}

sub _getArtist {
    my ( $self, $artistID ) = @_;
    assert($artistID);

    if ( !$self->{_artist}{$artistID} ) {
        $self->{_artist}{$artistID} = RPS::DB::Item::Artist->Lookup( artist_id => $artistID );
        assert( $self->{_artist}{$artistID}, "Unable to fetch an artist using id $artistID" );
    }

    return $self->{_artist}{$artistID};
}

sub _getProductType {
    my ( $self, $productTypeID ) = @_;
    assert($productTypeID);

    if ( !$self->{_productType} ) {
        my $productTypeList = RPS::DB::Item::ProductType->GetAll();
        while ( my $productType = $productTypeList->next() ) {
            $self->{_productType}{ $productType->product_type_id } = $productType;
        }
    }

    return $self->{_productType}{$productTypeID};
}

sub _onFailure {
    my $self = shift;

}

sub interupt {
    shift->_onFailure( interupt => 1 );
}

1;
