#!/usr/bin/perl
#------------------------------------------------------------
# Copyright (C) 2006 RoyaltyShare, Inc.   All Rights Reserved
#------------------------------------------------------------
use strict;

#use warnings;

use PDF::API2;

use Data::Dumper;
use Getopt::Std;
use Carp;

use lib '/app/tools/common/lib';
use Common::Assert;
use Common::RSMath;
use Common::Locale;
use Common::Client;

use lib '/app/tools/rps/lib';
use RPS::DB::Item::Album;
use RPS::DB::Item::Channel;
use RPS::DB::Item::ContractRateType;
use RPS::DB::Item::MechanicalStatementCrossedLicenseTransaction;
use RPS::DB::Item::IncomeSource;
use RPS::DB::Item::MechanicalRun;
use RPS::DB::Item::MechanicalStatement;
use RPS::DB::Item::MechanicalStatementAdjustmentItem;
use RPS::DB::Item::MechanicalStatementItem;
use RPS::DB::Item::MechanicalStatementLicense;
use RPS::DB::Item::MechanicalStatementLicenseTransaction;
use RPS::DB::Item::MechanicalStatementPublisher;
use RPS::DB::Item::MechanicalStatementPublisherTransaction;
use RPS::DB::Item::MechanicalStatementTrack;
use RPS::DB::Item::MechanicalStatementTransaction;
use RPS::DB::Item::Payor;
use RPS::DB::Item::PriceLevel;
use RPS::DB::Item::Product;
use RPS::DB::Item::ProductType;
use RPS::DB::Item::Publisher;
use RPS::DB::Item::Region;
use RPS::DB::Item::StatRate;
use RPS::RoyaltyRun::Status;

use lib '/app/tools/rps/bin/statements';
use TableObj;
use Formats;
use EmbedImage;

$SIG{__DIE__} = \&Carp::confess;

#
# A lot of this code is taken from this tutorial: http://rick.measham.id.au/pdf-api2/
#

# These constants will make it easier to convert between 'regular' units
# and postscript points.
# There are 72 postscript points in an inch, and 25.4 millimeters in an inch.
# All the PDF::API2 methods expect their size or coordinate arguments to be in points.
#
use constant mm => ( 25.4 / 72 );
use constant in => ( 1 / 72 );
use constant pt => 1;

# The standard page dimensions.  Note that we're creating _landscape_ docs.
#
use constant kPageHeight => ( 8.5 / in );
use constant kPageWidth  => ( 11 / in );

# The margins of the page.
# Remember that (0,0) in PDF coordinates is the bottom-left of the page.
#
use constant kLeftMargin   => 0.5 / in;
use constant kBottomMargin => 0.5 / in;
use constant kRightMargin  => ( kPageWidth - ( 0.5 / in ) );
use constant kTopMargin    => ( kPageHeight - ( 0.5 / in ) );

# We are going to keep track of every page we create, so that we
# can go back later and add page numbers
#
my @gPayeePages;

# We are going to keep track of every page we create, so that we
# can go back later and add page numbers
#
my @gFullPages;

# We'll store a hashref with font info here, once we have a PDF object to work with.
#
my $font;

# This determines how much output we spew forth to STDERR.
# The user can set this with the -V command-line argument.
#
my $gVerbosityLevel = 1;

# Parse the command-line, then create the PDF!
#
my %options;
parseCommandLine( \%options );
createStatementPDF( $options{clientID}, $options{mechanicalStatementID}, $options{mode},
    $options{outputFile} );

# ----------------------------------------------------------------------------------------------

sub createStatementPDF
{
    my ( $clientID, $mechanicalStatementID, $mode, $outFilePath ) = @_;

    # Instantiate the application singleton object.
    #
    my $appSingleton = Common::RSApp->new( clientID => $clientID );

    # Grab the statement item and off we go.
    #
    my $statement = RPS::DB::Item::MechanicalStatement->Lookup(mechanical_statement_id => $mechanicalStatementID); 
    
    # If an output file path was not specified, create one out of the statement id.
    #
    if ( !$outFilePath )
    {
        $outFilePath = "mechanical_statement_$mechanicalStatementID.pdf";
    }    
    
    # Mode can have three different values: p, f, and b.
    # p = Create payee version
    # f = Create full version
    # b = Create both
    #
    
    if ($mode eq 'p' || $mode eq 'b')
    {
        createPayeeStatementPDF( $statement, $outFilePath )
    }

    if ($mode eq 'f' || $mode eq 'b')
    {
        createFullStatementPDF( $statement, $outFilePath )
    }    

}


##########################
# Payee Statement Stuff  #
##########################

sub createPayeeStatementPDF
{
    my ( $statement, $outFilePath ) = @_;

    # Instantiate the PDF object.
    #
    my $pdf = PDF::API2->new( -file => $outFilePath );

    # Fetch the fonts that we might want to use.
    # Note that every time we define a font, it will get embedded in the document,
    # so we will grab them all here at the very beginning.
    # !!! Be sure to remove any of these we don't actually need...
    #
    # (These are the 'built-in' fonts that all pdf documents get for free. We can embed fancy
    #  fonts if we want to, but that will make the statement files larger...)
    #
    $font = {
        Helvetica => {
            Bold  => $pdf->corefont( 'Helvetica-Bold', -encoding => 'latin1' ),
            Roman => $pdf->corefont( 'Helvetica',      -encoding => 'latin1' ),
            Italic =>
              $pdf->corefont( 'Helvetica-Oblique', -encoding => 'latin1' ),
        },
        Times => {
            Bold   => $pdf->corefont( 'Times-Bold',   -encoding => 'latin1' ),
            Roman  => $pdf->corefont( 'Times',        -encoding => 'latin1' ),
            Italic => $pdf->corefont( 'Times-Italic', -encoding => 'latin1' ),
        },
    };

    # Declare the 'cursor' coordinates.  As we go, we'll be updating these values so that the
    # next element shows up in the right place.
    #
    my $x = kLeftMargin;
    my $y = kTopMargin;

    # Create the first (blank) page.
    # Each output subroutine will take the current page as a parameter, and will
    # return the page that they ended on.
    #
    my $page = newPayeePage($pdf);
    
    
	# Add label logo to the first page, if desired
	#	
	my $payor = RPS::DB::Item::Payor->Lookup(payor_id => $statement->payor_id);
	my $showLogo = $payor->show_logo;
		 
    if ($showLogo == 1) 
    {
        my $clientNameClean = Common::Client::Current()->WebAlias();
        $clientNameClean = Common::Client::Current()->ClientNameClean() unless $clientNameClean;
    	($pdf, $page) = EmbedImage::labelLogo($pdf, $page, $clientNameClean, kTopMargin, kRightMargin);
    }
        

    # Each section of the statement will have its own subroutine.
    #
    ( $x, $y, $page ) = payeeHeader( $pdf, $statement, $x, $y, $page );
    ( $x, $y, $page ) = payeeSummary( $pdf, $statement, $x, $y, $page );

    my $publisher = RPS::DB::Item::Publisher->Lookup(publisher_id => $statement->publisher_id);

    # Determine if this is an admin or regular publisher.
    if (   $publisher->is_admin == 1
        || $publisher->is_agency == 1 )
    {

        # Loop through all publishers for admins.
        my $publisherList = RPS::DB::Item::MechanicalStatementPublisher->GetSortedByMechanicalStatementID($statement->mechanical_statement_id);
        
        while (my $subPublisher = $publisherList->next())
        {
            ( $x, $y, $page ) = payeeDetails( $pdf, $subPublisher, $x, $y, $page );
        }
    }
    else
    {

        # Not an admin, so just do this once.
        ( $x, $y, $page ) = payeeDetails( $pdf, $statement, $x, $y, $page );
    }


    # If the state of the run is not 'COMMITTED' or 'CLOSED', then we want to add a watermark
    # to the pages so that our users don't mail this statement out.
    #
    my $run = RPS::DB::Item::MechanicalRun->Lookup( mechanical_run_id => $statement->mechanical_run_id );
    if (   RPS::RoyaltyRun::Status::kCommitted != $run->status
        && RPS::RoyaltyRun::Status::kClosed != $run->status )
    {
        addDraftWatermarkPayee($pdf);
    }

    # Now add the page numbers, and other 'footer' stuff
    #
    payeeFooter($pdf);

    # All done, save and clean up
    #
    $pdf->save();
    $pdf->end();
}

sub payeeHeader
{
    my ( $pdf, $statement, $x, $y, $page ) = @_;

    my $text = $page->text();

    # Step 1 - Put the text 'United States Mechanical Royalty Statement' at the top of the page.
    #
    $y = printText(
        page        => $page,
        display     => 'United States Mechanical Royalty Statement',      
        y           => $y,        
        font        => $font->{Helvetica}{Bold}, 
        fontSize    => 12 / pt,      
        centered    => 1   
    );          

    # Print the 'From: Payor' info
    #
    my $payor = RPS::DB::Item::Payor->Lookup(payor_id => $statement->payor_id);

    my $cityStateLine = $payor->city;
    if ( $payor->city && $payor->state_province )
    {
        $cityStateLine .= ",";
    }
    $cityStateLine .= $payor->state_province;
    
    if ($payor->postal_code)
    {        
        $cityStateLine .=  " " . $payor->postal_code;   
    }    
    

    $y = printText(
        page        => $page,
        display     => 'From:',   
        x           => $x,   
        y           => $y,        
        font        => $font->{Helvetica}{Roman}, 
        fontSize    => 9 / pt  
    );  

    $y = printText(
        page        => $page,
        display     => $payor->name,   
        x           => $x,   
        y           => $y,        
        font        => $font->{Helvetica}{Roman}, 
        fontSize    => 9 / pt  
    );  

    $y = printText(
        page        => $page,
        display     => $payor->street_address,   
        x           => $x,   
        y           => $y,        
        font        => $font->{Helvetica}{Roman}, 
        fontSize    => 9 / pt  
    );  
    
    $y = printText(
        page        => $page,
        display     => $payor->street_address_2,   
        x           => $x,   
        y           => $y,        
        font        => $font->{Helvetica}{Roman}, 
        fontSize    => 9 / pt  
    );      
    
    $y = printText(
        page        => $page,
        display     => $payor->street_address_3,   
        x           => $x,   
        y           => $y,        
        font        => $font->{Helvetica}{Roman}, 
        fontSize    => 9 / pt  
    );      
    
    $y = printText(
        page        => $page,
        display     => $cityStateLine,   
        x           => $x,   
        y           => $y,        
        font        => $font->{Helvetica}{Roman}, 
        fontSize    => 9 / pt  
    );      

    $y = printText(
        page        => $page,
        display     => $payor->country_code,   
        x           => $x,   
        y           => $y,        
        font        => $font->{Helvetica}{Roman}, 
        fontSize    => 9 / pt  
    );   

    # Add in some space, then print the 'To:' info
    #
    $y -= 9 / pt;

    my $payee = RPS::DB::Item::Publisher->Lookup(publisher_id => $statement->publisher_id);

    my $cityStateLine = $payee->city;
    if ( $payee->city && $payee->state_province )
    {
        $cityStateLine .= ",";
    }
    $cityStateLine .= $payee->state_province;
    
    if ($payee->postal_code)
    {        
        $cityStateLine .=  " " . $payee->postal_code;   
    }        
    

    $y = printText(
        page        => $page,
        display     => $payee->publisher_name,   
        x           => $x,   
        y           => $y,        
        font        => $font->{Helvetica}{Roman}, 
        fontSize    => 9 / pt  
    );   
        
    $y = printText(
        page        => $page,
        display     => $payee->street_address,   
        x           => $x,   
        y           => $y,        
        font        => $font->{Helvetica}{Roman}, 
        fontSize    => 9 / pt  
    );     
    
    $y = printText(
        page        => $page,
        display     => $payee->street_address_2,   
        x           => $x,   
        y           => $y,        
        font        => $font->{Helvetica}{Roman}, 
        fontSize    => 9 / pt  
    );   
    
    $y = printText(
        page        => $page,
        display     => $payee->street_address_3,   
        x           => $x,   
        y           => $y,        
        font        => $font->{Helvetica}{Roman}, 
        fontSize    => 9 / pt  
    );                 
        
    $y = printText(
        page        => $page,
        display     => $cityStateLine,   
        x           => $x,   
        y           => $y,        
        font        => $font->{Helvetica}{Roman}, 
        fontSize    => 9 / pt  
    );           
        
    $y = printText(
        page        => $page,
        display     => $payee->country_code,   
        x           => $x,   
        y           => $y,        
        font        => $font->{Helvetica}{Roman}, 
        fontSize    => 9 / pt  
    );           

    # Now print the run label. Which means we need to fetch the run...
    #
    my $run = RPS::DB::Item::MechanicalRun->Lookup( mechanical_run_id => $statement->mechanical_run_id);
 
    $y -= 9 / pt;
    
    $y = printText(
        page        => $page,
        display     => $run->label,   
        x           => $x,   
        y           => $y,        
        font        => $font->{Helvetica}{Bold}, 
        fontSize    => 9 / pt  
    );             

    $y -= 18 / pt;

    return ( $x, $y, $page );
}

