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

#use warnings;

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 Common::UTF8;

use lib '/app/tools/rps/lib';
use RPS::Statement::Mechanical::CA::StatementFull;
use RPS::Statement::Mechanical::CA::StatementLicenseTransactionList;
use RPS::Payor::Payor;
use RPS::Publisher::CA::Publisher;
use RPS::Mechanical::CA::MechanicalRun;
use RPS::DB::Item::CAMechanicalRun;
use RPS::DB::Item::ContractRateType;
use RPS::DB::Item::IncomeSource;
use RPS::DB::Item::Region;
use RPS::DB::Item::Channel;
use RPS::DB::Item::PriceLevel;
use RPS::DB::Item::ProductType;
use RPS::DB::Item::TrackLicense;

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

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



# 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 text file!
#
my %options;
parseCommandLine( \%options );
createStatement( $options{clientID}, $options{mechanicalStatementID},
    $options{outputFile} );

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

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

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

    # Instantiate the MechanicalStatement object.
    # This object will contain all the info we need to output the statement document.
    #
    my $statement = RPS::Statement::Mechanical::CA::StatementFull->new(
        mechanicalStatementID => $mechanicalStatementID,
        focusPublisherID      => 'all'
    );

    my $runDBItem = RPS::DB::Item::CAMechanicalRun->Lookup(ca_mechanical_run_id => $statement->MechanicalRunID());

    my $payorID = $runDBItem->payor_id();


    my $run = RPS::Mechanical::CA::MechanicalRun->new(
        mechanicalRunID => $statement->MechanicalRunID(),
        payorID => $payorID,
    );

    # If an output file path was not specified, create one out of the statement id.
    #
    if ( !$outFilePath )
    {
        $outFilePath = "ca_mechanical_statement_$mechanicalStatementID.txt";
    }

	# Open file for writing
	open(my $outFile,">".$outFilePath);
	#binmode($outFile, ':utf8');
	#binmode $outFile,":encoding(latin1)";

    header($outFile, $run);


    my $statementUnits;
    my $statementAmount;
    my $statementRecords;


    # Loop through all publishers
    my $publisherList = $statement->MechanicalStatementPublisherList()->getList();
    foreach my $publisher (@$publisherList)
    {
        my ($publisherUnits, $publisherAmount, $publisherRecords) = details($outFile, $publisher);
        $statementUnits += $publisherUnits;
        $statementAmount += $publisherAmount;
        $statementRecords += $publisherRecords;
    }

    # We need to account for the header and footer in the statement records count.
    #
    $statementRecords += 2;

    footer($outFile, $run, $statementUnits, $statementAmount, $statementRecords);

    # All done, close it up.
    #
    close $outFile;
}

sub header
{
    my ($outFile, $run) = @_;

    my $payorID = $run->PayorID();
    my $payor = RPS::Payor::Payor->new(payorID => $payorID);

    # StartTime format is 2009-05-08 11:42:51
    my $dateCreated = formatDate($run->StartTime());
    my $periodStart = formatDate($run->StartDate());
    my $periodEnd = formatDate($run->EndDate());

	# Write out header stuff.
	my @headerFields = (
	    'HC',
	    formatAN($payor->Name(), 50),
	    formatAN($periodStart, 8),
	    formatAN($periodEnd, 8),
	    formatAN($dateCreated, 8),
	);

	my $header = join('', @headerFields);
	print $outFile uc("$header") . "\r\n";

}

