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

package RPS::ArtistRoyalty::Fast::TermType::Revenue;

use strict;

use lib '/app/tools/common/lib';
use lib '/app/tools/rps/lib';
use Common::RSMath;
use RPS::ArtistRoyalty::Fast::Static::Sales;
use RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem;
use RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyAlbum;

use base 'RPS::ArtistRoyalty::Fast::TermType::Base';

sub isRevenueBased { 1 }

sub _getPrice {
    my ( $self, $sale, $priceLevel, $productPrices ) = @_;

    # !!! Price doesn't actually mean anything?
    # !!! Not sure what is best to return here.
    # !!! I'll try '1' and see what that does...

    #    return 1;
    return $sale->[RPS::ArtistRoyalty::Fast::Static::Sales::kPrice];
}

sub _getPriceLevel {
    my ( $self, $sale, $productTerm ) = @_;

    return 0;
}

# JPK - Try calculating revenue a bit differently (sales * price)
#
sub accumulateData {
    my ( $self, $data, $item ) = @_;

    $item->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kSales] += $data->[RPS::ArtistRoyalty::Fast::Mapped::Data::kSales];
    $item->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kReturns] +=
      $data->[RPS::ArtistRoyalty::Fast::Mapped::Data::kReturns];

    # The isDigital flag is contained in the RPS::ArtistRoyalty::Fast::Mapped::Data line.
    # Oddly, the ArtistRoyaltyIncomeItem data doesn't contain product_id.
    # I'm going to have to store this flag in the IncomeItem, so I can get at
    # it when we're calculating the reserves right before output.
    # It will (or at least should...) always be the same for given line.
    #
    my $isDigital = $data->[RPS::ArtistRoyalty::Fast::Mapped::Data::kIsDigital];
    $item->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kIsDigital] = $isDigital;

    # !!! This calculation is only for digital sales.
    # !!! If this is a physical sale, we use the kTotalRevenue column in the data.
    #

    my $revenue;
    if ($isDigital) {

        # !!! Not sure if this 'early rounding' really makes sense here.
        # !!!
        # !!! In some cases it help, but in others I am not so sure.
        # !!! I feel like I keep going back and forth with this.
        # !!! But I am having difficulty finding example in the code where I round the sale price.
        #
        #        my $price = Common::RSMath::round($data->[RPS::ArtistRoyalty::Fast::Mapped::Data::kPrice], 4);
        my $price = $data->[RPS::ArtistRoyalty::Fast::Mapped::Data::kPrice];

        #        my $convRate = Common::RSMath::round($data->[RPS::ArtistRoyalty::Fast::Mapped::Data::kConversionRate], 4);

        # !!! It totaly doesn't make sense.  However, it sure looks like we sometimes to round
        # !!! the price off.  It's just not clear to me when this rounded rate comes into play.
        # !!! In processSale, it looks like we calculate the total revenue of a sale using
        # !!! the unrounded values. But price is rounded to 4 places when used as a hash key.
        # !!! It's all very weird...

        #        my $price = $data->[RPS::ArtistRoyalty::Fast::Mapped::Data::kPrice];
        my $convRate = $data->[RPS::ArtistRoyalty::Fast::Mapped::Data::kConversionRate];
        Log->info("TermType/Revenue price: $price  convRate: $convRate");

        # Based on NET UNITS.
        # It looks like kReturns are negative numbers, so just sum that with the Sales.
        # !!! They should NOT have been negative numbers, that was a mistake in the Extractor.  Fixed that, so fix this too.
        #
        $revenue = ( $data->[RPS::ArtistRoyalty::Fast::Mapped::Data::kSales] - $data->[RPS::ArtistRoyalty::Fast::Mapped::Data::kReturns] ) *
          $price * $convRate;
        Log->info("TermType/Revenue revenue: $revenue");
    } else {
        my $convRate = $data->[RPS::ArtistRoyalty::Fast::Mapped::Data::kConversionRate];
        $revenue = $data->[RPS::ArtistRoyalty::Fast::Mapped::Data::kRevenue] * $convRate;
    }

    # JPK - The old code has a rounding bug :  This replicates it.
    #
    my $distFee = $data->[RPS::ArtistRoyalty::Fast::Mapped::Data::kDistributionFee];
    if ($distFee) {

        # The bug is - this happens even if the fee is '0.00'.
        # Not to mention rounding at all is pointless...
        #
        $revenue = Common::RSMath::round( $revenue * ( ( 100 - $distFee ) / 100 ), 2 );
        Log->info("Rounded with distFee $distFee");
    }

    $item->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kNetRevenue] += $revenue;

    Log->info( $item->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kArtistContractTermID] . ', '
          . $item->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kAlbumID] . ', '
          . $item->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kTrackID] . ', '
          . $item->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kProductID] . ', '
          . $item->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kIncomeSourceID]
          . " TermType/Revenue FINAL revenue: $revenue" );

    if ( 1 == $data->[RPS::ArtistRoyalty::Fast::Mapped::Data::kReservePeriodsRemaining] ) {
        $item->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kUnitsLiquidated] +=
          $data->[RPS::ArtistRoyalty::Fast::Mapped::Data::kUnitsLiquidated];
        $item->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kRevenueLiquidated] +=
          $data->[RPS::ArtistRoyalty::Fast::Mapped::Data::kRevenueLiquidated];
    }

    # Now we may need to do some logging.
    #
    $self->_logSaleOrReserves( $data, $item );

}

