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


# Going to need every field in artist_contract_term_reserve.
# I will also want to join to new_artist_contract to get the payee_id.
# Probably join to product to make sure the product still exists.
# need the rate_type_id from the term, so join that too.
# 
# This should just be a set of single records, so we can use a flat text file.

package RPS::ArtistRoyalty::Fast::Static::Reserves;

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

use lib '/app/tools/common/lib';
use lib '/app/tools/rps/lib';

use Common::RSApp;
use Common::Log;
use DB_File;

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

use constant kArtistContractTermReserveID   => 0;
use constant kArtistContractTermID          => 1;
use constant kIncomeSourceID                => 2;
use constant kRegionID                      => 3;
use constant kChannelID                     => 4;
use constant kPriceLevelID                  => 5;
use constant kOriginalStatementItemID       => 6;
use constant kProductID                     => 7;
use constant kProductFormatID               => 8;
use constant kUnits                         => 9;
use constant kRevenue                       => 10;
use constant kPrice                         => 11;
use constant kRevenueBased                  => 12;
use constant kEffectiveRate                 => 13;
use constant kPeriodsRemaining              => 14;
use constant kAlbumID                       => 15;
use constant kTrackID                       => 16;
use constant kArtistContractID              => 17;
use constant kArtistPayeeID                 => 18;
use constant kContractRateTypeID            => 19;
use constant kCrossed                       => 20;
use constant kProrateTrackCount             => 21;



sub FileName { 'reserves' }
sub CacheQueryTableList { "'artist_contract_term_reserve','product','new_artist_contract_term','new_artist_contract','artist_royalty_income_item','artist_royalty_album','artist_royalty_statement','artist_royalty_run','album_contract','track_contract','artist_payee'" };