sub details
{
    my ($outFile, $statement) = @_;


    # We'll add to these as we go so that we can print out publisher totals at the end.
    #
    my $publisherRecords = 0;
    my $publisherUnits = 0;
    my $publisherAmount = 0;

    my $publisherNumber = $statement->Publisher()->ClientAccountID();


	# Write out the publisher header stuff.
	#
	_printPublisherHeader($outFile, $publisherNumber, $statement->Publisher()->PublisherName());



    my $trackList = $statement->MechanicalStatementTrackList()->getList();
    foreach my $track (@$trackList)
    {
        my $trackData = RPS::DB::Item::Track->Lookup(track_id => $track->TrackID());
        my $trackTitle = $trackData->title;


        # Need to grab the song for this track now.
        #
        my $master = RPS::DB::Item::Master->Lookup(master_id => $trackData->master_id);
        my $song = RPS::DB::Item::Song->Lookup(song_id => $master->song_id());

        my $iswc = $song->iswc();
        my $duration = $master->duration();
        $duration = formatDuration($duration);

        # Composer is not mandatory, so we're leaving it blank for now.
        #
        my $composer = '';

	    # Go through the crossed license list
	    #
	    my $crossedLicenseList = $track->MechanicalStatementCrossedLicenseList()->getList();

	    if ( @$crossedLicenseList > 0 )
	    {
	        my $licenseAmount;
	        my $licenseUnits;
	        my $licenseRecords;

	        # Song header is really more of a license header.
	        # Since crossed licenses are grouped, we'll just print out one for all of them.
	        #

	        my $issuerSongID = $trackData->track_id . "C";

	        _printSongHeader($outFile, $publisherNumber, $issuerSongID, $trackTitle, $iswc, $composer);

		    foreach my $license (@$crossedLicenseList)
		    {

		        my $trackLicenseData = RPS::DB::Item::CATrackLicense->Lookup(ca_track_license_id => $license->TrackLicenseID());

                my $issuerLicenseID = $trackLicenseData->issuer_license_id;

    	        # If there is a previous balance for this license, let's print that out now.
    	        #
    	        if ($license->PreviousAdvanceBalance() != 0)
    	        {
                    _printSongBalanceForward($outFile, $license->PreviousAdvanceBalance(), $publisherNumber,  $issuerSongID, $issuerLicenseID, $track, $duration, $iswc);

                    $licenseAmount += $license->PreviousAdvanceBalance();

                    $licenseRecords++;
                }


		        my $incomeItemList = $license->MechanicalStatementItemList()->getList();
		        my $incomeItemListLength = scalar(@$incomeItemList);

				# If there are income items, print them out now.
				#
		        if ( $incomeItemListLength != 0 )
		        {

		            foreach my $incomeItem (@$incomeItemList)
		            {
		                _printSongRecord($outFile, $publisherNumber, $issuerSongID, $issuerLicenseID, $track, $incomeItem, $duration, $iswc);

		                $licenseAmount += $incomeItem->AmountPaid();

		                $licenseUnits += $incomeItem->NetUnits();

		                $licenseRecords++;
		            }
	        	}

	        	# If there are adjustments or advances for this license, print them out now.
	        	#
		        my $xmlObj = $license->MechanicalStatementLicenseTransactionList();
		        my $licenseTransactionList  = $xmlObj->getList();
		        my $licenseTransactionCount = scalar(@$licenseTransactionList);

		        if ( $licenseTransactionCount != 0 )
		        {
		            foreach my $licenseTransaction (@$licenseTransactionList)
		            {
                        _printSongAdjustment($outFile, $licenseTransaction->Amount(), $publisherNumber, $issuerSongID, $issuerLicenseID, $track, $duration, $iswc);

                        $licenseAmount += $licenseTransaction->Amount();

                        $licenseRecords++;
		            }
		        }

		    }

        	# If there are adjustments or advances for crossed licenses for this track, print them out now.
        	#
	        my $xmlObj = $track->MechanicalStatementCrossedLicenseTransactionList();
	        my $licenseTransactionList  = $xmlObj->getList();
	        my $licenseTransactionCount = scalar(@$licenseTransactionList);


	        if ( $licenseTransactionCount != 0 )
	        {
	            foreach my $licenseTransaction (@$licenseTransactionList)
	            {
                    _printSongAdjustment($outFile, $licenseTransaction->Amount(), $publisherNumber, $issuerSongID, '', $track, $duration, $iswc);

                    $licenseAmount += $licenseTransaction->Amount();

                    $licenseRecords++;
	            }
	        }
	        
	        
	        # If there is a previous balance for this group of crossed licenses, let's print that out now.
	        #
	        if ($track->CrossedPreviousAdvanceBalance() != 0)
	        {
                _printSongBalanceForward($outFile, $track->CrossedPreviousAdvanceBalance(), $publisherNumber,  $issuerSongID, '', $track, $duration, $iswc);

                $licenseAmount += $track->CrossedPreviousAdvanceBalance();

                $licenseRecords++;
            }	        
	        

	        # Negative balances will be carried forward, so don't include them in the totals for the track.
	        #
	        if ($licenseAmount < 0)
	        {
	       	    $licenseAmount = 0;
	       	    $licenseUnits = 0;

	       	}

	       	# We need to account for the header and footer records in the count.
	       	#
	       	$licenseRecords += 2;

	        _printSongTrailer($outFile, $publisherNumber, $issuerSongID, $trackTitle, $licenseUnits, $licenseAmount, $licenseRecords);

	        # Add the crossed license totals to the publisher totals.
	        #
    	    $publisherUnits += $licenseUnits;
    	    $publisherAmount += $licenseAmount;
    	    $publisherRecords += $licenseRecords;

	    }


	    # Go through the uncrossed license list
	    #
	    my $licenseList = $track->MechanicalStatementLicenseList()->getList();
	    foreach my $license (@$licenseList)
	    {
	        my $licenseRecords;
	        my $licenseAmount;
	        my $licenseUnits;

            my $trackLicenseData = RPS::DB::Item::CATrackLicense->Lookup(ca_track_license_id => $license->TrackLicenseID());

            my $issuerLicenseID = $trackLicenseData->issuer_license_id;
            my $issuerSongID = $license->TrackLicenseID();


	        _printSongHeader($outFile, $publisherNumber, $issuerSongID, $trackTitle, $iswc, $composer);


	        # If there is a previous balance for this license, let's print that out now.
	        #
	        if ($license->PreviousAdvanceBalance() != 0)
	        {
                _printSongBalanceForward($outFile, $license->PreviousAdvanceBalance(), $publisherNumber, $issuerSongID, $issuerLicenseID, $track, $duration, $iswc);

                $licenseAmount += $license->PreviousAdvanceBalance();

                $licenseRecords++;
            }


	        my $incomeItemList = $license->MechanicalStatementItemList()->getList();
	        my $incomeItemListLength = scalar(@$incomeItemList);

			# If there are income items, print them out now.
			#
	        if ( $incomeItemListLength != 0 )
	        {

	            foreach my $incomeItem (@$incomeItemList)
	            {
		            _printSongRecord($outFile, $publisherNumber, $issuerSongID, $issuerLicenseID, $track, $incomeItem, $duration, $iswc);


                    $licenseAmount += $incomeItem->AmountPaid();
                    $licenseUnits += $incomeItem->NetUnits();


		            $licenseRecords++;
	            }
	        }

	        my $xmlObj = $license->MechanicalStatementLicenseTransactionList();
	        my $licenseTransactionList  = $xmlObj->getList();
	        my $licenseTransactionCount = scalar(@$licenseTransactionList);

	        if ( $licenseTransactionCount != 0 )
	        {
	            foreach my $licenseTransaction (@$licenseTransactionList)
	            {
                    _printSongAdjustment($outFile, $licenseTransaction->Amount(), $publisherNumber, $issuerSongID, $issuerLicenseID, $track, $duration, $iswc);

                    $licenseAmount += $licenseTransaction->Amount();

                    $licenseRecords++;
	            }
	        }

	        # Negative balances will be carried forward, so don't include them in the totals for the license.
	        #
	        if ($licenseAmount < 0)
	        {
	       	    $licenseAmount = 0;
	       	    $licenseUnits = 0;

	       	}

    	    # Print out the totals for this track.
    	    # We need to account for the header and footer in the track record count.
    	    #
	       	$licenseRecords += 2;

	       	_printSongTrailer($outFile, $publisherNumber, $issuerSongID, $trackTitle, $licenseUnits, $licenseAmount, $licenseRecords);

	       	# Add the license totals to the publisher totals.
	       	#
    	    $publisherUnits += $licenseUnits;
    	    $publisherAmount += $licenseAmount;
    	    $publisherRecords += $licenseRecords;

	    }

	}

    # Print out the footer with the grand totals for this publisher.
    #

    # We need to account for the header and footer in the publisher record count.
    #
    $publisherRecords += 2;

	_printPublisherTrailer($outFile, $publisherNumber, $publisherUnits, $publisherAmount, $publisherRecords);

    return ($publisherUnits, $publisherAmount, $publisherRecords);

}



