#---------------------------------------------------------------
# ____                   _ _         ____  _
#|  _ \ ___  _   _  __ _| | |_ _   _/ ___|| |__   __ _ _ __ ___
#| |_) / _ \| | | |/ _` | | __| | | \___ \| '_ \ / _` | '__/ _ \
#|  _ < (_) | |_| | (_| | | |_| |_| |___) | | | | (_| | | |  __/
#|_| \_\___/ \__, |\__,_|_|\__|\__, |____/|_| |_|\__,_|_|  \___|
#            |___/             |___/
#
# Copyright (C) 2012 RoyaltyShare, Inc.   All Rights Reserved
#---------------------------------------------------------------

package RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyAlbum;

use strict;
use Data::Dumper;
use File::Path;

use lib '/app/tools/common/lib';
use lib '/app/tools/rps/lib';
use lib '/app/tools/raptor/lib';
use Common::RSApp;
use Common::Assert;

use Data::Dumper;
use DB_File;

use RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyStatement;
use RPS::ArtistRoyalty::Fast::Mapped::Data;

use Common::Log;

use base 'RPS::ArtistRoyalty::Fast::Final';

use constant kArtistRoyaltyAlbumID       => 0;
use constant kArtistRoyaltyStatementID   => 1;
use constant kArtistContractID           => 2;
use constant kAlbumID                    => 3;
use constant kUnitLevelIncome            => 4;
use constant kNetRevenueIncome           => 5;
use constant kNetRevenueExpenses         => 6;
use constant kNetRevenueExpensesSubtotal => 7;
use constant kRecoupableExpenses         => 8;
use constant kTotalIncome                => 9;
use constant kTotalExpenses              => 10;
use constant kPreviousBalance            => 11;
use constant kTotal                      => 12;
use constant kLicenseIncomeSubtotal      => 13;
use constant kDefaultNetRevenueRate      => 14;
use constant kIsCrossCollateralized      => 15;

# Private
use constant kStatementRef => 16;

my @gFields = (
    'artist_royalty_album_id', 'artist_royalty_statement_id', 'artist_contract_id',       'album_id',
    'unit_level_income',       'net_revenue_income',          'net_revenue_expenses',     'net_revenue_expenses_subtotal',
    'recoupable_expenses',     'total_income',                'total_expenses',           'previous_balance',
    'total',                   'license_income_subtotal',     'default_net_revenue_rate', 'is_cross_collateralized',
);
sub Fields { return \@gFields; }

#root@localhost [C_WELK]> desc artist_royalty_album;
#+-------------------------------+------------------+------+-----+---------+----------------+
#| Field                         | Type             | Null | Key | Default | Extra          |
#+-------------------------------+------------------+------+-----+---------+----------------+
#| artist_royalty_album_id       | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
#| artist_royalty_statement_id   | int(10) unsigned | NO   | MUL | 0       |                |
#| artist_contract_id            | int(10) unsigned | NO   |     | 0       |                |
#| album_id                      | int(10) unsigned | NO   |     | 0       |                |
#| unit_level_income             | decimal(16,4)    | NO   |     | 0.0000  |                |
#| net_revenue_income            | decimal(16,4)    | NO   |     | 0.0000  |                |
#| net_revenue_expenses          | decimal(16,4)    | NO   |     | 0.0000  |                |
#| net_revenue_expenses_subtotal | decimal(16,4)    | NO   |     | 0.0000  |                |
#| recoupable_expenses           | decimal(16,4)    | NO   |     | 0.0000  |                |
#| total_income                  | decimal(16,4)    | NO   |     | 0.0000  |                |
#| total_expenses                | decimal(16,4)    | NO   |     | 0.0000  |                |
#| previous_balance              | decimal(16,4)    | NO   |     | 0.0000  |                |
#| total                         | decimal(16,4)    | NO   |     | 0.0000  |                |
#| license_income_subtotal       | decimal(16,4)    | NO   |     | 0.0000  |                |
#| default_net_revenue_rate      | decimal(8,4)     | NO   |     | 0.0000  |                |
#| is_cross_collateralized       | tinyint(1)       | NO   |     | 0       |                |
#+-------------------------------+------------------+------+-----+---------+----------------+
#16 rows in set (0.00 sec)

sub FileName  { 'artist_royalty_album' }
sub _MaxIDSql { 'SELECT MAX(artist_royalty_album_id) FROM artist_royalty_album' }

sub new {
    my ( $class, $data, $statement ) = @_;

    my $item = $class->BlankItem();
    $class->_IncrementID();

    $item->[kArtistRoyaltyAlbumID]     = $class->_CurrentID();
    $item->[kArtistRoyaltyStatementID] = $statement->id();

    $item->[kArtistContractID]      = $data->[RPS::ArtistRoyalty::Fast::Mapped::Data::kArtistContractID];
    $item->[kAlbumID]               = $data->[RPS::ArtistRoyalty::Fast::Mapped::Data::kAlbumID];
    $item->[kIsCrossCollateralized] = $data->[RPS::ArtistRoyalty::Fast::Mapped::Data::kCrossed];

    push @$item, $statement;

    # !!! We are eventually going to need to keep the reference to $statement around,
    # !!! so we can call it upon destruction to update summary data.
    # !!! We'll do that by pushing it onto the end of the array.
    # !!! Once we've sent over the summary data, we need to remember to pop that off so we
    # !!! don't write it out to the output file...
    #
    bless $item, $class;

    return $item;
}

