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

package RPS::Report::Dynamic::Payee::Publishers;

use strict;
use warnings;
use Data::Dumper;

use lib '/app/tools/common/lib';
use Common::Assert;

use lib '/app/tools/rps/lib';
use RPS::DB::Item::Affiliate;
use RPS::DB::Item::Payor;
use RPS::DB::Item::FinanceTransaction;
use RPS::DB::Item::PendingTransaction;

use base 'RPS::Report::Dynamic::Payee::Base';

# defined at the end of this file
#
sub _ParamClass {
    my $self = shift;

    if ( $self->Type eq "US Publishers" ) {
        return 'RPS::Report::Dynamic::Payee::Publishers::Parameters';
    }

    return 'RPS::Report::Dynamic::Payee::Parameters';
}

sub _columns {
    my ($self) = @_;

    my $cols = [];

    push( @$cols, $self->_getNameColumnHash( 'publisher',         'publisher' ) );
    push( @$cols, $self->_getNameColumnHash( 'client-account-no', 'client_account_no' ) );
    push( @$cols, $self->_getNameColumnHash( 'status',            'status' ) );
    push( @$cols, $self->_getNameColumnHash( 'address-1',         'address_1' ) );
    push( @$cols, $self->_getNameColumnHash( 'address-2',         'address_2' ) );
    push( @$cols, $self->_getNameColumnHash( 'address-3',         'address_3' ) );
    push( @$cols, $self->_getNameColumnHash( 'city',              'city' ) );
    push( @$cols, $self->_getNameColumnHash( 'state-province',    'state' ) );
    push( @$cols, $self->_getNameColumnHash( 'zip-postal',        'postal_code' ) );
    push( @$cols, $self->_getNameColumnHash( 'country',           'country' ) );
    push( @$cols, $self->_getNameColumnHash( 'email',             'email' ) );
    push( @$cols, $self->_getNameColumnHash( 'phone',             'phone' ) );
    push( @$cols, $self->_getNameColumnHash( 'fax',               'fax' ) );
    push( @$cols, $self->_getNameColumnHash( 'publisher-type',    'publisher_type' ) );
    push( @$cols, $self->_getNameColumnHash( 'admin',             'admin' ) );
    push( @$cols, $self->_getNameColumnHash( 'agent',             'agent' ) );
    push( @$cols, $self->_getNameColumnHash( 'tax-id',            'tax_id' ) );

    push @$cols,
      {
        header => {
            name => 'affiliation',
        },
        column => {
            field  => 'affiliate_id',
            method => '_idToAffiliate',
        }
      };
    push( @$cols, $self->_getNameColumnHash( 'comments', 'comments' ) );

    # for "US Publishers" only
    if ( $self->Type eq "US Publishers" ) {
        push @$cols,
          {
            header => {
                name => 'publisher-statement-distribution',
            },
            column => {
                field  => 'distribution',
                method => '_distributionIdToName',
            }
          };
        push( @$cols, $self->_getNameColumnHash( 'publisher-statement-distribution-status', 'distribution_status' ) );
    }

    push @$cols,
      {
        header => {
            name => 'publisher-date-created',
        },
        column => {
            field  => 'date_created',
            method => '_formatDate',
            excel  => 'date:Y-M-D',
        }
      };
    push @$cols,
      {
        header => {
            name => 'publisher-created-by',
        },
        column => {
            field  => 'created_by',
            method => '_userIDToUserName',
        }
      };
    push @$cols,
      {
        header => {
            name => 'publisher-date-modified',
        },
        column => {
            field  => 'date_modified',
            method => '_formatDate',
            excel  => 'date:Y-M-D',
        }
      };
    push @$cols,
      {
        header => {
            name => 'publisher-modified-by',
        },
        column => {
            field  => 'modified_by',
            method => '_userIDToUserName',
        }
      };
    push( @$cols, $self->_getNameColumnHash( 'rs-publisher-id', 'publisher_id' ) );

    my $reportType = $self->Type eq "US Publishers"
        ? $self->parameters()->{OptionalData}->ReportType()
        : '';
    if ( $reportType && $reportType =~ /^PublishersAndRecipients$/i ) {
        push( @$cols, $self->_getNameColumnHash( 'additional-statement-recipient', 'recipient_name' ) );
        push( @$cols, $self->_getNameColumnHash( 'additional-statement-recipient-email', 'recipient_email' ) );
        push( @$cols, $self->_getNameColumnHash( 'additional-statement-recipient-distribution-status', 'recipient_distribution_status' ) );
        push( @$cols, $self->_getNameColumnHash( 'rs-additional-statement-recipient-id', 'recipient_id' ) );
    }

    return $cols;
}

sub _getEmptyColumnHash {
    my ( $self, $name ) = @_;
    return {
        header => { name  => $name, },
        column => { value => '', },
    };
}

my $gAffiliateCache;