sub payeeSummary
{
    my ( $pdf, $statement, $x, $y, $page ) = @_;

    ( $x, $y, $page ) = drawBalanceTable( $pdf, $statement, $x, $y, $page, \&newPayeePage );

    my $publisher = RPS::DB::Item::Publisher->Lookup(publisher_id => $statement->publisher_id);

    # Determine if this is an admin or regular publisher.
    if ( $publisher->is_admin == 1 || $publisher->is_agency == 1 )
    {
        ( $x, $y, $page ) =
          payeePublisherTable( $pdf, $statement, $x, $y, $page );
    }

    #$y -= 18;

    return ( $x, $y, $page );
}

sub payeePublisherTable
{
    my ( $pdf, $statement, $x, $y, $page ) = @_;
    my $fontSize = 7 / pt;

    my $text = $page->text();

    # We'll create a 2-d array that contains the data we want to display.
    #
    my @publisherArray;

    # This array will keep track of various row properties.
    # We're going to change the font for a couple of rows (such as the header),
    # and do a few more tricks.
    #
    my @rowProperties;



    # Get any publishers
    #
    my $publisherList = RPS::DB::Item::MechanicalStatementPublisher->GetSortedByMechanicalStatementID($statement->mechanical_statement_id);
  
    if ($publisherList->hasNext())
    {

        # The column headers
        #
        push @publisherArray, [ ' ', ' ', ' ', ' ', ' ' ];
        push @rowProperties, {};
        push @publisherArray, [ ' ', ' ', ' ', ' ', ' ' ];
        push @rowProperties, {};
        push @publisherArray, [ 'Publisher', 'Amount Due' ];
        push @rowProperties,
          {
            font  => $font->{Helvetica}{Bold},
            lines => [
                {
                    start_col => 0,
                    end_col   => 1,
                    top_pad   => 4,
                },
            ],
          };
    
    
        while (my $subPublisher = $publisherList->next())
        {
            my $publisherItem = RPS::DB::Item::Publisher->Lookup(publisher_id => $subPublisher->publisher_id);
            my $name   = $publisherItem->publisher_name();
            my $amount = formatMoney( $subPublisher->amount_due() );
            
#            if ($statement->on_hold == 1 || $subPublisher->on_hold == 1)
            if ($subPublisher->on_hold == 1)
            {
                $amount = "ON-HOLD";   
            }
            
            $amount = ' ' unless defined $amount;               
    
            push @publisherArray, [ $name, $amount ];
            push @rowProperties, {};
        }
    
        my $tableObj = TableObj->new(
            $pdf, $page, \@publisherArray,
            bottom_margin => kBottomMargin + 20,
            new_page_y    => kTopMargin - 20,
            new_page_func => \&newPayeePage,
            font          => $font->{Helvetica}{Roman},
            font_size     => $fontSize,
            column_props  => [
                {
                    min_w     => 0.5 / in,
                    font      => $font->{Helvetica}{Roman},
                    font_size => $fontSize,
                },
                {
                    min_w     => 0.5 / in,
                    font      => $font->{Helvetica}{Roman},
                    font_size => $fontSize,
                    justify   => 'right',
                },
            ],
            row_props => \@rowProperties,
        );
    
        ( $page, $y ) = $tableObj->print( $x, $y );
    
    }

    return ( $x, $y, $page );
}

sub payeeDetails
{
    my ( $pdf, $statement, $x, $y, $page ) = @_;
    my $fontSize = 7 / pt;

    # We need to know if this is an admin statement
    my $whatAmI = ref($statement);

    # start details on a new page
    $page = newPayeePage($pdf);
    $y    = kTopMargin - 10;

    # If Admin, print this Publisher's Name at the top.
    if ( 'RPS::DB::Item::MechanicalStatementPublisher' eq $whatAmI )
    {
        my $publisher = RPS::DB::Item::Publisher->Lookup(publisher_id => $statement->publisher_id);

        $y = printText(
            page        => $page,
            display     => $publisher->publisher_name,      
            y           => $y,        
            font        => $font->{Helvetica}{Bold}, 
            fontSize    => 12 / pt,      
            centered    => 1   
        );                 
        
    }

    my @rows;
    my @rowProps;

    # Set up the header
    #
    push @rows, [ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' ];
    push @rowProps, {
        font  => $font->{Helvetica}{Bold},
        lines => [
            {
                start_col => 0,
                end_col   => 9,
                top_pad   => 4,

                # bottom_pad => 2,
            },
        ],
    };
    push @rows,
      [
        'Track Title',
        'Album Title',
        'UPC',
        'Product Config',
        'Region',
        'Rate Period',
        'Share',
        'Net Rate',
        'Net Units',
        'Amount Due'
      ];
    push @rowProps, {
        font   => $font->{Helvetica}{Bold},
        repeat => 1,
        lines  => [
            {
                start_col => 0,
                end_col   => 9,
                top_pad   => 4,

                # bottom_pad => 2,
            },
        ],
    };

    # Add the track details.
    #
    my $statementTrackCollection;
    if ('RPS::DB::Item::MechanicalStatementPublisher' eq $whatAmI)
    {
        $statementTrackCollection = RPS::DB::Item::MechanicalStatementTrack->GetSortedByMechanicalStatementIDPublisherID($statement->mechanical_statement_id, $statement->publisher_id);
    }
    else
    {
        $statementTrackCollection = RPS::DB::Item::MechanicalStatementTrack->GetSortedByMechanicalStatementID($statement->mechanical_statement_id);
    }
    
	while ($statementTrackCollection->hasNext())
	{
		my $statementTrack = $statementTrackCollection->next();    
        payeeTrackDetails( $statementTrack, $statement, \@rows, \@rowProps )
    }    
    
    # Force the columns to be fixed width.
    #
    my @colProps = (
        {

            # track title
            min_w => 2 / in,
            max_w => 2 / in,
            pad   => 0,
        },
        {

            # album title
            min_w => 1.8 / in,
            max_w => 1.8 / in,
            pad   => 0,
        },
        {

            # upc
            min_w => 0.75 / in,
            max_w => 0.75 / in,
            pad   => 0,
        },
        {

            # product config
            min_w => 0.75 / in,
            max_w => 0.75 / in,
            pad   => 0,
        },
        {

            # region
            min_w => 0.65 / in,
            max_w => 0.65 / in,
            pad   => 0,
        },
        {

            # rate period
            min_w => 0.60 / in,
            max_w => 0.60 / in,
            pad   => 0,
        },
        {

            # share
            min_w => 0.5 / in,
            max_w => 0.5 / in,
            pad   => 0,
        },
        {

            # net rate
            min_w => 0.5 / in,
            max_w => 0.5 / in,
            pad   => 0,
        },
        {

            # net units
            justify => 'right',
            min_w   => 1.45 / in,
            max_w   => 1.45 / in,
            pad     => 0,
        },
        {

            # amount due
            justify => 'right',
            min_w   => 1 / in,
            max_w   => 1 / in,
            pad     => 0,
        },
    );

    my $tableObj = TableObj->new(
        $pdf, $page, \@rows,
        bottom_margin => kBottomMargin +
          20,    # adding a bit of padding to avoid weirdness
        new_page_y    => kTopMargin - 20,             # ditto
        new_page_func => \&newPayeePage,
        font          => $font->{Helvetica}{Roman},
        font_size     => $fontSize,
        column_props  => \@colProps,
        row_props     => \@rowProps,
    );

    ( $page, $y ) = $tableObj->print( $x, $y );

    # Last, print the grand total
    #

    my @totalRows;
    my @totalRowProps;

    if ( 'RPS::DB::Item::MechanicalStatementPublisher' eq $whatAmI )
    {
        my $previousBalance = $statement->previous_balance;
        
        # Add the transactions in.
        #		
        my $transactionCollection = RPS::DB::Item::MechanicalStatementPublisherTransaction->GetByMechanicalStatementAndPublisherID($statement->mechanical_statement_id, $statement->publisher_id);
        
        my $transactionCount = RPS::DB::Item::MechanicalStatementPublisherTransaction->GetCountByMechanicalStatementAndPublisherID($statement->mechanical_statement_id, $statement->publisher_id);
        
        if ($previousBalance != 0 || $transactionCount > 0)
        { 
            push @totalRows,  [ 'Publisher Subtotal:', formatMoney($statement->subtotal) ];
        
            if ($previousBalance != 0)
            {
                push @totalRows,  [ 'Previous Balance:', formatMoney($statement->previous_balance) ]; 
                push @totalRowProps, {};
            } 
            
        	while ($transactionCollection->hasNext())
        	{
        		my $transaction = $transactionCollection->next();  
                my $type;
                if ( $transaction->type_code == 2 )
                {
                    $type = 'Adjustment';
                }
                elsif ( $transaction->type_code == 3 )
                {
                    $type = 'Advance';
                }
                elsif ( $transaction->type_code == 4 )
                {
                    $type = 'Payment';
                }           
                push @totalRows,  [ "$type:", formatMoney($transaction->amount) ];
                push @totalRowProps, {};
            }
            
            push @totalRows,  [ 'Ending Balance:', formatMoney($statement->statement_total) ]; 
            # Note that this will actually go above the ending balance, since we did't add an element to the 
            # array for the subtotal.
            #
            push @totalRowProps, {              
                repeat => 1,
                lines  => [
                    {
                        start_col  => 1,
                        end_col    => 1,    
                        top_pad    => 2,
                        bottom_pad => -1, 
                    },
                ],
            };   
            
            push @totalRows, [];
            push @totalRowProps, { font   => $font->{Helvetica}{Bold} };       
        }

        my $amountDue;
        my $parentStatement = RPS::DB::Item::MechanicalStatement->Lookup(mechanical_statement_id => $statement->mechanical_statement_id);
#        if ($parentStatement->on_hold == 1 || $statement->on_hold == 1)
        if ($statement->on_hold == 1)
        {
            $amountDue = "ON-HOLD";   
        }
        else
        {
            $amountDue = formatMoney($statement->amount_due)   
        }
            
             
        push @totalRows,  [ 'Publisher Amount Due:', $amountDue ];       
        push @totalRowProps, { font => $font->{Helvetica}{Bold} };
        
        # And now an extra one to make up for the subtotal row not having one.
        #
        push @totalRowProps, { font => $font->{Helvetica}{Bold} };

    }
    else
    {
        push @totalRows,  [ 'Total:', formatMoney($statement->subtotal) ];
        push @totalRowProps, { font => $font->{Helvetica}{Bold} };
    }

    $y -= 5 / pt;

    my $table = TableObj->new(
        $pdf, $page, \@totalRows,
        bottom_margin => kBottomMargin +
          20,    # adding a bit of padding to avoid weirdness
        new_page_y    => kTopMargin - 10,            # ditto
        new_page_func => \&newPayeePage,
        font          => $font->{Helvetica}{Roman},
        font_size     => $fontSize,
        column_props  => [
            {
                justify => 'right',
                min_w   => 9 / in,
                pad     => 0,
                font          => $font->{Helvetica}{Bold},
            },
            {
                justify => 'right',
                min_w   => 1 / in,
                pad     => 0,
            },
        ],
        row_props     => \@totalRowProps,
    );
    ( $page, $y ) = $table->print( $x, $y );

    return ( $x, $y, $page );
}

sub payeeTrackDetails
{
    my ( $track, $statement, $rows, $rowDetails ) = @_;

    payeeCrossedLicenseDetails( $track, $statement, $rows, $rowDetails );
    payeeLicenseDetails( $track, $statement, $rows, $rowDetails );
}

sub payeeCrossedLicenseDetails
{
    my ( $statementTrack, $statement, $rows, $rowProps ) = @_;

    my $track = RPS::DB::Item::Track->Lookup(track_id => $statementTrack->track_id);
    my $album = RPS::DB::Item::Album->Lookup(album_id => $statementTrack->album_id);

    # Go through the entire (crossed) license list
    #
    my $licenseCollection = RPS::DB::Item::MechanicalStatementLicense->GetByMechanicalStatementIDTrackIDPublisherID($statement->mechanical_statement_id, $statementTrack->track_id, $statement->publisher_id);
    
    my $licenseCount = 0;

    my $lastRow;
    my $lastCellArray;

	while ($licenseCollection->hasNext())
	{
		my $license = $licenseCollection->next();
		my $statementTrackLicense = RPS::DB::Item::TrackLicense->Lookup(track_license_id => $license->track_license_id);

        next if (! $license->crossed);    
        
        $licenseCount++;

        my $incomeItemCollection = RPS::DB::Item::MechanicalStatementItem->GetByStatementAndTrackLicense($statement->mechanical_statement_id, $license->track_license_id);
        
        my $itemCount = 0;
        
    	while ($incomeItemCollection->hasNext())
    	{
    		my $incomeItem = $incomeItemCollection->next();        
			$itemCount++;
			
			# We need to grab the album title from the product.
			# If it's a track product, we'll need to grab it from the parent product.
			my $product = RPS::DB::Item::Product->Lookup( product_id => $incomeItem->product_id );
			my $albumTitle = _getAlbumTitle( $product, $album->title );
		                
			# We have to check the license product type id to see 
			# if we're dealing with a ringtone.
			#
			my $productTypeID = _checkForRingtone( $statementTrackLicense, $incomeItem );
			
            my $statRateIDToUse = $incomeItem->applied_stat_rate_id;
            if (! $statRateIDToUse)
            {
                $statRateIDToUse = $incomeItem->sale_stat_rate_id;
            }
            my $ratePeriod = _getRatePeriod($statRateIDToUse);    
    
            push @$rows,
              [
                $track->title,
                $albumTitle,
                $incomeItem->upc,
                productCodeToName( $productTypeID ),
                regionIDToName( $statementTrackLicense->region_id ),
                $ratePeriod,
                formatPercent( $statementTrackLicense->share ),
                formatNumber( $incomeItem->net_rate ),
                formatNumber( $incomeItem->net_units ),
                formatMoney( $incomeItem->amount_paid ),
              ];
		
		
			if ( ($itemCount == 1) && ($licenseCount != 1) ) 
			{
                push @$rowProps, {
            		pad => 8,	
            	};			
            }
            else
            {							
                push @$rowProps, {};
		    }

		}
		
		if ($itemCount == 0)
		{
		
            # Even if there are no income items,
            # we still want to display the track info.
            push @$rows,
              [
                $track->title(), $album->title(), ' ', ' ',
                regionIDToName( $statementTrackLicense->region_id() ),
                ' ', ' ', ' ', ' ', ' ',
              ];
    
            push @$rowProps, {
            		pad => 8,	
            };
		
		}
		

        # Add the controlled comp adjustments
        #
        
        my $adjustmentCollection = RPS::DB::Item::MechanicalStatementAdjustmentItem->GetByMechanicalStatementIDTrackLicenseID($statement->mechanical_statement_id, $license->track_license_id);

    	while ($adjustmentCollection->hasNext())
    	{
    		my $adjustment = $adjustmentCollection->next();            

            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                'Controlled Comp Adjustment:',
                formatMoney( $adjustment->amount )
              ];
        
            push @$rowProps, {};
        
        }		
		
		       
		        
        #  Now we want to display the subtotal, previous balance, transactions, etc. for this license
        #
        
	    # We want a little line above the subtotal.
        #
        my $numRows = scalar(@$rowProps);
        my $lastRowPropHashref = $$rowProps[ ( $numRows - 1 ) ];
        $lastRowPropHashref->{lines} = [
            {
                start_col => 9,
                end_col   => 9,
                top_pad   => 2,

                # bottom_pad => 2,
            },
        ];
        

        # Add the license summary stuff.
        #
        # We are going to change a lot of things if there is no previous balance
        # OR license transactions.  So let's check for them now.      
        my $previousBalance = $license->previous_advance_balance();

        push @$rows,
          [
            ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
            'Current Period License Subtotal:',
            formatMoney( $license->subtotal )
          ];

        push @$rowProps, {
						pad => -1,
        };
        
        # Add the transactions in.
        #		
        my $transactionCollection = RPS::DB::Item::MechanicalStatementLicenseTransaction->GetByMechanicalStatementLicenseID($license->mechanical_statement_license_id);
        
        my $transactionCount = 0;		

    	while ($transactionCollection->hasNext())
    	{
    		my $licenseTransaction = $transactionCollection->next();        
			$transactionCount++;        
        
		
            my $transactionType;
            if ( $licenseTransaction->type_code == 3 )
            {
                $transactionType = 'Advance:';
            }
            else
            {
                $transactionType = 'Adjustment:';
            }

            my $memo = ' ';
            if ( $licenseTransaction->memo )
            {
                $memo = '(' . $licenseTransaction->memo . ') ';
            }

            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                $memo . $transactionType,
                formatMoney( $licenseTransaction->amount )
              ];
            push @$rowProps, {};
        }
		
		if ($transactionCount > 0)
		{
		
            # We want a little line under the last transaction.
            #
            my $numRows = scalar(@$rowProps);
            my $lastRowPropHashref = $$rowProps[ ( $numRows - 1 ) ];
            $lastRowPropHashref->{lines} = [
                {
                    start_col => 9,
                    end_col   => 9,
                    top_pad   => 2,
    
                    # bottom_pad => 2,
                },
            ];
        }
        
		
        if ( ( $previousBalance != 0 ) || ($license->advance_balance != 0) )
        {
            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                'Previous License Balance:',
                formatMoney($previousBalance)
              ];

            push @$rowProps, {
                lines => [
                    {
                        start_col => 9,
                        end_col   => 9,
                        top_pad   => 2,

                        # bottom_pad => 2,
                    },
                ],
            };
		
            my $licenseBalance = $license->advance_balance;

            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                'License Balance Forward:',
                formatMoney($licenseBalance)
              ];
            push @$rowProps, {
								pad => -1,		            	
                lines => [
                    {
                        start_col => 9,
                        end_col   => 9,
                        top_pad   => 2,

                        # bottom_pad => 2,
                    },
                ],
            };
        }
		
        # And really, truly finally, the adjusted subtotal if need be.
        #
        if ( ( $transactionCount != 0 ) || ( $previousBalance != 0 ) || ($license->subtotal != $license->adjusted_subtotal ))
        {
            my $licenseBalance = $license->adjusted_subtotal;

            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                'License Adjusted Subtotal:',
                formatMoney($licenseBalance)
              ];
            push @$rowProps, {
            		pad => -1,	
            };
        }	
        
        $licenseCount++;	
    }        
        
    if ($licenseCount > 0)
    {

        # Add the license summary stuff.
        #
        # We are going to change a lot of things if there is no previous balance
        # OR license transactions.  So let's check for them now.    
        
        my $previousBalance = $statementTrack->crossed_previous_advance_balance;

        push @$rows,
          [
            ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
            'Current Period Crossed Subtotal:',
            formatMoney( $statementTrack->crossed_subtotal )
          ];
        push @$rowProps, {
						pad => 8,
        };         


        # Add the transactions in.
        #    
        my $crossedTransactionCollection = RPS::DB::Item::MechanicalStatementCrossedLicenseTransaction->GetByMechanicalStatementIDPublisherIDTrackID($statement->mechanical_statement_id, $statement->publisher_id, $statementTrack->track_id);
        
        my $crossedTransactionCount = 0;		
    
    	while ($crossedTransactionCollection->hasNext())
    	{
    		my $crossedTransaction = $crossedTransactionCollection->next();        
    		$crossedTransactionCount++;    
    		
            my $transactionType;
            if ( $crossedTransaction->type_code == 3 )
            {
                $transactionType = 'Advance:';
            }
            else
            {
                $transactionType = 'Adjustment:';
            }

            my $memo = ' ';
            if ( $crossedTransaction->memo )
            {
                $memo = '(' . $crossedTransaction->memo . ') ';
            }

            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                $memo . $transactionType,
                formatMoney( $crossedTransaction->amount )
              ];
            push @$rowProps, {};
        }


        if ($crossedTransactionCount > 0)
        {
            # We want a little line under the last transaction.
            #
            my $numRows = scalar(@$rowProps);
            my $lastRowPropHashref = $$rowProps[ ( $numRows - 1 ) ];
            $lastRowPropHashref->{lines} = [
                {
                    start_col => 9,
                    end_col   => 9,
                    top_pad   => 2,
                },
            ];
        }

        if ( ( $previousBalance != 0 ) || ($statementTrack->crossed_advance_balance != 0) )
        {
            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                'Previous Crossed Balance:',
                formatMoney($previousBalance)
              ];

            push @$rowProps, {
                lines => [
                    {
                        start_col => 9,
                        end_col   => 9,
                        top_pad   => 2,
                    },
                ],
            };

            my $licenseBalance = $statementTrack->crossed_advance_balance;

            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                'Crossed Balance Forward:',
                formatMoney($licenseBalance)
              ];
              
	        push @$rowProps, {
							pad => -1,
	        };

        }

        # And really, truly finally, the adjusted subtotal if need be.
        #
        if ( ( $crossedTransactionCount != 0 ) || ( $previousBalance != 0 ) || ($statementTrack->crossed_subtotal != $statementTrack->crossed_adjusted_subtotal ))
        {
            my $licenseBalance = $statementTrack->crossed_adjusted_subtotal;

            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                'Crossed Adjusted Subtotal:',
                formatMoney($licenseBalance)
              ];
	        push @$rowProps, {};
        }


        # We want the last item to have a line underneath it.
        pop(@$rowProps);        
        push @$rowProps, {
            pad => 8,
            lines => [
                {
                    start_col => 0,
                    end_col   => 9,
                    top_pad   => 2,
                },
            ],
        };        
        
    }
}