sub	_printPublisherHeader
{
    my ($outFile, $publisherNumber, $publisherName) = @_;

	my @publisherHeaderFields = (
	    'HP',
	    formatAN($publisherNumber, 10),
	    formatAN($publisherName, 50),
	);

	my $publisherHeader = join('', @publisherHeaderFields);
	print $outFile uc("$publisherHeader") . "\r\n";
}


sub _printPublisherPreviousBalance
{
    my ($outFile, $publisherNumber, $previousBalance) = @_;

	my @publisherFields = (
	    'DP',
	    formatAN($publisherNumber, 10),
	    formatRZ($previousBalance, 13, 2, 1),
	    formatAN('Previous Balance', 50),
	);

	my $publisherPreviousBalance = join('', @publisherFields);
	print $outFile uc("$publisherPreviousBalance") . "\r\n";
}


sub _printPublisherPreviousAdvanceBalance
{
    my ($outFile, $publisherNumber, $previousAdvanceBalance) = @_;

	my @publisherFields = (
	    'DP',
	    formatAN($publisherNumber, 10),
	    formatRZ($previousAdvanceBalance, 13, 2, 1),
	    formatAN('Previous Advance Balance', 50),
	);

	my $publisherPreviousAdvanceBalance = join('', @publisherFields);
	print $outFile uc("$publisherPreviousAdvanceBalance") . "\r\n";

}


