#---------------------------------------------------------------
# ____                   _ _         ____  _
#|  _ \ ___  _   _  __ _| | |_ _   _/ ___|| |__   __ _ _ __ ___
#| |_) / _ \| | | |/ _` | | __| | | \___ \| '_ \ / _` | '__/ _ \
#|  _ < (_) | |_| | (_| | | |_| |_| |___) | | | | (_| | | |  __/
#|_| \_\___/ \__, |\__,_|_|\__|\__, |____/|_| |_|\__,_|_|  \___|
#            |___/             |___/
#
# 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',
        retail         => 'K',
    };
}

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|12LTD|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 =~ /^(?:7|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.
###