sub payeeLicenseDetails
{
    my ( $statementTrack, $statement, $rows, $rowProps ) = @_;

    my $track = RPS::DB::Item::Track->Lookup(track_id => $statementTrack->track_id);
    my $album = RPS::DB::Item::Album->Lookup(album_id => $statementTrack->album_id);

    # Go through the entire (uncrossed) license list
    #
    my $licenseCollection = RPS::DB::Item::MechanicalStatementLicense->GetByMechanicalStatementIDTrackIDPublisherID($statement->mechanical_statement_id, $statementTrack->track_id, $statement->publisher_id);

    my $licenseCount = 0;

	while ($licenseCollection->hasNext())
	{
		my $license = $licenseCollection->next();
		my $statementTrackLicense = RPS::DB::Item::TrackLicense->Lookup(track_license_id => $license->track_license_id);

        next if ($license->crossed);  
        
        $licenseCount++;

        my $incomeItemCollection = RPS::DB::Item::MechanicalStatementItem->GetByStatementAndTrackLicense($statement->mechanical_statement_id, $license->track_license_id);
        
        my $itemCount = 0;
        
    	while ($incomeItemCollection->hasNext())
    	{
    		my $incomeItem = $incomeItemCollection->next();        
			$itemCount++;                

			# We need to grab the album title from the product.
			# If it's a track product, we'll need to grab it from the parent product.
			my $product = RPS::DB::Item::Product->Lookup( product_id => $incomeItem->product_id );
			my $albumTitle = _getAlbumTitle( $product, $album->title );
			         
			# We have to check the license product type id to see 
			# if we're dealing with a ringtone.
			#
			my $productTypeID = _checkForRingtone( $statementTrackLicense, $incomeItem );				                

            my $statRateIDToUse = $incomeItem->applied_stat_rate_id;
            if (! $statRateIDToUse)
            {
                $statRateIDToUse = $incomeItem->sale_stat_rate_id;
            }
            my $ratePeriod = _getRatePeriod($statRateIDToUse);   

            push @$rows,
              [
                $track->title,
                $albumTitle,
                $incomeItem->upc,
                productCodeToName( $productTypeID ),
                regionIDToName( $license->region_id ),
                $ratePeriod,
                formatPercent( $statementTrackLicense->share ),
                formatNumber( $incomeItem->net_rate ),
                formatNumber( $incomeItem->net_units ),
                formatMoney( $incomeItem->amount_paid ),
              ];

            push @$rowProps, {};

        }
             
        if ($itemCount == 0)
        {
    
            # Even if there are no income items,
            # we still want to display the track info.
            push @$rows,
              [
                $track->title, $album->title, ' ', ' ',
                regionIDToName( $license->region_id ),
                ' ', ' ', ' ', ' ', ' ',
              ];
    
            push @$rowProps, {};
    
        }
        
        
        # Add the controlled comp adjustments
        #
        
        my $adjustmentCollection = RPS::DB::Item::MechanicalStatementAdjustmentItem->GetByMechanicalStatementIDTrackLicenseID($statement->mechanical_statement_id, $license->track_license_id);

    	while ($adjustmentCollection->hasNext())
    	{
    		my $adjustment = $adjustmentCollection->next();            

            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                'Controlled Comp Adjustment:',
                formatMoney( $adjustment->amount )
              ];
        
            push @$rowProps, {};
        
        }

        # We want a little line above the total
        #
        my $numRows = scalar(@$rowProps);
        my $lastRowPropHashref = $$rowProps[ ( $numRows - 1 ) ];
        $lastRowPropHashref->{lines} = [
            {
                start_col => 9,
                end_col   => 9,
                top_pad   => 2,
    
                # bottom_pad => 2,
            },
        ];
        

        # Add the license summary stuff.
        #
        # We are going to change a lot of things if there is no previous balance
        # OR license transactions.  So let's check for them now.  
        my $previousBalance         = $license->previous_advance_balance;
    
        push @$rows,
          [
            ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
            'Current Period License Subtotal:',
            formatMoney( $license->subtotal )
          ];
    
        push @$rowProps, {
    					pad => -1,
        };


        # Add the transactions in.
        #		
        my $transactionCollection = RPS::DB::Item::MechanicalStatementLicenseTransaction->GetByMechanicalStatementLicenseID($license->mechanical_statement_license_id);
        
        my $transactionCount = 0;		

    	while ($transactionCollection->hasNext())
    	{
    		my $licenseTransaction = $transactionCollection->next();        
			$transactionCount++;

            my $transactionType;
            if ( $licenseTransaction->type_code == 3 )
            {
                $transactionType = 'Advance:';
            }
            else
            {
                $transactionType = 'Adjustment:';
            }

            my $memo = ' ';
            if ( $licenseTransaction->memo )
            {
                $memo = '(' . $licenseTransaction->memo . ') ';
            }

            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                $memo . $transactionType,
                formatMoney( $licenseTransaction->amount )
              ];
            push @$rowProps, {};
        }

        if ($transactionCount > 0)
        {
            # We want a little line under the last transaction.
            #
            my $numRows = scalar(@$rowProps);
            my $lastRowPropHashref = $$rowProps[ ( $numRows - 1 ) ];
            $lastRowPropHashref->{lines} = [
                {
                    start_col => 9,
                    end_col   => 9,
                    top_pad   => 2,
                },
            ];
        }

        if ( ( $previousBalance != 0 ) || ($license->advance_balance != 0) )
        {
            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                'Previous License Balance:',
                formatMoney($previousBalance)
              ];

            push @$rowProps, {
                lines => [
                    {
                        start_col => 9,
                        end_col   => 9,
                        top_pad   => 2,
                    },
                ],
            };

            my $licenseBalance = $license->advance_balance;

            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                'License Balance Forward:',
                formatMoney($licenseBalance)
              ];
            push @$rowProps, {
								pad => -1,		            	
                lines => [
                    {
                        start_col => 9,
                        end_col   => 9,
                        top_pad   => 2,
                    },
                ],
            };
        }

        # And really, truly finally, the adjusted subtotal if need be.
        #
        if ( ( $transactionCount != 0 ) || ( $previousBalance != 0 ) || ($license->subtotal != $license->adjusted_subtotal ))
        {
            my $licenseBalance = $license->adjusted_subtotal;

            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                'License Adjusted Subtotal:',
                formatMoney($licenseBalance)
              ];
            push @$rowProps, {}; 
        } 

        # We want the last item to have a line underneath it.
        pop(@$rowProps);        
        push @$rowProps, {
            pad => -1,
            lines => [
                {
                    start_col => 0,
                    end_col   => 9,
                    top_pad   => 2,
                },
            ],
        };   
             
    }
}