sub _printPublisherTransaction
{
    my ($outFile, $publisherNumber, $transaction) = @_;

    my $transactionType = transactionTypeCodeToName($transaction->TypeCode());
    my $transactionAmount = $transaction->Amount;
	my @publisherTransactionFields = (
	    'DP',
	    formatAN($publisherNumber, 10),
	    formatRZ($transactionAmount, 13, 2, 1),
	    formatAN($transactionType, 50),
	);

	my $publisherTransactions = join('', @publisherTransactionFields);
	print $outFile uc("$publisherTransactions") . "\r\n";
}


sub	_printPublisherTrailer
{
    my ($outFile, $publisherNumber, $units, $amount, $records) = @_;

	my @publisherTrailerFields = (
	    'TP',
	    formatAN($publisherNumber, 10),
	    formatRZ($units, 13, 0, 1),
	    formatRZ($amount, 13, 2, 1),
	    formatRZ($records, 6, 0),
	);

	my $publisherTrailer = join('', @publisherTrailerFields);
	print $outFile uc("$publisherTrailer") . "\r\n";
}


sub _printSongHeader
{
    my ($outFile, $publisherNumber, $issuerSongID, $songTitle, $iswc, $composer) = @_;

	my @songHeaderFields = (
	    'HS',
	    formatAN($publisherNumber, 10),
	    formatAN($issuerSongID, 20),
	    formatAN($songTitle, 50),
	    formatAN($iswc, 20),
	    formatAN($composer, 100),
	);

	my $songHeader = join('', @songHeaderFields);
	print $outFile uc("$songHeader") . "\r\n";
}