sub _idToAffiliate {
    my ( $self, %args ) = @_;
    my $rowItem   = $args{row};
    my $fieldName = $args{field};

    my $id = $rowItem->$fieldName();

    my $affiliate;
    if ($id) {
        if ( !$gAffiliateCache ) {
            $gAffiliateCache = {};
            my $all = RPS::DB::Item::Affiliate->GetAll();
            while ( my $data = $all->next() ) {
                $gAffiliateCache->{ $data->affiliate_id() } = $data->name();
            }
        }

        $affiliate = $gAffiliateCache->{$id};
    }

    return $affiliate;
}

# Overriding this to fetch and return any transactions (if requested and there are any).
#
#sub _nextReportLineData
#{
#    my ($self) = @_;
#
#    # Are we still sending out transactions from the last Publisher?
#    #
#    if (defined $self->{_transactionList} && 0 != scalar @{$self->{_transactionList}})
#    {
#        return $self->_nextReportLineWithTransaction();
#    }
#
#    $self->{_currentLine} = $self->SUPER::_nextReportLineData();
#
#
#    # If we're supposed to be reporting transactions, first try and fetch all of them.
#    # If we got some, then start returning lines with transactions attached.
#    # Otherwise, just return the latest line.
#    #
#    if( $self->{_currentLine} && ($self->_showProcessed() || $self->_showUnprocessed() ) )
#    {
#        $self->_fetchAllTransactions();
#
#
#        # Return the line with transactions, if there were any.
#        #
#        if (defined $self->{_transactionList} && 0 != scalar @{$self->{_transactionList}})
#        {
#            return $self->_nextReportLineWithTransaction();
#        }
#    }
#
#
#    return $self->{_currentLine};
#}
#
#
#my %gTransactionTypes = (
#    RPS::DB::Item::FinanceTransaction::kTypeOpeningBalance()    => 'opening balance',
#    RPS::DB::Item::FinanceTransaction::kTypeAdjustment()        => 'adjustment',
#    RPS::DB::Item::FinanceTransaction::kTypeAdvance()           => 'advance',
#    RPS::DB::Item::FinanceTransaction::kTypePayment()           => 'payment',
#    RPS::DB::Item::FinanceTransaction::kTypeClosingBalance()    => 'closing balance',
#);
#
## So my strategy here is to go ahead and grab _all_ the transactions from all accounts,
## and stuff that data into an array reference.
##
#sub _fetchAllTransactions
#{
#    my ($self) = @_;
#
#    # Make sure we're dealing with an empty array.
#    #
#    $self->{_transactionList} = [];
#
#
#    # We'll need our publisher id.
#    # Note that this is either a 'publisher_id' or a 'ca_publisher_id', depending on
#    # what flavor of report we're building, but we use the same key name in the report header.
#    #
#    if (! $self->{_arrayIndex})
#    {
#        $self->_buildArrayIndex();
#    }
#    my $pubID = $self->{_currentLine}->[ $self->{_arrayIndex}{'rs-publisher-id'} ];
#
#    if (! $pubID)
#    {
##        return;
#    }
#
#    # We'll need a bit of abstraction here, since the US and CA publishers have
#    # different account tables.  Happily, the schemas are virtually identical:  Only
#    # the 'publisher id' key and table keys are different.
#    #
#    my $directAccountCollection = $self->_getDirectAccounts($pubID);
#    while (my $directAccount = $directAccountCollection->next())
#    {
#        my $payor = RPS::DB::Item::Payor->Lookup(payor_id => $directAccount->payor_id());
#
#        if ($self->_showProcessed())
#        {
#            # !!! Do we need to contrain this list by date?
#            #
#            my $transactions = RPS::DB::Item::FinanceTransaction->GetAccountTransactions(finance_account_id => $directAccount->finance_account_id());
#            while (my $t = $transactions->next())
#            {
#                push @{$self->{_transactionList}}, $self->_getTransactionHash($payor, $directAccount->min_payment(), $t->balance(), $t, 'direct', 'processed');
#            }
#        }
#
#        if ($self->_showUnprocessed())
#        {
#            my $transactions = RPS::DB::Item::PendingTransaction->GetAccountTransactions(finance_account_id => $directAccount->finance_account_id());
#            while (my $t = $transactions->next())
#            {
#                push @{$self->{_transactionList}}, $self->_getTransactionHash($payor, $directAccount->min_payment(), '', $t, 'direct', 'pending');
#            }
#        }
#    }
#
#
#    # Now the same thing with the indirect accounts.
#    #
#    my $indirectAccountCollection = $self->_getIndirectAccounts($pubID);
#    while (my $indirectAccount = $indirectAccountCollection->next())
#    {
#        my $payor = RPS::DB::Item::Payor->Lookup(payor_id => $indirectAccount->payor_id());
#
#        if ($self->_showProcessed())
#        {
#            my $transactions = RPS::DB::Item::FinanceTransaction->GetAccountTransactions(finance_account_id => $indirectAccount->finance_account_id());
#            while (my $t = $transactions->next())
#            {
#                # Note that indirect accounts don't have minimum payments.
#                #
#                push @{$self->{_transactionList}}, $self->_getTransactionHash($payor, '', $t->balance(), $t, 'indirect', 'processed');
#            }
#        }
#
#        if ($self->_showUnprocessed())
#        {
#            my $transactions = RPS::DB::Item::PendingTransaction->GetAccountTransactions(finance_account_id => $indirectAccount->finance_account_id());
#            while (my $t = $transactions->next())
#            {
#                push @{$self->{_transactionList}}, $self->_getTransactionHash($payor, '', '', $t, 'indirect', 'pending');
#            }
#        }
#    }
#}
#
#
#sub _getDirectAccounts
#{
#    my ($self, $pubID) = @_;
#    assert(0, 'override');
#}
#
#sub _getIndirectAccounts
#{
#    my ($self, $pubID) = @_;
#    assert(0, 'override');
#}
#
#sub _getTransactionHash
#{
#    my ($self, $payor, $minPayment, $balance, $transaction, $type, $status) = @_;
#
#    return {
#        'payor-name'            => $payor->name(),
#        'client-payor-no'       => $payor->client_payor_id(),
#        'payor-status'          => $payor->inactive() ? 'inactive' : 'active',
#        'default-payor'         => $payor->is_default() ? 'yes' : 'no',
#        'minimum-payment'       => $minPayment,
#        'account-type'          => $type,
#        'transaction-status'    => $status,
#        'transaction-type'      => $gTransactionTypes{ $transaction->type_code() },
#        'amount'                => $transaction->amount(),
#        'transaction-date'      => $transaction->transaction_date(),
#        'check-no'              => $transaction->check_number(),
#        'memo'                  => $transaction->memo(),
#        'balance'               => $balance,
#    };
#}
#
#
#sub _nextReportLineWithTransaction
#{
#    my ($self) = @_;
#
#    # Shift the next transaction off the list.
#    # (We want the one from the front of the list, hence shift).
#    #
#    my $transaction = shift @{$self->{_transactionList}};
#
#    # Populate the transaction columns.
#    #
#    # We need to know the array index for each column.
#    # This can shift around depending on what options were selected.
#    # So we'll build a hash that maps column title to array index.
#    #
#    if (! $self->{_arrayIndex})
#    {
#        $self->_buildArrayIndex();
#    }
#
#    $self->{_currentLine}->[ $self->{_arrayIndex}{'payor-name'} ]               = $transaction->{'payor-name'};
#    $self->{_currentLine}->[ $self->{_arrayIndex}{'client-payor-no'} ]          = $transaction->{'client-payor-no'};
#    $self->{_currentLine}->[ $self->{_arrayIndex}{'payor-status'} ]             = $transaction->{'payor-status'};
#    $self->{_currentLine}->[ $self->{_arrayIndex}{'default-payor'} ]            = $transaction->{'default-payor'};
#    $self->{_currentLine}->[ $self->{_arrayIndex}{'minimum-payment'} ]          = $transaction->{'minimum-payment'};
#    $self->{_currentLine}->[ $self->{_arrayIndex}{'account-type'} ]             = $transaction->{'account-type'};
#    $self->{_currentLine}->[ $self->{_arrayIndex}{'transaction-status'} ]       = $transaction->{'transaction-status'};
#    $self->{_currentLine}->[ $self->{_arrayIndex}{'transaction-type'} ]         = $transaction->{'transaction-type'};
#    $self->{_currentLine}->[ $self->{_arrayIndex}{'amount'} ]                   = $transaction->{'amount'};
#    $self->{_currentLine}->[ $self->{_arrayIndex}{'transaction-date'} ]         = $transaction->{'transaction-date'};
#    $self->{_currentLine}->[ $self->{_arrayIndex}{'check-no'} ]                 = $transaction->{'check-no'};
#    $self->{_currentLine}->[ $self->{_arrayIndex}{'memo'} ]                     = $transaction->{'memo'};
#    $self->{_currentLine}->[ $self->{_arrayIndex}{'balance'} ]                  = $transaction->{'balance'};
#
#
#    return $self->{_currentLine};
#}

sub _buildArrayIndex {
    my ($self) = @_;
    $self->{_arrayIndex} = {};

    my $columns = $self->_columns();
    for ( my $i = 0 ; $i < scalar @$columns ; $i++ ) {
        my $col = $columns->[$i];

        my $colName = $col->{header}{name};
        assert( !defined $self->{_arrayIndex}{$colName} );
        $self->{_arrayIndex}{$colName} = $i;
    }
}


1;

package RPS::Report::Dynamic::Payee::Publishers::Parameters;
use strict;
use warnings;

use lib '/app/tools/common/lib';
use lib '/app/tools/report/lib';
use lib '/app/tools/rps/lib';
use base 'RPS::Report::Dynamic::Payee::Parameters';

sub _OptionalData {
    {
        'ReportType' => {
            type          => Report::Dynamic::Parameters::kTypeRadioGroup,
            order         => 1,
            validValues   => [ 'Publishers', 'PublishersAndRecipients' ],
            displayValues => [ 'Publishers', 'Publishers & Additional Statement Recipients' ],

            value => 'Publishers', # This sets the _default_ value.
            filename => [ 'wPublishers', 'wPublishersAndRecipients' ],
        },
    };
}

1;