sub statement {
    my $self = shift;
    return $self->[kStatementRef];
}

sub process {
    my ( $self, $data ) = @_;

    # Test whether we're still looking at data for 'this' object.
    #
    if (   $self->[kAlbumID] != $data->[RPS::ArtistRoyalty::Fast::Mapped::Data::kAlbumID]
        || $self->[kArtistContractID] != $data->[RPS::ArtistRoyalty::Fast::Mapped::Data::kArtistContractID] ) {
        return undef;
    }

    return 1;
}

sub _output {
    my ( $self, $fd ) = @_;

    my $statement = pop @$self;

    # do nothing if we don't have an album id.
    # this comes into play when we've got payee transactions...
    #
    # !!! Actually, this will also come into play when we have contract-level
    # license income (at least I think it will).
    # In that case we'll need to send our accumulated license income up to the
    # statement.
    #
    if ( 0 == $self->[kAlbumID] ) {
        if ( $self->[kLicenseIncomeSubtotal] != 0 ) {
            $statement->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyStatement::kContractLevelLicenseIncomeSubtotal] +=
              $self->[kLicenseIncomeSubtotal];
        }

        # Don't actually output an album row.
        #
        return undef;
    }

    # Sum up some stuff.
    #
    if ( $self->[kNetRevenueExpenses] ) {
        $self->[kNetRevenueExpensesSubtotal] =
          Common::RSMath::round( $self->[kNetRevenueExpenses] * ( $self->[kDefaultNetRevenueRate] / 100 ), 4 );
    }

    $self->[kTotalExpenses] = $self->[kNetRevenueExpensesSubtotal] + $self->[kRecoupableExpenses];

    $self->[kTotalIncome] = $self->[kUnitLevelIncome] + $self->[kNetRevenueIncome];

    # !!! Need to start thinking about account balances...
    #
    # So, I'll need a data structure to access the ArtistRoyaltyAlbumBalanceAccount data.
    # It maps by artist_payee_id,album_id,artist_contract_id.
    # I think I'll just serialize a hash of {album_id}{artist_contract_id} = $previousBalance, and
    # store that in a berkeley db file keyed by the artist_payee_id.
    # I'll use a global variable to hold onto the last one I looked at, and stash the associated payee id.
    #
    # Ok, so build the account data first.
    #

    # Actually, let's give the payee album balance to the Statement.
    # We're going to eval in a hash for each payee, so it makes sense.

    my $previousBalance = $statement->previousBalance( $self->[kAlbumID], $self->[kArtistContractID] );
    Log->info( "in ArtistRoyaltyAlbum, previous balance for album "
          . $self->[kAlbumID]
          . ", contract "
          . $self->[kArtistContractID]
          . " = $previousBalance" );
    $self->[kPreviousBalance] = $previousBalance;

    # !!! Yes, this total seems correct.
    # !!! But I need to be careful how I update the statement summary data, which is broken up into a lot of different slots.
    # !!! EXCEPT many of these 'slots' don't appear to even get used anymore.  neat.
    #
    $self->[kTotal] = $previousBalance - $self->[kTotalExpenses] + $self->[kTotalIncome] + $self->[kLicenseIncomeSubtotal];

    # !!! Having trouble getting all this summary data to add up correctly.
    # !!! Let's restart.

    if ( $self->[kIsCrossCollateralized] ) {
        $statement->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyStatement::kCrossCollateralizedIncomeSubtotal] += $self->[kTotalIncome];
        $statement->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyStatement::kCrossCollateralizedSubtotal]       += $self->[kTotal];
        $statement->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyStatement::kCrossCollateralizedExpenseSubtotal] +=
          $self->[kTotalExpenses];

        $statement->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyStatement::kCrossCollateralizedPreviousBalance] += $previousBalance;

        # It's weird how the arithmetic seems to change here...
        # !!! I keep on going back and forth with when these fucking Totals get updated.  driving me nuts.
        #
        # !!! It just seems pointless and wrong to update the statement totals here.
        # !!! Why can't the statement do that itself?
        #        my $crossSubtotal = $self->[kTotalIncome] - $self->[kTotalExpenses] + $self->[kLicenseIncomeSubtotal];
        #        $statement->[ArtistRoyaltyStatement::kTotal] += $crossSubtotal if $crossSubtotal > 0;

        # JPK - Stupidly, this column is only supposed to contain _crossed_ license income subtotals.
        #
        $statement->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyStatement::kLicenseIncomeSubtotal] += $self->[kLicenseIncomeSubtotal];
    } else {
        $statement->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyStatement::kUncrossedSubtotal] += $self->[kTotal];
        $statement->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyStatement::kTotal] += $self->[kTotal] if $self->[kTotal] > 0;
    }

    $self->SUPER::_output($fd);
}

1;

