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

package RPS::Import::PIAS::v5;

use strict;

use lib '/app/tools/common/lib';
use Common::Country;
use Common::Assert;
use Date::Calc qw(Days_in_Month Decode_Month);

use lib '/app/tools/rps/lib';
use base 'RPS::Import::Importer';

sub _fieldMap {
    {
        # Header
        dateBegin        => 'A',
        currencyCode     => 'A',

        # Detail
        countryCode      => 'E',
        productType      => 'G',
        artistName       => 'A',
        upc              => 'D',
        isrc             => 'C',
        albumName        => 'B',
        priceLevel       => 'H',
        wholesalePrice   => 'K',
        totalRevenue     => 'Q',
    }
}

sub _unverifiedFieldMap {
    {
        netUnits => 'P',
    }
}

sub physical { 1; }

sub _headerIdentifier { ( albumName => 'PRODUCT' ) }

sub channel { RPS::File::Sale::CHANNEL_RETAIL }

sub artistName {
    my $self = shift;
    my $name = $self->_getByFieldName( 'artistName' );
    $name =~ s/^-   //;  # Remove any cruft if necessary
    return $name;
}

sub priceLevel { 
    my $self = shift;
    my $priceCategory = $self->_getByFieldName('priceLevel');
    
    if( $priceCategory =~ /^(INVOICE|CREDIT NOTE)$/i )
    {
        return RPS::File::Sale::PLEVEL_UNKNOWN;
    }
    elsif( $priceCategory =~ /^FULL PRICE$/i )
    {
        return RPS::File::Sale::PLEVEL_FULL;
    }
    elsif( $priceCategory =~ /^MID PRICE$/i )
    {
        return RPS::File::Sale::PLEVEL_MID;
    }
    elsif( $priceCategory =~ /^BUDGET$/i )
    {
        return RPS::File::Sale::PLEVEL_BUDGET;
    }
    $self->fail("Unable to get price level from $priceCategory");
}

sub currencyCode {
    my $self = shift;
    return $self->{_currencyCode} if( $self->{_currencyCode} );
    $self->fail("Unable to determine currency code");
}

sub saleDates {
    my $self = shift;

    return ($self->{_startDate}, $self->{_endDate}) if( $self->{_startDate} ); # from header of current sheet; see _preProcess
}

sub countryCode {
    my $self = shift;
    my $cname = $self->_getByFieldName( 'countryCode' );
    
    my $countryObj  = Common::Country->Get( $cname );
    my $countryCode = $countryObj->alpha2() if( $countryObj );
    return $countryCode;
}