sub _Create
{
    my ($class, $filename, $payorID) = @_;


    open RESERVEFILE, "> $filename" or die "ERROR: Unable to open $filename for writing: $!";

    # We need to account for old reserves we ported over from the previous schema, that will have an 'original_statement_item_id' of 0,
    # as well as reserves from committed or closed runs.
    # Rather than do an 'OR', which is oddly slow, we'll union two queries.  

   


    # !!! Challenge:   I need to get the cross_collateralized flag from track_contract or album_contract, as appropriate.
    # !!! I do have the track and album id... but I don't know explicitly whether this was a track or album contract.
    # !!! I might have to break each of these queries into 2 distinct queries in order to get what I'm looking for.

    # !!! I seem to be getting fooled here.  I'm bringing up reserves that are associated with non-existent track contracts, because
    # !!! there is an album contract someplace.
    # !!! Basically, if the reserve lists a track id, then this reserve is associated with a track contract.  At least that's how the old
    # !!! code figures it.

    my $baseSql = qq/
    SELECT
    artist_contract_term_reserve.artist_contract_term_reserve_id,
    artist_contract_term_reserve.artist_contract_term_id,
    artist_contract_term_reserve.income_source_id,
    artist_contract_term_reserve.region_id,
    artist_contract_term_reserve.channel_id,
    artist_contract_term_reserve.price_level_id,
    artist_contract_term_reserve.original_statement_item_id,
    artist_contract_term_reserve.product_id,
    artist_contract_term_reserve.product_format_id,
    artist_contract_term_reserve.units,
    artist_contract_term_reserve.revenue,
    artist_contract_term_reserve.price,
    artist_contract_term_reserve.revenue_based,
    artist_contract_term_reserve.effective_rate,
    artist_contract_term_reserve.periods_remaining,
    artist_contract_term_reserve.album_id,
    artist_contract_term_reserve.track_id,
    new_artist_contract.artist_contract_id,
    new_artist_contract.artist_payee_id,
    new_artist_contract_term.contract_rate_type_id,
    album_contract.cross_collateralized,
    artist_contract_term_reserve.prorate_track_count
    FROM artist_contract_term_reserve
    JOIN product USING (product_id)
    JOIN new_artist_contract_term USING (artist_contract_term_id)
    JOIN new_artist_contract USING (artist_contract_id)
    JOIN artist_royalty_income_item ON (artist_royalty_income_item.artist_royalty_income_item_id = artist_contract_term_reserve.original_statement_item_id)
    JOIN artist_royalty_album USING (artist_royalty_album_id)
    JOIN artist_royalty_statement USING (artist_royalty_statement_id)
    JOIN artist_royalty_run USING (artist_royalty_run_id)
    JOIN album_contract ON (album_contract.album_id=artist_contract_term_reserve.album_id AND album_contract.artist_contract_id = new_artist_contract.artist_contract_id)
    JOIN artist_payee ON (new_artist_contract.artist_payee_id = artist_payee.artist_payee_id)
    WHERE new_artist_contract.payor_id=$payorID
    AND artist_contract_term_reserve.periods_remaining>0
    AND artist_royalty_run.status IN (2,5)
    AND album_contract.status=1
    AND artist_payee.status IN (1,2)
    AND artist_contract_term_reserve.track_id=0
    UNION
    SELECT
    artist_contract_term_reserve.artist_contract_term_reserve_id,
    artist_contract_term_reserve.artist_contract_term_id,
    artist_contract_term_reserve.income_source_id,
    artist_contract_term_reserve.region_id,
    artist_contract_term_reserve.channel_id,
    artist_contract_term_reserve.price_level_id,
    artist_contract_term_reserve.original_statement_item_id,
    artist_contract_term_reserve.product_id,
    artist_contract_term_reserve.product_format_id,
    artist_contract_term_reserve.units,
    artist_contract_term_reserve.revenue,
    artist_contract_term_reserve.price,
    artist_contract_term_reserve.revenue_based,
    artist_contract_term_reserve.effective_rate,
    artist_contract_term_reserve.periods_remaining,
    artist_contract_term_reserve.album_id,
    artist_contract_term_reserve.track_id,
    new_artist_contract.artist_contract_id,
    new_artist_contract.artist_payee_id,
    new_artist_contract_term.contract_rate_type_id,
    track_contract.cross_collateralized,
    artist_contract_term_reserve.prorate_track_count
    FROM artist_contract_term_reserve
    JOIN product USING (product_id)
    JOIN new_artist_contract_term USING (artist_contract_term_id)
    JOIN new_artist_contract USING (artist_contract_id)
    JOIN artist_royalty_income_item ON (artist_royalty_income_item.artist_royalty_income_item_id = artist_contract_term_reserve.original_statement_item_id)
    JOIN artist_royalty_album USING (artist_royalty_album_id)
    JOIN artist_royalty_statement USING (artist_royalty_statement_id)
    JOIN artist_royalty_run USING (artist_royalty_run_id)
    JOIN track_contract ON (track_contract.track_id=artist_contract_term_reserve.track_id AND track_contract.artist_contract_id = new_artist_contract.artist_contract_id)
    JOIN artist_payee ON (new_artist_contract.artist_payee_id = artist_payee.artist_payee_id)
    WHERE new_artist_contract.payor_id=$payorID
    AND artist_contract_term_reserve.periods_remaining>0
    AND artist_royalty_run.status IN (2,5)
    AND track_contract.status=1
    AND artist_payee.status IN (1,2)
    AND artist_contract_term_reserve.track_id>0
    /;

    my $oldSql = qq/
    SELECT
    artist_contract_term_reserve.artist_contract_term_reserve_id,
    artist_contract_term_reserve.artist_contract_term_id,
    artist_contract_term_reserve.income_source_id,
    artist_contract_term_reserve.region_id,
    artist_contract_term_reserve.channel_id,
    artist_contract_term_reserve.price_level_id,
    artist_contract_term_reserve.original_statement_item_id,
    artist_contract_term_reserve.product_id,
    artist_contract_term_reserve.product_format_id,
    artist_contract_term_reserve.units,
    artist_contract_term_reserve.revenue,
    artist_contract_term_reserve.price,
    artist_contract_term_reserve.revenue_based,
    artist_contract_term_reserve.effective_rate,
    artist_contract_term_reserve.periods_remaining,
    artist_contract_term_reserve.album_id,
    artist_contract_term_reserve.track_id,
    new_artist_contract.artist_contract_id,
    new_artist_contract.artist_payee_id,
    new_artist_contract_term.contract_rate_type_id,
    album_contract.cross_collateralized,
    artist_contract_term_reserve.prorate_track_count
    FROM artist_contract_term_reserve
    JOIN product USING (product_id)
    JOIN new_artist_contract_term USING (artist_contract_term_id)
    JOIN new_artist_contract USING (artist_contract_id)
    JOIN album_contract ON (album_contract.album_id=artist_contract_term_reserve.album_id AND album_contract.artist_contract_id=new_artist_contract.artist_contract_id)
    JOIN artist_payee ON (new_artist_contract.artist_payee_id = artist_payee.artist_payee_id)
    WHERE new_artist_contract.payor_id=$payorID
    AND artist_contract_term_reserve.periods_remaining>0
    AND artist_contract_term_reserve.original_statement_item_id=0
    AND album_contract.status=1
    AND artist_payee.status IN (1,2)
    AND artist_contract_term_reserve.track_id=0
    UNION
    SELECT
    artist_contract_term_reserve.artist_contract_term_reserve_id,
    artist_contract_term_reserve.artist_contract_term_id,
    artist_contract_term_reserve.income_source_id,
    artist_contract_term_reserve.region_id,
    artist_contract_term_reserve.channel_id,
    artist_contract_term_reserve.price_level_id,
    artist_contract_term_reserve.original_statement_item_id,
    artist_contract_term_reserve.product_id,
    artist_contract_term_reserve.product_format_id,
    artist_contract_term_reserve.units,
    artist_contract_term_reserve.revenue,
    artist_contract_term_reserve.price,
    artist_contract_term_reserve.revenue_based,
    artist_contract_term_reserve.effective_rate,
    artist_contract_term_reserve.periods_remaining,
    artist_contract_term_reserve.album_id,
    artist_contract_term_reserve.track_id,
    new_artist_contract.artist_contract_id,
    new_artist_contract.artist_payee_id,
    new_artist_contract_term.contract_rate_type_id,
    track_contract.cross_collateralized,
    artist_contract_term_reserve.prorate_track_count
    FROM artist_contract_term_reserve
    JOIN product USING (product_id)
    JOIN new_artist_contract_term USING (artist_contract_term_id)
    JOIN new_artist_contract USING (artist_contract_id)
    JOIN track_contract ON (track_contract.track_id=artist_contract_term_reserve.track_id AND track_contract.artist_contract_id=new_artist_contract.artist_contract_id)
    JOIN artist_payee ON (new_artist_contract.artist_payee_id = artist_payee.artist_payee_id)
    WHERE new_artist_contract.payor_id=$payorID
    AND artist_contract_term_reserve.periods_remaining>0
    AND artist_contract_term_reserve.original_statement_item_id=0
    AND track_contract.status=1
    AND artist_payee.status IN (1,2)
    AND artist_contract_term_reserve.track_id>0
    /;

    # I don't know yet whether I'll want this data arranged in any particular way.  It seems to me that I've got
    # everything I need in this one query already, so I don't think I need to rely on efficiently accessing any other
    # data.
    #
    my $sql = "$baseSql UNION $oldSql";


    my $dbo = Common::RSApp::GetClientDB();
    my $sth = $dbo->DoCmd($sql);
    while (my $ar = $sth->fetchrow_arrayref())
    {
        print RESERVEFILE join("\t", @$ar) . "\n";
    }

    close RESERVEFILE;
}


sub GetReserves
{
    my ($class, $dataPath) = @_;


    # Currently the sales file is a text file.
    # We'll use DB_RECNO, which allows us to access the file through
    # a tied array ref.
    #
    # !!! Or, we'll just return a file handle...   Don't really need fancy tied arrays for this, do we?
    #
    my $filename = "$dataPath/".$class->FileName();

    my @array;
    tie @array, "DB_File", $filename, O_RDONLY, 0666, $DB_RECNO or die "Error opening $filename: $!\n";

    return \@array;
}


1;