sub _printSongBalanceForward
{
    my ($outFile, $trackAmount, $publisherNumber, $issuerSongID, $issuerLicenseID, $track, $duration, $iswc) = @_;

	my @itemRow = (
	    'DS',
	    formatAN('B', 2),
	    formatAN($publisherNumber, 10),
	    formatAN($issuerSongID, 20),
	    formatAN($track->SongTitle(), 50),
	    formatAN($track->CatalogNumber(), 15),
	    formatAN('', 15),
	    formatRZ(0, 13, 0, 1),
	    'P',
	    formatRZ(0, 15, 9),
	    formatRZ(0, 7, 4),
	    formatRZ($trackAmount, 13, 2, 1),
	    formatRZ($duration, 6, 0),
	    formatAN('', 20),
	    formatAN($iswc, 20),
	    formatAN('', 5), # distribution method
    );

    my $joinedItemRow = join("", @itemRow);
	print $outFile uc("$joinedItemRow") . "\n";
}


sub _printSongRecord
{
    my ($outFile, $publisherNumber, $issuerSongID, $issuerLicenseID, $track, $incomeItem, $duration, $iswc) = @_;

	my @itemRow = (
	    'DS',
	    formatAN('N', 2),
	    formatAN($publisherNumber, 10),
	    formatAN($issuerSongID, 20),
	    formatAN($track->SongTitle(), 50),
	    formatAN($track->CatalogNumber(), 15),
	    formatAN($issuerLicenseID, 15),
	    formatRZ($incomeItem->NetUnits(), 13, 0, 1),
	    'P',
	    formatRZ($incomeItem->NetRate(), 15, 9),
	    formatRZ($incomeItem->TrackLicense->Share(), 7, 4),
	    formatRZ($incomeItem->AmountPaid(), 13, 2, 1),
	    formatRZ($duration, 6, 0),
	    formatAN($incomeItem->UPC(), 20),
	    formatAN($iswc, 20),
	    formatAN('', 5), # distribution method
    );

    my $joinedItemRow = join("", @itemRow);
	print $outFile uc("$joinedItemRow") . "\n";
}


sub _printSongAdjustment
{
    my ($outFile, $adjustmentAmount, $publisherNumber, $issuerSongID, $issuerLicenseID, $track, $duration, $iswc) = @_;

	my @itemRow = (
	    'DS',
	    formatAN('A', 2),
	    formatAN($publisherNumber, 10),
	    formatAN($issuerSongID, 20),
	    formatAN($track->SongTitle(), 50),
	    formatAN($track->CatalogNumber(), 15),
	    formatAN($issuerLicenseID, 15),
	    formatRZ(0, 13, 0, 1),
	    'P',
	    formatRZ(0, 15, 9),
	    formatRZ(0, 7, 4),
	    formatRZ($adjustmentAmount, 13, 2, 1),
	    formatRZ($duration, 6, 0),
	    formatAN('', 20),
	    formatAN($iswc, 20),
	    formatAN('', 5), # distribution method
    );

    my $joinedItemRow = join("", @itemRow);
	print $outFile uc("$joinedItemRow") . "\n";
}


sub _printSongTrailer
{
    my ($outFile, $publisherNumber, $issuerSongID, $songTitle, $units, $amount, $records) = @_;

	my @songHeaderFields = (
	    'TS',
	    formatAN($publisherNumber, 10),
	    formatAN($issuerSongID, 20),
	    formatAN($songTitle, 50),
	    formatRZ($units, 13, 0, 1),
	    formatRZ($amount, 13, 2, 1),
	    formatRZ($records, 6, 0),
	);

	my $songHeader = join('', @songHeaderFields);
	print $outFile uc("$songHeader") . "\r\n";
}


sub footer
{
    my ($outFile, $run, $units, $amount, $records) = @_;

    my $payorID = $run->PayorID();
    my $payor = RPS::Payor::Payor->new(payorID => $payorID);

	# Write out footer stuff.
	my @footerFields = (
	    'TC',
	    formatAN($payor->Name(), 50),
	    formatRZ($units, 13, 0, 1),
	    formatRZ($amount, 13, 2, 1),
	    formatRZ($records, 6, 0),
	);

	my $footer = join('', @footerFields);
	print $outFile uc("$footer") . "\r\n";
}



# Formatting functions
#

