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