sub payeeFooter
{
    my ($pdf) = @_;

    my $pageCount = 1;
    my $numPages  = scalar @gPayeePages;
    foreach my $page (@gPayeePages)
    {
        my $text = $page->text;
        
        printText(
            page        => $page,
            display     => "$pageCount of $numPages",      
            y           => kBottomMargin,        
            font        => $font->{Helvetica}{Roman}, 
            fontSize    => 12 / pt,      
            centered    => 1   
        );            
        
        $pageCount++;
    }
}

sub newPayeePage
{
    my ($pdf) = @_;

    my $page = $pdf->page;

    # the mediabox is the size of the paper.
    #
    $page->mediabox( kPageWidth, kPageHeight );

# the cropbox defines the margins, essentially.
# the args are the coordinates for the left, bottom, right, and top (in that order)
#

# !!! Rather than set the cropbox right to the margins, I am going to make it larger.
# !!! Basically, I want to have this thing render in the viewer with the appearance of having
# !!! margins.
#
#    $page->cropbox(kLeftMargin, kBottomMargin, kRightMargin, kTopMargin);
    $page->cropbox( 5, 5, kPageWidth - 5, kPageHeight - 5 );

# Not currently declaring a 'bleedbox' or an 'artbox'.  Check out the tutorial if you want to
# know what those are... the url for that is at the top of this file.
#
    push @gPayeePages, $page;

    return $page;
}



##########################
# Shared Statement Stuff #
##########################

sub drawBalanceTable
{
    my ( $pdf, $statement, $x, $y, $page, $newPageFuncRef ) = @_;
    my $fontSize = 7 / pt;

    my $text = $page->text();

    # We'll create a 2-d array that contains the data we want to display.
    #
    my @balanceArray;

    # This array will keep track of various row properties.
    # We're going to change the font for a couple of rows (such as the header),
    # and do a few more tricks.
    #
    my @rowProperties;

    # The column headers
    #
    push @balanceArray, [ ' ', 'Amount', 'Check #', 'Date', 'Memo' ];
    push @rowProperties, { font => $font->{Helvetica}{Bold}, };

    # The first line
    #
    push @balanceArray,
      [
        "Previous Period Balance",
        formatMoney( $statement->previous_balance() ),
        ' ', ' ', ' '
      ];
    push @rowProperties, {};

    # Get any transactions
    #
    my $transactionCollection = RPS::DB::Item::MechanicalStatementTransaction->GetByMechanicalStatementID($statement->mechanical_statement_id);		

	while ($transactionCollection->hasNext())
	{
		my $transaction = $transactionCollection->next();  
        my $type;
        if ( $transaction->type_code == 2 )
        {
            $type = 'Adjustment';
        }
        elsif ( $transaction->type_code == 3 )
        {
            $type = 'Advance';
        }
        elsif ( $transaction->type_code == 4 )
        {
            $type = 'Payment';
        }
        my $amount = formatMoney( $transaction->amount );
        $amount = ' ' unless defined $amount;
        my $checkNum = $transaction->check_number;
        $checkNum = ' ' unless defined $checkNum;
        my $date = $transaction->transaction_date;
        $date = ' ' unless defined $date;
        my $memo = $transaction->memo;
        $memo = ' ' unless defined $memo;

        push @balanceArray, [ $type, $amount, $checkNum, $date, $memo ];
        push @rowProperties, {};
    }

    push @balanceArray,
      [
        'Current Period Royalties:',
        formatMoney( $statement->subtotal ),
        ' ', ' ', ' '
      ];
    push @rowProperties, {
        lines => [
            {

                # pen_size => 1,
                # color => 'black',
                start_col => 0,
                end_col   => 1,
                top_pad   => 4,

                # bottom_pad => 2,
            },
        ],
    };

    if ( $statement->previous_advance_balance != 0 )
    {
        push @balanceArray,
          [
            'Previous Advance Balance:',
            formatMoney( $statement->previous_advance_balance() ),
            ' ', ' ', ' '
          ];
        push @rowProperties, {};
        push @balanceArray,
          [
            'Applied To Advance:',
            formatMoney( $statement->applied_to_advance() ),
            ' ', ' ', ' '
          ];
        push @rowProperties, {};
        push @balanceArray,
          [
            'Current Advance Balance:',
            formatMoney( $statement->advance_balance() ),
            ' ', ' ', ' '
          ];
        push @rowProperties, {
            lines => [
                {

                    # pen_size => 1,
                    # color => 'black',
                    start_col => 0,
                    end_col   => 1,
                    top_pad   => 4,

                    # bottom_pad => 2,
                },
            ],
        };
    }

    # figure out what value to use for Ending Balance
    my $endingBalance;
    if ( $statement->balance != 0 )
    {
        $endingBalance = $statement->balance;
    }
    elsif ( $statement->amount_due() != 0 )
    {
        $endingBalance = $statement->amount_due;
    }
    else
    {
        $endingBalance = $statement->statement_total;
    }

    push @balanceArray,
      [ 'Ending Balance:', formatMoney($endingBalance), ' ', ' ', ' ' ];
    push @rowProperties, { font => $font->{Helvetica}{Bold} };

    push @balanceArray, [ ' ', ' ', ' ', ' ', ' ' ];
    push @rowProperties, {};

    push @balanceArray,
      [
        'Minimum Payment:',
        formatMoney( $statement->min_payment() ),
        ' ', ' ', ' '
      ];
    push @rowProperties, {};

    my $tableObj = TableObj->new(
        $pdf, $page, \@balanceArray,
        bottom_margin => kBottomMargin +
          20,    # adding a bit of padding to avoid weirdness
        new_page_y    => kTopMargin - 20,             # ditto
        new_page_func => $newPageFuncRef,
        font          => $font->{Helvetica}{Roman},
        font_size     => $fontSize,
        column_props  => [
            {
                font      => $font->{Helvetica}{Bold},
                font_size => $fontSize,

                #                justify => 'center',
                min_w => 1.25 / in,
                max_w => 1.25 / in,
            },
            {
                font      => $font->{Helvetica}{Roman},
                font_size => $fontSize,
                justify   => 'right',
                min_w     => 1.25 / in,
                max_w     => 1.25 / in,
            },
            {
                font      => $font->{Helvetica}{Roman},
                font_size => $fontSize,

                #                justify => 'right',
                min_w => 1.0 / in,
                pad   => ( 1 / 4 ) / in,
            },
            {
                font      => $font->{Helvetica}{Roman},
                font_size => $fontSize,

                #                justify => 'right',
                min_w => 1.0 / in,
            },
            {
                font      => $font->{Helvetica}{Roman},
                font_size => $fontSize,

                #justify => 'right',
                min_w => 1.0 / in,
            },
        ],
        row_props => \@rowProperties,
    );

    ( $page, $y ) = $tableObj->print( $x, $y );

    $y -= 2;

    my @amountDueArray;
    my @amountDueProperties;

    my $amountDue = formatMoney( $statement->amount_due );
    my $currencyCode = ' (USD)';
    
    # If the main payee is on hold, clear that data out.
    #
    if ($statement->on_hold == 1)
    {
        $amountDue = "ON-HOLD"; 
        $currencyCode = '';  
    }
    
    push @amountDueArray, [' ', ' ', ' '];
    push @amountDueProperties,
    {
        lines =>
        [
            {
                # pen_size => 1,
                # color => 'black',
                start_col => 0,
                end_col => 2,
                top_pad => 2,
                bottom_pad => 0,
            },
        ],
    };

    push @amountDueArray,
      [
        'Amount Payable:',
        $amountDue,
        $currencyCode
      ];
    push @amountDueProperties, { 
        font => $font->{Helvetica}{Bold},
        lines =>
        [
            {
                # pen_size => 1,
                # color => 'black',
                start_col => 0,
                end_col => 2,
                top_pad => 5,
                bottom_pad => 0,
            },
        ],
    };

    my $bigFontSize = 10/pt;

    my $tableObj = TableObj->new(
        $pdf, $page, \@amountDueArray,
        bottom_margin => kBottomMargin +
          20,    # adding a bit of padding to avoid weirdness
        new_page_y    => kTopMargin - 20,             # ditto
        new_page_func => $newPageFuncRef,
        font          => $font->{Helvetica}{Roman},
        font_size     => $bigFontSize,
        column_props  => [
            {
                font      => $font->{Helvetica}{Bold},
                font_size => $bigFontSize,
                min_w     => 1.25 / in,
                max_w     => 1.25 / in,
            },
            {
                font      => $font->{Helvetica}{Roman},
                font_size => $bigFontSize,
                justify   => 'right',
                min_w     => 1.25 / in,
                max_w     => 1.25 / in,
            },
            {
                font      => $font->{Helvetica}{Roman},
                font_size => $bigFontSize,
                justify   => 'left',
                min_w     => 1.0 / in,
            },
        ],
        row_props => \@amountDueProperties,
    );

    ( $page, $y ) = $tableObj->print( $x, $y );

    return ( $x, $y, $page );
}



##########################
# Full Statement Stuff   #
##########################