sub updateAlbumSummary {
    my ( $self, $item, $album ) = @_;
    $album->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyAlbum::kNetRevenueIncome] +=
      $item->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kTotal];
}

# Net revenue is different than all the others (which are 'price-based').
#
sub calculateFinalRateData {
    my ( $self, $incomeItem, $isDigital ) = @_;

    # We've been calculating the net revenue all along.
    # Go ahead and round immediately.
    #
    my $netRevenue = Common::RSMath::round( $incomeItem->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kNetRevenue], 2 );

    # !!! What about the ol' conversion rate?
    # !!! That's hidden away in the sale data, and will probably need to be injected into the mapped data somehow.
    #
    my $totalRevenue = $netRevenue;

    # Take reserves before deductions.
    #
    my $revenueReserved;

    if ( !$isDigital ) {
        my $reservePercentage = $self->[RPS::ArtistRoyalty::Fast::Static::Terms::kReserveRate];
        if ( $netRevenue > 0 && $reservePercentage ) {
            $revenueReserved = Common::RSMath::round( $netRevenue * ( $reservePercentage / 100 ), 2 );
            $netRevenue -= $revenueReserved;
        }
    }

    # Add in liquidated units
    #
    $netRevenue += $incomeItem->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kRevenueLiquidated];

    if ( $netRevenue > 0 && $self->[RPS::ArtistRoyalty::Fast::Static::Terms::kFreeGoodsDeduction] ) {
        $netRevenue =
          Common::RSMath::round( $netRevenue * ( ( 100 - $self->[RPS::ArtistRoyalty::Fast::Static::Terms::kFreeGoodsDeduction] ) / 100 ),
            2 );
    }

    my $netRate = $incomeItem->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kRate];
    if ( $self->[RPS::ArtistRoyalty::Fast::Static::Terms::kPercentageOfSales] ) {
        $netRate = $netRate * ( $self->[RPS::ArtistRoyalty::Fast::Static::Terms::kPercentageOfSales] / 100 );
    }

    if ( $self->[RPS::ArtistRoyalty::Fast::Static::Terms::kRateReduction] ) {
        $netRate = $netRate * ( $self->[RPS::ArtistRoyalty::Fast::Static::Terms::kRateReduction] / 100 );
    }

    if ( $self->[RPS::ArtistRoyalty::Fast::Static::Terms::kPackagingDeduction] ) {
        $netRate = $netRate * ( ( 100 - $self->[RPS::ArtistRoyalty::Fast::Static::Terms::kPackagingDeduction] ) / 100 );
    }

    my $total = Common::RSMath::round( ( ( $netRate / 100 ) * $netRevenue ), 2 );

    # Just write the data straight into the record.
    #
    $incomeItem->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kNetUnits] =
      $incomeItem->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kSales] -
      $incomeItem->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kReturns];
    $incomeItem->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kNetRevenue]      = $netRevenue;
    $incomeItem->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kRevenue]         = $totalRevenue;
    $incomeItem->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kNetRate]         = $netRate;
    $incomeItem->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kTotal]           = $total;
    $incomeItem->[RPS::ArtistRoyalty::Fast::Final::ArtistRoyaltyIncomeItem::kRevenueReserved] = $revenueReserved;

}

1;