sub formatAN
{
    #  Left-adjusted alphanumeric field, right space-filled
    #
    my ($string, $length) = @_;
    my $latinString = Common::UTF8::ToAscii($string);

    my $padded = pack("A$length",$latinString);

    return $padded;
}


sub formatRZ
{
    #  Right-adjusted numeric field, left zero filled
    my ($string, $length, $decimalPlaces, $signed) = @_;

    # Let's see if we're dealing witha positive or negative number.
    #
    my $sign;

    if ($string < 0)
    {
        $sign = '-';
    }
    else
    {
        $sign = '+';
    }

    # First, let's make sure there are the right number of places after the decimal.
    #
    if ($decimalPlaces > 0)
    {
        my $sprintfArg = "%." . $decimalPlaces . "f";
        $string = sprintf($sprintfArg, $string);
    }

    # Now let's get rid of anything that's not a digit.
    $string =~ s/\D//g;

    $string = substr("0"x$length.$string,-$length);

    # Note that we are not "signing" zero at this time.
    # If it turns out that we should be, simply remove that part of the following if statement.
    #
    if ($string != 0 && $signed)
    {
        #
        # Here's the fun part.  We need to convert the last digit to EBCDIC.
        # This allows us to show whether a number is positive or negative without using an extra character.
        # Characters aren't cheap, ya know.
        my $last = chop($string);
        $last = convertToEBCDIC($sign.$last);
        $string .= $last;
    }


    return $string;
}


sub transactionTypeCodeToName
{
    my ($code) = @_;

    my $name = "Adjustment";

    if ($code == 3)
    {
        $name = "Advance";
    }

    return $name;
}


sub convertToEBCDIC
{
    my ($string) = @_;

    if ($string eq '+0')
    {
        $string = '{';
    }
    elsif ($string eq '+1')
    {
        $string = 'A';
    }
    elsif ($string eq '+2')
    {
        $string = 'B';
    }
    elsif ($string eq '+3')
    {
        $string = 'C';
    }
    elsif ($string eq '+4')
    {
        $string = 'D';
    }
    elsif ($string eq '+5')
    {
        $string = 'E';
    }
    elsif ($string eq '+6')
    {
        $string = 'F';
    }
    elsif ($string eq '+7')
    {
        $string = 'G';
    }
    elsif ($string eq '+8')
    {
        $string = 'H';
    }
    elsif ($string eq '+9')
    {
        $string = 'I';
    }
    elsif ($string eq '-0')
    {
        $string = '}';
    }
    elsif ($string eq '-1')
    {
        $string = 'J';
    }
    elsif ($string eq '-2')
    {
        $string = 'K';
    }
    elsif ($string eq '-3')
    {
        $string = 'L';
    }
    elsif ($string eq '-4')
    {
        $string = 'M';
    }
    elsif ($string eq '-5')
    {
        $string = 'N';
    }
    elsif ($string eq '-6')
    {
        $string = 'O';
    }
    elsif ($string eq '-7')
    {
        $string = 'P';
    }
    elsif ($string eq '-8')
    {
        $string = 'Q';
    }
    elsif ($string eq '-9')
    {
        $string = 'R';
    }
    return $string;
}


sub formatDate
{
    my ($date) = @_;

    # Returns date in format: yyyymmdd

	my $formattedDate = substr($date,0,4);
	$formattedDate .= substr($date,5,2);
	$formattedDate .= substr($date,8,2);
	return $formattedDate;
}


sub formatDuration
{
    my ($seconds) = @_;
    $seconds = 0 unless( $seconds );

    my $hours = $seconds / 3600;
    $seconds = $seconds % 3600;
	my $minutes = $seconds / 60;
	$seconds = $seconds % 60;
	return sprintf("%02d%02d%02d", $hours, $minutes, $seconds);

}


# 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 );
}


#
# Boring script stuff below...
#

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

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

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

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

sub usage
{
    print STDERR "\nusage: $0 -c <client_id> -s <ca_mechanical_statement_id> [-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 <ca_mechanical_statement_id>\tThe id of the ca mechanical statement to convert to cmrra text\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";
    }
}