sub createFullStatementPDF
{
    my ( $statement, $outFilePath ) = @_;

    # We need to tweak the $outFilePath to avoid over-writing the payee version.
    #
    my @pathArray = split("/", $outFilePath);
    @pathArray[$#pathArray] = "FULL_" . @pathArray[$#pathArray];
    $outFilePath = join("/", @pathArray);

    # Instantiate the PDF object.
    #
    my $pdf = PDF::API2->new( -file => $outFilePath );

    # Fetch the fonts that we might want to use.
    # Note that every time we define a font, it will get embedded in the document,
    # so we will grab them all here at the very beginning.
    # !!! Be sure to remove any of these we don't actually need...
    #
    # (These are the 'built-in' fonts that all pdf documents get for free. We can embed fancy
    #  fonts if we want to, but that will make the statement files larger...)
    #
    $font = {
        Helvetica => {
            Bold  => $pdf->corefont( 'Helvetica-Bold', -encoding => 'latin1' ),
            Roman => $pdf->corefont( 'Helvetica',      -encoding => 'latin1' ),
            Italic =>
              $pdf->corefont( 'Helvetica-Oblique', -encoding => 'latin1' ),
        },
        Times => {
            Bold   => $pdf->corefont( 'Times-Bold',   -encoding => 'latin1' ),
            Roman  => $pdf->corefont( 'Times',        -encoding => 'latin1' ),
            Italic => $pdf->corefont( 'Times-Italic', -encoding => 'latin1' ),
        },
    };

    # Declare the 'cursor' coordinates.  As we go, we'll be updating these values so that the
    # next element shows up in the right place.
    #
    my $x = kLeftMargin;
    my $y = kTopMargin;

    # Create the first (blank) page.
    # Each output subroutine will take the current page as a parameter, and will
    # return the page that they ended on.
    #
    my $page = newFullPage($pdf);        

    # Each section of the statement will have its own subroutine.
    #
    ( $x, $y, $page ) = fullHeader( $pdf, $statement, $x, $y, $page );
    ( $x, $y, $page ) = fullSummary( $pdf, $statement, $x, $y, $page );

    # Determine if this is an admin or regular publisher.
    my $publisherItem = RPS::DB::Item::Publisher->Lookup(publisher_id => $statement->publisher_id);

    if (   $publisherItem->is_admin == 1
        || $publisherItem->is_agency == 1 )
    {

        # Loop through all publishers for admins.
        #
        my $publisherList = RPS::DB::Item::MechanicalStatementPublisher->GetSortedByMechanicalStatementID($statement->mechanical_statement_id);
        while (my $subPublisherItem = $publisherList->next())
        {
            ( $x, $y, $page ) = fullDetails( $pdf, $subPublisherItem, $x, $y, $page );
        }
    }
    else
    {

        # Not an admin, so just do this once.
        ( $x, $y, $page ) = fullDetails( $pdf, $statement, $x, $y, $page );
    }

    # If the state of the run is not 'COMMITTED' or 'CLOSED', then we want to add a watermark
    # to the pages so that our users don't mail this statement out.
    #
    my $run = RPS::DB::Item::MechanicalRun->Lookup( mechanical_run_id => $statement->mechanical_run_id );
    if (   RPS::RoyaltyRun::Status::kCommitted != $run->status
        && RPS::RoyaltyRun::Status::kClosed != $run->status )
    {
        addDraftWatermarkFull($pdf);
    }

    # Now add the page numbers, and other 'footer' stuff
    #
    fullFooter($pdf);

    # All done, save and clean up
    #
    $pdf->save();
    $pdf->end();
}


sub fullHeader
{
    my ( $pdf, $statement, $x, $y, $page ) = @_;

    my $text = $page->text();

    # Step 1 - Put the text 'United States Mechanical Royalty Statement' at the top of the page.
    
    $y = printText(
        page        => $page,
        display     => 'United States Mechanical Royalty Statement',      
        y           => $y,        
        font        => $font->{Helvetica}{Bold}, 
        fontSize    => 12 / pt,      
        centered    => 1   
    );          

    # Now print the run label. Which means we need to fetch the run...
    #
    my $run = RPS::DB::Item::MechanicalRun->Lookup(mechanical_run_id => $statement->mechanical_run_id);
    $y -= 9 / pt;
    
    $y = printText(
        page        => $page,
        display     => $run->label,   
        x           => $x,   
        y           => $y,        
        font        => $font->{Helvetica}{Bold}, 
        fontSize    => 9 / pt  
    );  

    # Print the links to download the payee pdf
    # and the text version.
    #
    
    #$y -= 15 / pt;
    
    #$y = printText(
    #    page        => $page,
    #    display     => "Publisher View", 
    #    link        => '/rps/statement?c=pdf_mechanical&MechanicalStatementID=' . $statement-#>MechanicalStatementID(),
    #    x           => $x + 20,   
    #    y           => $y,        
    #    font        => $font->{Helvetica}{Roman}, 
    #    fontSize    => 9 / pt  
    #);       
	
	#EmbedImage::addIconGIF(
	#    page    =>  $page,
	#    pdf     =>  $pdf,
	#    source  =>  '/app/tools/common/production/images/pdficon_small.gif',
	#    link    =>  '/rps/statement?c=pdf_mechanical&MechanicalStatementID=' . $statement-#>MechanicalStatementID(),
	#    width   =>  17,
	#    height  =>  17,
	#    x       =>  $x,
	#    y       =>  $y
	#);    
    
    #$y -= 15 / pt;
    
    #$y = printText(
    #    page        => $page,
    #    display     => "Electronic Format", 
    #    link        => '/rps/statement?c=text_mechanical&MechanicalStatementID=' . $statement-#>MechanicalStatementID(),
    #    x           => $x + 20,   
    #    y           => $y,        
    #    font        => $font->{Helvetica}{Roman}, 
    #    fontSize    => 9 / pt  
    #);     
       
	#EmbedImage::addIconGIF(
	#    page    =>  $page,
	#    pdf     =>  $pdf,
	#    source  =>  '/app/tools/common/production/images/icons/office/Document-(16x16).gif',
	#    link    =>  '/rps/statement?c=text_mechanical&MechanicalStatementID=' . $statement-#>MechanicalStatementID(),
	#    width   =>  16,
	#    height  =>  16,
	#    x       =>  $x,
	#    y       =>  $y
	#);	
	
     
    $y -= 9 / pt;

    my $payee = RPS::DB::Item::Publisher->Lookup(publisher_id => $statement->publisher_id);

    my $cityStateLine = $payee->city;
    if ( $payee->city && $payee->state_province )
    {
        $cityStateLine .= ",";
    }
    $cityStateLine .= $payee->state_province;
    
    if ($payee->postal_code)
    {        
        $cityStateLine .=  " " . $payee->postal_code;   
    }    
    
    my $publisherID = $payee->publisher_id;

    $y = printText(
        page        => $page,
        display     => $payee->publisher_name,   
        link        => '/rps/publisher?PublisherID=' . $publisherID . '&c=show',
        x           => $x,   
        y           => $y,        
        font        => $font->{Helvetica}{Roman}, 
        fontSize    => 9 / pt  
    );   
        
    $y = printText(
        page        => $page,
        display     => $payee->street_address,   
        x           => $x,   
        y           => $y,        
        font        => $font->{Helvetica}{Roman}, 
        fontSize    => 9 / pt  
    );        
    
    $y = printText(
        page        => $page,
        display     => $payee->street_address_2,   
        x           => $x,   
        y           => $y,        
        font        => $font->{Helvetica}{Roman}, 
        fontSize    => 9 / pt  
    );      
    
    $y = printText(
        page        => $page,
        display     => $payee->street_address_3,   
        x           => $x,   
        y           => $y,        
        font        => $font->{Helvetica}{Roman}, 
        fontSize    => 9 / pt  
    );                 
        
    $y = printText(
        page        => $page,
        display     => $cityStateLine,   
        x           => $x,   
        y           => $y,        
        font        => $font->{Helvetica}{Roman}, 
        fontSize    => 9 / pt  
    );           
        
    $y = printText(
        page        => $page,
        display     => $payee->country_code,   
        x           => $x,   
        y           => $y,        
        font        => $font->{Helvetica}{Roman}, 
        fontSize    => 9 / pt  
    );                      

    $y -= 15 / pt;

    return ( $x, $y, $page );
}

sub fullSummary
{
    my ( $pdf, $statement, $x, $y, $page ) = @_;

    ( $x, $y, $page ) = drawBalanceTable( $pdf, $statement, $x, $y, $page, \&newFullPage );

    my $publisher = RPS::DB::Item::Publisher->Lookup(publisher_id => $statement->publisher_id);

    # Determine if this is an admin or regular publisher.
    if ( $publisher->is_admin == 1 || $publisher->is_agency == 1 )
    {
        ( $x, $y, $page ) =
          fullPublisherTable( $pdf, $statement, $x, $y, $page );
    }

    #$y -= 18;

    return ( $x, $y, $page );
}

sub fullPublisherTable
{
    my ( $pdf, $statement, $x, $y, $page ) = @_;
    
    # First, a little room please.
    $y -= 16;
    
    my $fontSize = 7 / pt;

    my $text = $page->text();

    # We'll create a 2-d array that contains the data we want to display.
    #
    my @publisherArray;
    
    # We'll create a similar thing for hyper-links.
    #
    my @linkArray;    

    # This array will keep track of various row properties.
    # We're going to change the font for a couple of rows (such as the header),
    # and do a few more tricks.
    #
    my @rowProperties;

    # Get any publishers
    #
    my $publisherList = RPS::DB::Item::MechanicalStatementPublisher->GetSortedByMechanicalStatementID($statement->mechanical_statement_id);
    if ($publisherList->hasNext())
    {
        
        # The column headers
        #
        push @publisherArray, [ 'Publisher', 'Amount Due' ];
        push @linkArray, [ '', '' ];
        push @rowProperties,
          {
            font  => $font->{Helvetica}{Bold},
            lines => [
                {
                    start_col => 0,
                    end_col   => 1,
                    top_pad   => 4,
                },
            ],
          };        
             
        while (my $publisher = $publisherList->next())
        {
            my $publisherItem = RPS::DB::Item::Publisher->Lookup(publisher_id => $publisher->publisher_id);
            my $name   = $publisherItem->publisher_name();
            my $amount = formatMoney( $publisher->amount_due() );
            
#            if ($statement->on_hold == 1 || $publisher->on_hold == 1)
            if ($publisher->on_hold == 1)
            {
                $amount = 'ON-HOLD';   
            }           
            
            $amount = ' ' unless defined $amount;        

            push @publisherArray, [ $name, $amount ];
            push @linkArray, [ '#PUBLISHER_DEST_'.$publisherItem->publisher_id, ''];            
            push @rowProperties, {};
        }

        my $tableObj = TableObj->new(
            $pdf, $page, \@publisherArray,
            bottom_margin => kBottomMargin +
              20,    # adding a bit of padding to avoid weirdness
            new_page_y    => kTopMargin - 20,             # ditto
            new_page_func => \&newFullPage,
            font          => $font->{Helvetica}{Roman},
            font_size     => $fontSize,
            column_props  => [
                {
                    min_w     => 0.5 / in,
                    font      => $font->{Helvetica}{Roman},
                    font_size => $fontSize,
                },
                {
                    min_w     => 0.5 / in,
                    font      => $font->{Helvetica}{Roman},
                    font_size => $fontSize,
                    justify   => 'right',
                },
            ],
            row_props => \@rowProperties,
            row_links => \@linkArray,
        );
    
        ( $page, $y ) = $tableObj->print( $x, $y );
    }

    return ( $x, $y, $page );
}

sub fullDetails
{
    my ( $pdf, $statement, $x, $y, $page ) = @_;
    my $fontSize = 7 / pt;

    # We need to know if this is an admin statement
    my $whatAmI = ref($statement);

    # start details on a new page
    $page = newFullPage($pdf);

    $y    = kTopMargin - 10;

    # If Admin, print this Publisher's Name at the top.
    if ( 'RPS::DB::Item::MechanicalStatementPublisher' eq $whatAmI )
    {
        my $publisherItem = RPS::DB::Item::Publisher->Lookup(publisher_id => $statement->publisher_id);

        $y = printText(
            page        => $page,
            display     => $publisherItem->publisher_name,      
            y           => $y,        
            font        => $font->{Helvetica}{Bold}, 
            fontSize    => 12 / pt,      
            centered    => 1,
            link        => '/rps/publisher?c=show&PublisherID=' . $publisherItem->publisher_id   
        );                 
        
        # Also, set up the named destination for the internal link
        #
        my $nd = $pdf->named_destination('Dests','#PUBLISHER_DEST_' . $publisherItem->publisher_id);
        $nd->link($page); # link the destination to this page            
    }

    my @rows;
    my @rowProps;
    my @links;

    # Set up the header
    #
    push @rows, [ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' ];
    push @links, [ '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];
    push @rowProps, {
        font  => $font->{Helvetica}{Bold},
        lines => [
            {
                start_col => 0,
                end_col   => 20,
                top_pad   => 4,

                # bottom_pad => 2,
            },
        ],
    };
    push @rows,
      [
        '',
        '',
        '',
        '',
        'Product',
        '',
        '',
        'Base',
        '% of',
        '',
        'Net',
        'Gross',
        '% of',
        'Free',
        '',
        '',
        'Liquid-',
        '',
        'Carry-',
        'Net',
        'Amount'
      ];
    push @links, [ '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];
    push @rowProps, {
        font   => $font->{Helvetica}{Bold},
        repeatRows => 1,
    };    
    push @rows,
      [
        '',
        'Track Title',
        'Album Title',
        'UPC',
        'Config',
        'Region',
        'Rate Period',
        'Rate',
        'Rate',
        'Share',
        'Rate',
        'Units',
        'Sales',
        'Goods',
        'Misc',
        'Reserves',
        'ations',
        'Returns',
        'over',
        'Units',
        'Due'
      ];
    push @links, [ '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];
    push @rowProps, {
        font   => $font->{Helvetica}{Bold},
        repeatRows => 1,
        lines  => [
            {
                start_col => 0,
                end_col   => 20,
                top_pad   => 4,

                # bottom_pad => 2,
            },
        ],
    };

    # Add the track details.
    #
    my $statementTrackCollection;
    if ('RPS::DB::Item::MechanicalStatementPublisher' eq $whatAmI)
    {
        $statementTrackCollection = RPS::DB::Item::MechanicalStatementTrack->GetSortedByMechanicalStatementIDPublisherID($statement->mechanical_statement_id, $statement->publisher_id);
    }
    else
    {
        $statementTrackCollection = RPS::DB::Item::MechanicalStatementTrack->GetSortedByMechanicalStatementID($statement->mechanical_statement_id);
    }
    
	while ($statementTrackCollection->hasNext())
	{
		my $statementTrack = $statementTrackCollection->next(); 
        fullTrackDetails( $statementTrack, $statement, \@rows, \@rowProps, \@links );
    }

    # Force the columns to be fixed width.
    #
    my $colProps = fullDetailColProps();
    
    my $tableObj = TableObj->new(
        $pdf, 
        $page, 
        \@rows,
        bottom_margin => kBottomMargin + 20,   
        new_page_y    => kTopMargin - 20,       
        new_page_func => \&newFullPage,
        font          => $font->{Helvetica}{Roman},
        font_size     => $fontSize,
        column_props  => $colProps,
        row_props     => \@rowProps,
        row_links     => \@links,
    );

    ( $page, $y ) = $tableObj->print( $x, $y );

    # Last, print the grand total
    #

    my @totalRows;
    my @totalRowProps;

    if ( 'RPS::DB::Item::MechanicalStatementPublisher' eq $whatAmI )
    {
        my $previousBalance = $statement->previous_balance();
        
        # Add the transactions in.
        #		
        my $transactionCollection = RPS::DB::Item::MechanicalStatementPublisherTransaction->GetByMechanicalStatementAndPublisherID($statement->mechanical_statement_id, $statement->publisher_id);
        
        my $transactionCount = RPS::DB::Item::MechanicalStatementPublisherTransaction->GetCountByMechanicalStatementAndPublisherID($statement->mechanical_statement_id, $statement->publisher_id);  
        
        if ($previousBalance != 0 || $transactionCount > 0)
        { 
            push @totalRows,  [ 'Publisher Subtotal:', formatMoney($statement->subtotal()) ];
        
            if ($previousBalance != 0)
            {
                push @totalRows,  [ 'Previous Balance:', formatMoney($statement->previous_balance()) ]; 
                push @totalRowProps, {};
            } 
            
        	while ($transactionCollection->hasNext())
        	{
        		my $transaction = $transactionCollection->next();   
                my $type;
                if ( $transaction->type_code == 2 )
                {
                    $type = 'Adjustment';
                }
                elsif ( $transaction->type_code == 3 )
                {
                    $type = 'Advance';
                }
                elsif ( $transaction->type_code == 4 )
                {
                    $type = 'Payment';
                }           
                push @totalRows,  [ "$type:", formatMoney($transaction->amount) ];
                push @totalRowProps, {};
            }
            
            push @totalRows,  [ 'Ending Balance:', formatMoney($statement->statement_total) ]; 
            # Note that this will actually go above the ending balance, since we did't add an element to the 
            # array for the subtotal.
            #
            push @totalRowProps, {              
                lines  => [
                    {
                        start_col  => 1,
                        end_col    => 1,    
                        top_pad    => 2,
                        bottom_pad => -1, 
                    },
                ],
            };   
            
            push @totalRows, [];
            push @totalRowProps, { font   => $font->{Helvetica}{Bold} };       
        }

        my $amountDue;
        my $parentStatement = RPS::DB::Item::MechanicalStatement->Lookup(mechanical_statement_id => $statement->mechanical_statement_id);
#        if ($parentStatement->on_hold == 1 || $statement->on_hold == 1)
        if ($statement->on_hold == 1)
        {
            $amountDue = "ON-HOLD";   
        }
        else
        {
            $amountDue = formatMoney($statement->amount_due)   
        }
             
        push @totalRows,  [ 'Publisher Amount Due:', $amountDue ];       
        push @totalRowProps, { font => $font->{Helvetica}{Bold} };
        
        # And now an extra one to make up for the subtotal row not having one.
        #
        push @totalRowProps, { font => $font->{Helvetica}{Bold} };

    }
    else
    {
        push @totalRows,  [ 'Total:', formatMoney($statement->subtotal) ];
        push @totalRowProps, { font => $font->{Helvetica}{Bold} };
    }

    $y -= 5 / pt;

    my $table = TableObj->new(
        $pdf, $page, \@totalRows,
        bottom_margin => kBottomMargin + 20, 
        new_page_y    => kTopMargin - 10,
        new_page_func => \&newFullPage,
        font          => $font->{Helvetica}{Roman},
        font_size     => $fontSize,
        column_props  => [
            {
                justify => 'right',
                min_w   => 9.39 / in,
                max_w   => 9.39 / in,
                pad     => 0,
                font          => $font->{Helvetica}{Bold},
            },
            {
                justify => 'right',
                min_w   => .61 / in,
                max_w   => .61 / in,
                pad     => 0,
            },
        ],
        row_props     => \@totalRowProps,
    );
    ( $page, $y ) = $table->print( $x, $y );

    return ( $x, $y, $page );
}

sub fullDetailColProps
{
    return [
        {
            
            # license icon
            min_w => .15 / in,
            max_w => .15 / in,
            pad   => 0,
            image => "gif",
        },    
        {
            
            # track title
            min_w => 0.9 / in,
            max_w => 0.9 / in,
            pad   => 0,
        },
        {

            # album title
            min_w => 0.75 / in,
            max_w => 0.75 / in,
            pad   => 0,
        },
        {

            # upc
            min_w => 0.7 / in,
            max_w => 0.7 / in,
            pad   => 0,
        },
        {

            # product (config)
            min_w => 0.41 / in,
            max_w => 0.41 / in,
            pad   => 0,
        },
        {

            # region
            min_w => 0.36 / in,
            max_w => 0.36 / in,
            pad   => 0,
        },
        {

            # rate period
            min_w => 0.6 / in,
            max_w => 0.6 / in,
            pad   => 0,
        },
        {

            # base rate
            min_w => 0.35 / in,
            max_w => 0.35 / in,
            pad   => 0,
        },        
        {

            # % of rate
            min_w => 0.5 / in,
            max_w => 0.5 / in,
            pad   => 0,
        },        
        {

            # share
            min_w => 0.45 / in,
            max_w => 0.45 / in,
            pad   => 0,
        },
        {

            # net rate
            min_w => 0.4 / in,
            max_w => 0.4 / in,
            pad   => 0,
        },
        {

            # gross units
            justify => 'right',
            min_w => 0.5 / in,
            max_w => 0.5 / in,
            pad   => 0,
        },       
        {

            # % of sales 
            justify => 'right',
            min_w => 0.42 / in,
            max_w => 0.42 / in,
            pad   => 0,
        }, 
        {

            # free (goods)
            justify => 'right',
            min_w => 0.35 / in,
            max_w => 0.35 / in,
            pad   => 0,
        },                
        {

            # misc
            justify => 'right',
            min_w => 0.35 / in,
            max_w => 0.35 / in,
            pad   => 0,
        },        
        {

            # reserves
            justify => 'right',
            min_w => 0.5 / in,
            max_w => 0.5 / in,
            pad   => 0,
        },     
        {

            # liquidations
            justify => 'right',
            min_w => 0.4 / in,
            max_w => 0.4 / in,
            pad   => 0,
        },    
        {

            # returns
            justify => 'right',
            min_w => 0.45 / in,
            max_w => 0.45 / in,
            pad   => 0,
        },    
        {

            # carryover
            justify => 'right',
            min_w => 0.4 / in,
            max_w => 0.4 / in,
            pad   => 0,
        },                   
        {

            # net units
            justify => 'right',
            min_w   => 0.45 / in,
            max_w   => 0.45 / in,
            pad     => 0,
            do_not_truncate => 1,
        },
        {

            # amount due
            justify => 'right',
            min_w   => 0.61 / in,
            max_w   => 0.61 / in,
            pad     => 0,
        }, 
    ];
}    

sub fullTrackDetails
{
    my ( $track, $statement, $rows, $rowDetails, $links ) = @_;

    fullCrossedLicenseDetails( $track, $statement, $rows, $rowDetails, $links );
    fullLicenseDetails( $track, $statement, $rows, $rowDetails, $links );
}

sub fullCrossedLicenseDetails
{
    my ( $statementTrack, $statement, $rows, $rowProps, $links ) = @_;
    
    my $album = RPS::DB::Item::Album->Lookup(album_id => $statementTrack->album_id);
    my $track = RPS::DB::Item::Track->Lookup(track_id => $statementTrack->track_id);    

    # Go through the entire (crossed) license list
    #  
    my $licenseCollection = RPS::DB::Item::MechanicalStatementLicense->GetByMechanicalStatementIDTrackIDPublisherID($statement->mechanical_statement_id, $statementTrack->track_id, $statement->publisher_id);

    my $licenseCount = 0;

	while ($licenseCollection->hasNext())
	{
		my $license = $licenseCollection->next();
		my $statementTrackLicense = RPS::DB::Item::TrackLicense->Lookup(track_license_id => $license->track_license_id);

        next if (! $license->crossed);    
        
        $licenseCount++;

        my $incomeItemCollection = RPS::DB::Item::MechanicalStatementItem->GetByStatementAndTrackLicense($statement->mechanical_statement_id, $license->track_license_id);
        
        my $itemCount = 0;
        
    	while ($incomeItemCollection->hasNext())
    	{
    		my $incomeItem = $incomeItemCollection->next();        
			$itemCount++;

			# We need to grab the album title from the product.
			# If it's a track product, we'll need to grab it from the parent product.
			my $product = RPS::DB::Item::Product->Lookup( product_id => $incomeItem->product_id );
			my $albumTitle = _getAlbumTitle( $product, $album->title );
		                
			# We have to check the license product type id to see 
			# if we're dealing with a ringtone.
			#
			my $productTypeID = _checkForRingtone( $statementTrackLicense, $incomeItem );				                

            my $statRateIDToUse = $incomeItem->applied_stat_rate_id;
            if (! $statRateIDToUse)
            {
                $statRateIDToUse = $incomeItem->sale_stat_rate_id;
            }
            my $ratePeriod = _getRatePeriod($statRateIDToUse);				                
		
            push @$rows,
              [
                '/app/tools/common/production/images/icons/mini/micro_briefcase.gif',
                $track->title,
                $albumTitle,
                $incomeItem->upc,
                productCodeToName( $productTypeID ),
                regionIDToName( $license->region_id ),
                $ratePeriod,
                formatNumber( $incomeItem->base_rate ),
                formatPercent( $statementTrackLicense->rate_percentage ),
                formatPercent( $statementTrackLicense->share ),
                formatNumber( $incomeItem->net_rate ),
                formatNumber( $incomeItem->sales),
                formatPercent( $statementTrackLicense->percentage_of_sales ),
                formatPercent( $statementTrackLicense->free_goods ),
                formatPercent( $statementTrackLicense->misc_deduction ),
                formatNumber( -1 * $incomeItem->reserved ),
                formatNumber( $incomeItem->liquidated ),
                formatNumber( -1 * $incomeItem->returns ),
                formatNumber( $incomeItem->carryover ),
                formatNumber( $incomeItem->net_units ),
                formatMoney( $incomeItem->amount_paid ),
              ];
              
            my $productLinkID = _getProductIDforLink( $product );                 
              
            push @$links, [ '/rps/license?c=show&TrackLicenseID=' . $license->track_license_id, '/rps/track?c=show&TrackID=' . $track->track_id, '/rps/product?c=show&ProductID=' . $productLinkID, '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];
	
	        if ( ($itemCount == 1) && ($licenseCount != 1) ) 
		    {
	            push @$rowProps, {
            		pad => 8,	
            	};			
            }
            else
            {							
    		    push @$rowProps, {};
            }
            
            $itemCount++;
        }

        if ($itemCount == 0)
        {
    
            # Even if there are no income items,
            # we still want to display the track info.
            push @$rows,
              [
                '/app/tools/common/production/images/icons/mini/micro_briefcase.gif',
                , $track->title, $album->title(), ' ', ' ',
                regionIDToName( $license->region_id ),
                ' ', ' ', ' ', ' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ', ' ', ' ', ' ',
              ];
            push @$links, [ '/rps/license?c=show&TrackLicenseID=' . $license->track_license_id, '/rps/track?c=show&TrackID=' . $track->track_id, '/rps/catalog?c=show&AlbumID=' . $track->album_id, '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];
#            push @$links, [ '', '/rps/track?c=show&TrackID=' . $track->track_id, '/rps/catalog?c=show&AlbumID=' . $track->album_id, '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];
    
            push @$rowProps, {
            		pad => 8,	
            };
    
        }


        # Add the controlled comp adjustments
        #
        
        my $adjustmentCollection = RPS::DB::Item::MechanicalStatementAdjustmentItem->GetByMechanicalStatementIDTrackLicenseID($statement->mechanical_statement_id, $license->track_license_id);

    	while ($adjustmentCollection->hasNext())
    	{
    		my $adjustment = $adjustmentCollection->next();            

            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                'Controlled Comp Adjustment:',
                formatMoney( $adjustment->amount )
              ];

            push @$links, [ '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];
        
            push @$rowProps, {};
        
        }
		       
		        
        #  Now we want to display the subtotal, previous balance, transactions, etc. for this license
        #
        
    	# We want a little line above the subtotal.
        #
        my $numRows = scalar(@$rowProps);
        my $lastRowPropHashref = $$rowProps[ ( $numRows - 1 ) ];
        $lastRowPropHashref->{lines} = [
            {
                start_col => 20,
                end_col   => 20,
                top_pad   => 2,
    
                # bottom_pad => 2,
            },
        ];
		        
		
        # Add the license summary stuff.
        #
        # We are going to change a lot of things if there is no previous balance
        # OR license transactions.  So let's check for them now.     
        my $previousBalance         = $license->previous_advance_balance;

        push @$rows,
          [
            ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
            'Current Period License Subtotal:',
            formatMoney( $license->subtotal )
          ];
          
        push @$links, [ '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];

        push @$rowProps, {
						pad => -1,
        };

		
        # Add the transactions in.
        #		
        my $transactionCollection = RPS::DB::Item::MechanicalStatementLicenseTransaction->GetByMechanicalStatementLicenseID($license->mechanical_statement_license_id);
        
        my $transactionCount = 0;		

    	while ($transactionCollection->hasNext())
    	{
    		my $licenseTransaction = $transactionCollection->next();        
			$transactionCount++;
		
            my $transactionType;
            if ( $licenseTransaction->type_code == 3 )
            {
                $transactionType = 'Advance:';
            }
            else
            {
                $transactionType = 'Adjustment:';
            }

            my $memo = ' ';
            if ( $licenseTransaction->memo() )
            {
                $memo = '(' . $licenseTransaction->memo() . ') ';
            }
		
            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                $memo . $transactionType,
                formatMoney( $licenseTransaction->amount )
              ];
            
            push @$links, [ '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];  
              
            push @$rowProps, {};
        }
        
        if ($transactionCount > 0)
        {
		
            # We want a little line under the last transaction.
            #
            my $numRows = scalar(@$rowProps);
            my $lastRowPropHashref = $$rowProps[ ( $numRows - 1 ) ];
            $lastRowPropHashref->{lines} = [
                {
                    start_col => 20,
                    end_col   => 20,
                    top_pad   => 2,

                    # bottom_pad => 2,
                },
            ];
        }
		
        if ( ( $previousBalance != 0 ) || ($license->advance_balance != 0) )
        {
            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                'Previous License Balance:',
                formatMoney($previousBalance)
              ];
              
            push @$links, [ '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];

            push @$rowProps, {
                lines => [
                    {
                        start_col => 20,
                        end_col   => 20,
                        top_pad   => 2,

                        # bottom_pad => 2,
                    },
                ],
            };

            my $licenseBalance = $license->advance_balance;

            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                'License Balance Forward:',
                formatMoney($licenseBalance)
              ];
              
            push @$links, [ '','', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ]; 
             
            push @$rowProps, {
								pad => -1,		            	
                lines => [
                    {
                        start_col => 20,
                        end_col   => 20,
                        top_pad   => 2,

                        # bottom_pad => 2,
                    },
                ],
            };
        }
		
        # And really, truly finally, the adjusted subtotal if need be.
        #
        if ( ( $transactionCount != 0 ) || ( $previousBalance != 0 ) || ($license->subtotal != $license->adjusted_subtotal ))
        {
            my $licenseBalance = $license->adjusted_subtotal;

            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                'License Adjusted Subtotal:',
                formatMoney($licenseBalance)
              ];
              
            push @$links, [ '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];  
              
            push @$rowProps, {
            		pad => -1,	
            };
        }	
		        
        $licenseCount++;	        
    
	}

    if ($licenseCount > 0)
    {

        # Add the license summary stuff.
        #
        # We are going to change a lot of things if there is no previous balance
        # OR license transactions.  So let's check for them now.
            
        my $previousBalance = $statementTrack->crossed_previous_advance_balance;
    
        push @$rows,
          [
            ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
            'Current Period Crossed Subtotal:',
            formatMoney( $statementTrack->crossed_subtotal )
          ];
              
        push @$links, [ '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];  
          
        push @$rowProps, {
    					pad => 8,
        };         
    
    
        # Add the transactions in.
        #    
        my $crossedTransactionCollection = RPS::DB::Item::MechanicalStatementCrossedLicenseTransaction->GetByMechanicalStatementIDPublisherIDTrackID($statement->mechanical_statement_id, $statement->publisher_id, $statementTrack->track_id);
        
        my $crossedTransactionCount = 0;		
    
    	while ($crossedTransactionCollection->hasNext())
    	{
    		my $crossedTransaction = $crossedTransactionCollection->next();        
    		$crossedTransactionCount++;   
    
            my $transactionType;
            if ( $crossedTransaction->type_code == 3 )
            {
                $transactionType = 'Advance:';
            }
            else
            {
                $transactionType = 'Adjustment:';
            }
    
            my $memo = ' ';
            if ( $crossedTransaction->memo )
            {
                $memo = '(' . $crossedTransaction->memo . ') ';
            }
    
            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                $memo . $transactionType,
                formatMoney( $crossedTransaction->amount )
              ];
              
            push @$links, [ '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];  
              
            push @$rowProps, {};
        }
    
        # We want a little line under the last transaction.
        #
        if ($crossedTransactionCount > 0)
        {
            my $numRows = scalar(@$rowProps);
            my $lastRowPropHashref = $$rowProps[ ( $numRows - 1 ) ];
            $lastRowPropHashref->{lines} = [
                {
                    start_col => 20,
                    end_col   => 20,
                    top_pad   => 2,
                },
            ];
        }
    
    
        if ( ( $previousBalance != 0 ) || ($statementTrack->crossed_advance_balance != 0) )
        {
            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                'Previous Crossed Balance:',
                formatMoney($previousBalance)
              ];
              
            push @$links, [ '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];
    
            push @$rowProps, {
                lines => [
                    {
                        start_col => 20,
                        end_col   => 20,
                        top_pad   => 2,
                    },
                ],
            };
    
            my $licenseBalance = $statementTrack->crossed_advance_balance;
    
            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                'Crossed Balance Forward:',
                formatMoney($licenseBalance)
              ];
              
            push @$links, [ '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];
              
            push @$rowProps, {
    						pad => -1,
            };
    
        }
    
        # And really, truly finally, the adjusted subtotal if need be.
        #
        if ( ( $crossedTransactionCount != 0 ) || ( $previousBalance != 0 ) || ($statementTrack->crossed_subtotal != $statementTrack->crossed_adjusted_subtotal ))
        {
            my $licenseBalance = $statementTrack->crossed_adjusted_subtotal;
    
            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                'Crossed Adjusted Subtotal:',
                formatMoney($licenseBalance)
              ];
             
            push @$links, [ '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];  
              
            push @$rowProps, {};
        }
    
    
        # We want the last item to have a line underneath it.
        pop(@$rowProps);        
        push @$rowProps, {
            pad => 8,
            lines => [
                {
                    start_col => 0,
                    end_col   => 20,
                    top_pad   => 2,
                },
            ],
        };
    }        
        
}

sub fullLicenseDetails
{
    my ( $statementTrack, $statement, $rows, $rowProps, $links ) = @_;

    my $album = RPS::DB::Item::Album->Lookup(album_id => $statementTrack->album_id);
    my $track = RPS::DB::Item::Track->Lookup(track_id => $statementTrack->track_id);

    # Go through the entire (uncrossed) license list
    #
    my $licenseCollection = RPS::DB::Item::MechanicalStatementLicense->GetByMechanicalStatementIDTrackIDPublisherID($statement->mechanical_statement_id, $statementTrack->track_id, $statement->publisher_id);

    my $licenseCount = 0;

	while ($licenseCollection->hasNext())
	{
		my $license = $licenseCollection->next();
		my $statementTrackLicense = RPS::DB::Item::TrackLicense->Lookup(track_license_id => $license->track_license_id);

        next if ($license->crossed);    
        
        $licenseCount++;

        my $incomeItemCollection = RPS::DB::Item::MechanicalStatementItem->GetByStatementAndTrackLicense($statement->mechanical_statement_id, $license->track_license_id);

        my $lastRow;
        my $lastCellArray;
        my $itemCount = 0;
        
    	while ($incomeItemCollection->hasNext())
    	{
    		my $incomeItem = $incomeItemCollection->next();        
			$itemCount++;

			# We need to grab the album title from the product.
			# If it's a track product, we'll need to grab it from the parent product.
			my $product = RPS::DB::Item::Product->Lookup( product_id => $incomeItem->product_id );
			my $albumTitle = _getAlbumTitle( $product, $album->title );
		                
			# We have to check the license product type id to see 
			# if we're dealing with a ringtone.
			#
			my $productTypeID = _checkForRingtone( $statementTrackLicense, $incomeItem );				                

            my $statRateIDToUse = $incomeItem->applied_stat_rate_id;
            if (! $statRateIDToUse)
            {
                $statRateIDToUse = $incomeItem->sale_stat_rate_id;
            }
            my $ratePeriod = _getRatePeriod($statRateIDToUse);
            
            push @$rows,
              [
                    '/app/tools/common/production/images/icons/mini/micro_briefcase.gif',
                    $track->title,
                    $albumTitle,
                    $incomeItem->upc,
                    productCodeToName( $productTypeID ),
                    regionIDToName( $license->region_id ),
                    $ratePeriod,
                    formatNumber( $incomeItem->base_rate ),
                    formatPercent( $statementTrackLicense->rate_percentage ),
                    formatPercent( $statementTrackLicense->share ),
                    formatNumber( $incomeItem->net_rate ),
                    formatNumber( $incomeItem->sales),
                    formatPercent( $statementTrackLicense->percentage_of_sales ),
                    formatPercent( $statementTrackLicense->free_goods ),
                    formatPercent( $statementTrackLicense->misc_deduction ),
                    formatNumber( -1 * $incomeItem->reserved ),
                    formatNumber( $incomeItem->liquidated ),
                    formatNumber( -1 * $incomeItem->returns ),
                    formatNumber( $incomeItem->carryover ),
                    formatNumber( $incomeItem->net_units ),
                    formatMoney( $incomeItem->amount_paid ),
              ];

            my $productLinkID = _getProductIDforLink( $product );

            push @$links, [ '/rps/license?c=show&TrackLicenseID=' . $license->track_license_id, '/rps/track?c=show&TrackID=' . $track->track_id, '/rps/product?c=show&ProductID=' . $productLinkID, '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];

            push @$rowProps, {};
        }

        if ($itemCount == 0)
        {

            # Even if there are no income items,
            # we still want to display the track info.
            push @$rows,
              [
                '/app/tools/common/production/images/icons/mini/micro_briefcase.gif',
                , $track->title, $album->title, ' ', ' ',
                regionIDToName( $license->region_id ),
                ' ', ' ', ' ', ' ', ' ',' ', ' ', ' ', ' ', ' ',' ', ' ', ' ', ' ', ' ',
              ];
              
            push @$links, [ '/rps/license?c=show&TrackLicenseID=' . $license->track_license_id, '/rps/track?c=show&TrackID=' . $track->track_id, '/rps/catalog?c=show&AlbumID=' . $track->album_id, '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];
#            push @$links, [ '', '/rps/track?c=show&TrackID=' . $track->track_id, '/rps/catalog?c=show&AlbumID=' . $track->album_id, '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];

            push @$rowProps, {};

        }

        # Add the controlled comp adjustments
        #
        
        my $adjustmentCollection = RPS::DB::Item::MechanicalStatementAdjustmentItem->GetByMechanicalStatementIDTrackLicenseID($statement->mechanical_statement_id, $license->track_license_id);

    	while ($adjustmentCollection->hasNext())
    	{
    		my $adjustment = $adjustmentCollection->next();            

            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                'Controlled Comp Adjustment:',
                formatMoney( $adjustment->amount )
              ];
           
            push @$links, [ '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];
        
            push @$rowProps, {};
        
        }


        # We want a little line above the subtotal.
        #
        my $numRows = scalar(@$rowProps);
        my $lastRowPropHashref = $$rowProps[ ( $numRows - 1 ) ];
        $lastRowPropHashref->{lines} = [
            {
                start_col => 20,
                end_col   => 20,
                top_pad   => 2,

                # bottom_pad => 2,
            },
        ];

        # Add the license summary stuff.
        #
        # We are going to change a lot of things if there is no previous balance
        # OR license transactions.  So let's check for them now.     
        
        my $previousBalance         = $license->previous_advance_balance;

        push @$rows,
          [
            ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
            'Current Period License Subtotal:',
            formatMoney( $license->subtotal )
          ];
          
        push @$links, [ '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];  

        push @$rowProps, {
						pad => -1,
        };


        # Add the transactions in.
        #		
        my $transactionCollection = RPS::DB::Item::MechanicalStatementLicenseTransaction->GetByMechanicalStatementLicenseID($license->mechanical_statement_license_id);
        
        my $transactionCount = 0;		

    	while ($transactionCollection->hasNext())
    	{
    		my $transaction = $transactionCollection->next();        
			$transactionCount++;

            my $transactionType;
            if ( $transaction->type_code == 3 )
            {
                $transactionType = 'Advance:';
            }
            else
            {
                $transactionType = 'Adjustment:';
            }

            my $memo = ' ';
            if ( $transaction->memo )
            {
                $memo = '(' . $transaction->memo . ') ';
            }

            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                $memo . $transactionType,
                formatMoney( $transaction->amount )
              ];
              
            push @$links, [ '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];  
              
            push @$rowProps, {};
        }
        
        if ($transactionCount > 0)
        {
            # We want a little line under the last transaction.
            #
            my $numRows = scalar(@$rowProps);
            my $lastRowPropHashref = $$rowProps[ ( $numRows - 1 ) ];
            $lastRowPropHashref->{lines} = [
                {
                    start_col => 20,
                    end_col   => 20,
                    top_pad   => 2,
                },
            ];
        }

        if ( ( $previousBalance != 0 ) || ($license->advance_balance != 0) )
        {
            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                'Previous License Balance:',
                formatMoney($previousBalance)
              ];

            push @$links, [ '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];

            push @$rowProps, {
                lines => [
                    {
                        start_col => 20,
                        end_col   => 20,
                        top_pad   => 2,
                    },
                ],
            };

            my $licenseBalance = $license->advance_balance;

            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                'License Balance Forward:',
                formatMoney($licenseBalance)
              ];
            
            push @$links, [ '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];  
              
            push @$rowProps, {
								pad => -1,		            	
                lines => [
                    {
                        start_col => 20,
                        end_col   => 20,
                        top_pad   => 2,
                    },
                ],
            };
        }

        # And really, truly finally, the adjusted subtotal if need be.
        #
        if ( ( $transactionCount != 0 ) || ( $previousBalance != 0 ) || ($license->subtotal != $license->adjusted_subtotal ))
        {
            my $licenseBalance = $license->adjusted_subtotal;

            push @$rows,
              [
                ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
                'License Adjusted Subtotal:',
                formatMoney($licenseBalance)
              ];
            
            push @$links, [ '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' ];  
              
            push @$rowProps, {}; 
        } 

        # We want the last item to have a line underneath it.
        pop(@$rowProps);        
        push @$rowProps, {
            pad => -1,
            lines => [
                {
                    start_col => 0,
                    end_col   => 20,
                    top_pad   => 2,
                },
            ],
        };   
             
    }
}

sub fullFooter
{
    my ($pdf) = @_;

    my $pageCount = 1;
    my $numPages  = scalar @gFullPages;
    foreach my $page (@gFullPages)
    {
        my $text = $page->text;
        
        printText(
            page        => $page,
            display     => "$pageCount of $numPages",      
            y           => kBottomMargin,        
            font        => $font->{Helvetica}{Roman}, 
            fontSize    => 12 / pt,      
            centered    => 1   
        );            
        
        $pageCount++;
    }
}

sub newFullPage
{
    my ($pdf) = @_;

    my $page = $pdf->page;

    # the mediabox is the size of the paper.
    #
    $page->mediabox( kPageWidth, kPageHeight );

# the cropbox defines the margins, essentially.
# the args are the coordinates for the left, bottom, right, and top (in that order)
#

# !!! Rather than set the cropbox right to the margins, I am going to make it larger.
# !!! Basically, I want to have this thing render in the viewer with the appearance of having
# !!! margins.
#
#    $page->cropbox(kLeftMargin, kBottomMargin, kRightMargin, kTopMargin);
    $page->cropbox( 5, 5, kPageWidth - 5, kPageHeight - 5 );

# Not currently declaring a 'bleedbox' or an 'artbox'.  Check out the tutorial if you want to
# know what those are... the url for that is at the top of this file.
#
    push @gFullPages, $page;

    return $page;
}






# This just prints a line of text, left justified to the left margin 
# unless "centered" is passed, in which case it centers the text.
#
sub printText
{
    my %args = @_;
    
	my $page        = $args{page};
    my $display     = $args{display};
    my $link        = $args{link};   
    my $x           = $args{x};
    my $y           = $args{y};
    my $font        = $args{font};       
    my $fontSize    = $args{fontSize}; 
    my $color       = $args{color};  
    my $centered    = $args{centered};      

    $color = 'black' unless $color;
    
    if ($link)
    {
        # We want to do something to make links stand out.
        # For now, just make them blue.
        $color = 'blue';   
    }
    
    my $text = $page->text();

    $text->font( $font, $fontSize );
    $text->fillcolor($color);    

    my $top = $y;
    my $left;
    my $right;

    my @strings = split( /\n/, $display );
    foreach my $string (@strings)
    {

        # Remove any carriage returns that are left over from the new line splitting above.
        $string =~ s/\r//g;

        # Calculate how wide this string will be.
        #
        my $stringWidth = $text->advancewidth($string);
        
        if ($centered)
        {
            $x = ( ( kRightMargin - kLeftMargin ) / 2 ) + kLeftMargin - ( $stringWidth / 2 );        
        }
        $left = $x;
        
        if (!$right || $right < ($stringWidth + $left))
        {
           $right = $stringWidth + $left;
        }

        $y -= $fontSize;

        $text->translate( $x, $y );
        $text->text($string);

        # Move the cursor down the page.
        # add a little bitty bit of padding
        $y -= 1;
    }
    
    my $bottom = $y;

    if ($link)
    {
        my $clientNameClean = Common::Client::Current()->WebAlias();
        $clientNameClean = Common::Client::Current()->ClientNameClean() unless $clientNameClean;
        my $url = "https://" . $clientNameClean . ".royaltyshare.com" . $link;
        # And now we'll create the actual link    
        my $annot = $page->annotation();
        $annot->url($url, -rect => [$left, $bottom, $right, $top]);        
    }

    return $y;
}

sub formatNumber
{
    my ($value) = @_;

    $value = Formats::formatNumber($value);

    return $value;
}

sub formatMoney
{
    my ($value) = @_;

    # Use our own rounding algorithm.
    #
    my $rVal = Common::RSMath::round($value, 2);
		
    $rVal = Common::Client::Current()->Locale()->formatMoney($rVal, "USD");

    return $rVal;  
  
    #my ($value) = @_;

    #$value = Formats::formatMoney($value);

    #return $value;
}

sub formatPercent
{
    my ($value) = @_;

    $value = Formats::formatPercent($value);

    return $value;
}


sub _checkForRingtone 
{
    my ($license, $incomeItem) = @_;
    
    my $productTypeID;
    
    if ($license->product_type_id == RPS::DB::Item::Product::kProductTypeRingtone)
    {
        $productTypeID = RPS::DB::Item::Product::kProductTypeRingtone;
    }
    else 
    {
        my $product = RPS::DB::Item::Product->Lookup(product_id => $incomeItem->product_id);
        $productTypeID = $product->product_type_id;
    }	
    
    return $productTypeID;	       
}

my %parentTitles;
sub _getAlbumTitle 
{
    my ($product, $albumTitle) = @_;
    
    my $title;
    
    # If this is a track product, we need to get the title from the parent.
    if ($product->product_type_id == RPS::DB::Item::Product::kProductTypeDigitalTrack && $product->parent_product_id)
    {
        if (!$parentTitles{$product->parent_product_id}) 
        {
            my $parentProduct = RPS::DB::Item::Product->Lookup(product_id => $product->parent_product_id);
            $parentTitles{$product->parent_product_id} = $parentProduct->title;
        }
        $title = $parentTitles{$product->parent_product_id};
    }
    else 
    {
        $title = $product->title;
    }	
    
    # Just in case we don't find a product title, let's fall back to the album title.
    if (!$title) 
    {
        $title = $albumTitle;
    }
    
    return $title;	       
}


sub _getProductIDforLink 
{
    my ($product) = @_;
    
    my $productID;
    
    # If this is a track product, we need to link to the parent product.
    if ($product->product_type_id == RPS::DB::Item::Product::kProductTypeDigitalTrack && $product->parent_product_id)
    {
        $productID = $product->parent_product_id;
    }
    else 
    {
        $productID = $product->product_id;
    }	
    
    return $productID;	       
}


my $gRatePeriodMap;
sub _getRatePeriod
{
    my ($id) = @_;

    return "" unless $id;

    if (! $gRatePeriodMap)
    {
        $gRatePeriodMap = RPS::DB::Item::StatRate->GetRatePeriodMap();
    }

    return $gRatePeriodMap->{$id};
}
# These functions map ids to their text representations.
# Basically, the first time we ask for a particular id->string mapping, we
# will query the correct database, and build a hash.  Subsequent calls just
# hit the hash.
#
# Because these tables are so similar, I abstracted the guts into the _genericMapAccessor
# method (to save myself some typing).
#
my %idMaps;

sub _genericMapAccessor
{
    my ( $collectionAccessor, $idName, $id ) = @_;

    if ( !defined $idMaps{$collectionAccessor} )
    {
        $idMaps{$collectionAccessor} = {};

       # This is a very naughty thing to do, but it works great in this context.
       #
       #        no strict 'refs';
       #        my $c = &$collectionAccessor();
       #        use strict 'refs';
        my $c = $collectionAccessor->GetAll();

        while ( my $item = $c->next() )
        {
            if ( $idName ne 'product_type_id' )
            {
                $idMaps{$collectionAccessor}{ $item->$idName() } = $item->name;
            }
            else
            {
                $idMaps{$collectionAccessor}{ $item->$idName() } =
                  $item->description;
            }
        }
    }

    return $idMaps{$collectionAccessor}{$id};
}

sub incomeSourceIDToName
{
    my ($id) = @_;

    return _genericMapAccessor( 'RPS::DB::Item::IncomeSource',
        'income_source_id', $id );
}

sub regionIDToName
{
    my ($id) = @_;

    # we don't want to show Rest of World here
    if ( $id != 0 )
    {
        return _genericMapAccessor( 'RPS::DB::Item::Region', 'region_id', $id );
    }
    else
    {
        return ' ';
    }
}

sub channelIDToName
{
    my ($id) = @_;
    return _genericMapAccessor( 'RPS::DB::Item::Channel', 'channel_id', $id );
}

sub priceLevelIDToName
{
    my ($id) = @_;
    return _genericMapAccessor( 'RPS::DB::Item::PriceLevel', 'price_level_id',
        $id );
}

sub contractRateTypeIDToName
{
    my ($id) = @_;
    return _genericMapAccessor( 'RPS::DB::Item::ContractRateType',
        'contract_rate_type_id', $id );
}

sub productCodeToName
{
    my ($id) = @_;
    return _genericMapAccessor( 'RPS::DB::Item::ProductType', 'product_type_id',
        $id );
}

sub addDraftWatermarkPayee
{
    my ($pdf, $pages) = @_;

    my $centerX = kPageWidth / 2;
    my $centerY = kPageHeight / 2;

    foreach my $page (@gPayeePages)
    {
        my $text = $page->text(1);
        $text->font( $font->{Helvetica}{Bold}, 128 / pt );
        $text->transform(
            -translate => [ $centerX, $centerY ],
            -rotate    => 45
        );

        $text->fillcolor('lightgray');
        $text->text_center('DRAFT');
        $text->fillcolor('black');
    }
}

sub addDraftWatermarkFull
{
    my ($pdf, $pages) = @_;

    my $centerX = kPageWidth / 2;
    my $centerY = kPageHeight / 2;

    foreach my $page (@gFullPages)
    {
        my $text = $page->text(1);
        $text->font( $font->{Helvetica}{Bold}, 128 / pt );
        $text->transform(
            -translate => [ $centerX, $centerY ],
            -rotate    => 45
        );

        $text->fillcolor('lightgray');
        $text->text_center('DRAFT');
        $text->fillcolor('black');
    }
}

#
# Boring script stuff below...
#

sub parseCommandLine
{
    my ($settings) = @_;

    my %opt;
    getopts( 's:c:f:m:V:', \%opt );

    if ( !$opt{s} || !$opt{c} || !$opt{m} )
    {
        usage();
        exit(1);
    }
    $settings->{mechanicalStatementID} = $opt{s};
    $settings->{clientID}              = $opt{c};
    $settings->{mode}                  = $opt{m};
    $settings->{outputFile}            = $opt{f};

    if ( defined $opt{V} )
    {
        $gVerbosityLevel = $opt{V};
    }
}

sub usage
{
    print STDERR
"\nusage: $0 -c <client_id> -s <mechanical_statement_id> -m <mode> [-f <output file>]\n";
    print STDERR "\n";
    print STDERR "Arguments:\n";
    print STDERR
      "\t-c <client_id>\t\t\tThe client_id of the client to process\n";
    print STDERR
"\t-s <mechanical_statement_id>\tThe id of the mechanical statement to convert to pdf\n";
    print STDERR
    "\t-m <mode>\tThe mode that the script should run in (p = payee, f = full, b = both)\n";
    print STDERR
"\t-f <output file>\tThe output file. Optional. If not provided, we'll make one up\n";
}

sub report
{
    my ( $string, $verbosity ) = @_;
    $verbosity = 1 unless defined $verbosity;

    if ( $gVerbosityLevel >= $verbosity )
    {
        print STDERR $string . "\n";
    }
}