sub productType {
    my $self = shift;
    my $type = $self->_getByFieldName('productType');

    if( $type =~ /^(lp|12|2x12|2lp|2nd LP Format)$/i )
    {
        return RPS::File::Sale::TYPE_LP;
    }
    elsif( $type =~ /^cd( digipack)?$/i )
    {
        return RPS::File::Sale::TYPE_CD;
    }
    elsif( $type =~ /^(2|4)cd$/i )
    {
        return RPS::File::Sale::TYPE_DBL_CD;
    }
    elsif( $type =~ /^12" ep$/i )
    {
        return RPS::File::Sale::TYPE_LP5;
    }
    $self->fail("Unknown configuration '$type'");
}

sub sales {
    my $self = shift;
    my $netUnits = $self->_getByFieldName('netUnits');

    return ( $netUnits > 0 ) ? $netUnits : 0;
}

sub salesRevenue {
    my $self = shift;
    my $revenue = $self->_getByFieldName('totalRevenue');

    return ( $revenue > 0 ) ? $revenue : 0;
}

sub returns {
    my $self = shift;
    my $netUnits = $self->_getByFieldName('netUnits');

    return ( $netUnits < 0 ) ? abs($netUnits) : 0;
}

sub returnsRevenue {
    my $self = shift;
    my $revenue = $self->_getByFieldName('totalRevenue');
    
    return ( $revenue < 0 ) ? abs($revenue) : 0;
}

# Note: adjusting offsets only works for column notation.  It does _not_
# work if the field is specified using cell notation (e.g., "C10").
# Also, we can shift left or right depending on the value of _shiftedColumns.
#
sub _getOffset {
    my $self = shift;
    my $field = shift;

    my $offset = $self->SUPER::_getOffset($field);
    return undef if( !defined $offset );
    if( $self->{_shiftedColumns} )
    {
        return $offset + $self->{_shiftedColumns};
    }
    return $offset;
}

sub _processSheet {
    my $self = shift;
    my $sheet = shift;
    my $sheetnum = shift;

    delete $self->{_shiftedColumns} if( exists $self->{_shiftedColumns} );

    # The only sheets that will be scanned for sales are the ones with a
    # valid header.  For whatever reason some of the headers may be offset
    # due to a blank leftmost column.  We check for that in the following
    # loop before calling the inherited _processSheet() to read the sales.
    # If the sheet looks shifted, we set a flag that is used by _getOffset
    # to correct map the fieldnames in _fieldMap to the actual column
    # positions containing the data.
    #
    foreach my $line (@$sheet) {
        $self->{line} = $line;
        my $albumName = $self->_getByFieldName('albumName'); # normally column B, unless shifted

        # Check for header line and adjust offset if album name is in the wrong spot
        #
        last if ( $albumName =~ /^PRODUCT$/i ); # column in right spot

        if( $albumName =~ /^ARTIST$/i )
        {
            # shifted column, set the correct field offset
            #
            $self->{_shiftedColumns} = 1;  # see _getOffset
            last;
        }
    }
    return $self->SUPER::_processSheet( $sheet, $sheetnum );
}

sub _preProcess {
    my( $self, %args ) = @_;

    Log->info( "Starting _preProcess" );
    $self->SUPER::_preProcess(%args);

    my $sheetNames = $args{sheet_names};
    my $sheetCount = 0;

    SHEET: foreach my $sheet(@{ $args{sheets} })
    {
        next if( $self->{_startDate} && $self->{_currencyCode} );

        my $sheetName = $sheetNames->[$sheetCount];
        if( $sheetName != /^summary$/i )
        {
            $sheetCount++;
            next;
        }

        my $linenum=1;
        foreach my $line(@$sheet)
        {
            $self->{line} = $line;

            # We should be able to find the required info within the first
            # 100 lines of the summary tab.  If not, then the following check
            # will prevent us from wasting time dealing with a summary tab
            # containing 1000's of lines.
            #
            last if( $linenum > 100 );

            # Look for the sale date and/or currency code information
            #
            if( !$self->{_startDate} || !$self->{_currencyCode} )
            {
                # The following loop iterates over the columns in the current line
                # and if it looks like a line containing dates and/or currency code
                # information, then we'll grab the data from the line.

                # Since we're not using _getFieldByName, we don't have to worry
                # about shifted columns or rows.
                #
                my $isDateLine = 0;
                my $isCurrencyLine = 0;
                foreach my $cell (@$line)
                {
                    # If we see the word "period" in the cell, then we'll assume that
                    # this is a date line and look for the actual date information
                    # on the same line.  The actual date information will usually be
                    # in a subsequent cell, however it may be part of the current cell
                    # so we check for that too.
                    #
                    $isDateLine = 1 if( $cell =~ /period/i );

                    # Similarly, we check for a label indicating that the currency code
                    # information is on this line.
                    # 
                    $isCurrencyLine = 1 if( $cell =~ /all amounts printed in/i ||
                                            $cell =~ /^Currency\:$/i );


                    if( $isDateLine && !$self->{_startDate} )
                    {
                        # The date information can be in one of the following formats:
                        #    FOR PERIOD JAN 2014 TO JUN 2014            (FB10711)
                        #    Reporting Period: 01/01/2015 to 30/06/2015 (FB11787, FB11789)
                        #    Period: 01/01/2015 to 30/06/2015           (FB12714)
                        #
                        if( $cell =~ /(\d{2})\/(\d{2})\/(\d{4}) to (\d{2})\/(\d{2})\/(\d{4})/i )
                        {
                            my($sDay, $sMonth, $sYear, $eDay, $eMonth, $eYear) = ($1, $2, $3, $4, $5, $6);
                            $self->{_startDate} = sprintf( "%04d-%02d-%02d", $sYear, $sMonth, $sDay );
                            $self->{_endDate}   = sprintf( "%04d-%02d-%02d", $eYear, $eMonth, $eDay );
                        }
                        elsif( $cell =~ /for period (\w+) (\d{4}) to (\w+) (\d{4})/i )
                        {
                            my $startMonth = Decode_Month($1);
                            my $startYear  = $2;

                            my $endMonth = Decode_Month($3);
                            my $endYear  = $4;

                            $self->{_startDate} = sprintf("%04d-%02d-%02d", $startYear, $startMonth, 1);
                            $self->{_endDate}   = sprintf("%04d-%02d-%02d", $endYear, $endMonth, Days_in_Month($endYear, $endMonth));
                        }
                    }

                    if( $isCurrencyLine && !$self->{_currencyCode} )
                    {
                        if( $cell =~ /all amounts printed in (\w+)/i )
                        {
                            $self->{_currencyCode} = $1;
                        }
                        elsif( '' ne $cell && $cell !~ /currency/i )
                        {
                            $self->{_currencyCode} = $cell;
                        }
                    }
                }
            }

            last SHEET if( $self->{_startDate} && $self->{_currencyCode} );

            $linenum++;
        }#line

        $sheetCount++;

        last; # ONLY process summary sheet for date/currency code

    }#sheet
}

sub _isValidSaleRecord {
    my $self = shift;

    # The line is valid if it has sales or returns, and has an album title
    #
    return ( ($self->sales != 0 || $self->returns != 0) && $self->albumName );
}

###
1;# Play nicely.
###
