package RPS::Import::ADA::v31;

use strict;
use Data::Dumper;

use lib '/app/tools/common/lib';
use Common::Util qw(normalize_date normalize_upc);
use Date::Calc qw(Days_in_Month);

use lib '/app/tools/data_classes/lib';
use Client::Service;

use lib '/app/tools/rps/lib';
use RPS::File::Sale;
use RPS::Import::ServiceMap;

use base 'RPS::Import::MapFaceBase';
use base 'RPS::Import::ADA::ADACommon';

sub _headerIdentifier {
    my $self = shift;
    my $sheetName = lc $self->{sheetname};
    my %headerMap = (
        'domestic' => { dateBegin => 'REPORT_START_DATE' },
        'intl digital' => { dateBegin => 'MONTH'},
    );
    return $headerMap{$sheetName};

}

# Note: sheetname isn't set when _fieldMap and _unverifiedFieldMap are
# first initialized, so we have to override _validateFieldMap to prevent
# errors.
#
sub _validateFieldMap {}

sub _fieldMap {
    my $self = shift;

    my $sheetName = lc $self->{sheetname};
    my %fieldMaps = (
        'domestic' => {
            dateBegin   => 'E',
            dateEnd     => 'F',
            labelName   => 'AD',
            productType => 'S',  # FORMAT
            formatType  => 'AQ', # INCOME_TYPE_CD
            serviceID   => 'C',
            artistName  => 'I',
            albumName   => 'X',
            upc         => 'V',
            trackName   => 'K',
            isrc        => 'T',
            units       => 'L',
            price       => 'Q',
        },
        'intl digital' => {
            dateBegin   => 'A',
            dateEnd     => 'A',
            labelName   => 'T',
            serviceID   => 'E',
            countryCode => 'F',
            artistName  => 'G',
            albumName   => 'Z',
            trackName   => 'H',
            units       => 'N',
            price       => 'O',
            upc         => 'I',
        },
    );

    if ($fieldMaps{$sheetName})
    {
        return $fieldMaps{$sheetName};
    }
    else
    {
        return $self->handleError("_fieldMap: Illegal sheet '$sheetName'",
            RPS::DB::Item::SaleImportError::kErrorNonqualifying);
    }
}

sub _unverifiedFieldMap {
    my $self = shift;
    my $sheetName = lc $self->{sheetname};
    my %fieldMaps = (
        'domestic' => {
        },
        'intl digital' => {
            deliveryType => 'D',    # Media Code
            deliveryFormat => 'AI', # EMD
            prodID    => 'K',
            prodIdent => 'J',
        },
    );

    if ($fieldMaps{$sheetName})
    {
        return $fieldMaps{$sheetName};
    }
    else
    {
        return $self->handleError("_unverifiedFieldMap: Illegal sheet '$sheetName'",
            RPS::DB::Item::SaleImportError::kErrorNonqualifying);
    }
}

sub serviceID {
    my $self = shift;
    my $serviceName = $self->_getByFieldName( 'serviceID' ) || return;

    my $serviceID = $self->getServiceID(lc ($serviceName)); # See ADACommon

    if (!$serviceID && $serviceName =~ /[[:^ascii:]]/)
    {
        # Case 15436 - defaulting service names with incompatible characters to ADA
        $serviceID = Client::Service::DSP_ADA;
    }

    if (!$serviceID)
    {
        return $self->handleError("Unknown service: $serviceName", RPS::DB::Item::SaleImportError::kErrorService);
    }
    else
    {
        return $serviceID;
    }
}

sub upc {
    my $self = shift;
    if( exists $self->_unverifiedFieldMap->{prodID} ) # intl
    {
        my $productID         = $self->_getByFieldName('prodID');
        my $productIdentifier = $self->_getByFieldName('prodIdent');
        $productIdentifier =~ s/\\//g;
        return $productIdentifier if( $productID =~ /upc/i );

        # If Product ID is not UPC, then we may still have a UPC
        # in another column if we're dealing with a track sale
        #
        my $upc = $self->_getByFieldName('upc');
        $upc =~ s/\\//g;
        return $upc if($self->productType eq RPS::File::Sale::TYPE_TRACK);
    }
    else
    {
        # domestic
        my $upc = $self->_getByFieldName('upc');
        $upc =~ s/\\//g;
        return $upc;
    }
}

sub isrc {
    my $self = shift;
    if( exists $self->_unverifiedFieldMap->{prodID} ) # intl
    {
        my $productID         = $self->_getByFieldName('prodID');
        my $productIdentifier = $self->_getByFieldName('prodIdent');
        $productIdentifier =~ s/\\//g;
        return $productIdentifier if( $productID =~ /isrc/i );
    }
    else
    {
        # domestic
        my $isrc = $self->_getByFieldName('isrc');
        $isrc =~ s/\\//g;
        return $isrc if($self->productType eq RPS::File::Sale::TYPE_TRACK);
    }
}

sub currencyCode { 'USD' }

sub countryCode {
    my $self = shift;

    if( exists $self->_fieldMap->{countryCode} )  # intl
    {
        if(defined $self->_getByFieldName('countryCode'))
        {
            my $name = $self->_getByFieldName('countryCode');
            my $o = Common::Country->Get($name);
            return $o->alpha2() if($o);

            return $self->handleError("Unknown country: $name", RPS::DB::Item::SaleImportError::kErrorCountry );
        }
    }
    else
    {
        return 'US'; # domestic
    }
}

sub trackName {
    my $self = shift;
    return $self->_getByFieldName('trackName') if($self->productType eq RPS::File::Sale::TYPE_TRACK);
}

sub serviceID {
    my $self = shift;
    my $service = $self->_getByFieldName( 'serviceID' ) || return;
    my $serviceID = $self->getServiceID( $service ) || $RPS::Import::ServiceMap::SERVICE_ALIASES{ lc $service };
    
    return $serviceID if( $serviceID );
    
    # Let's keep trying.
    # Trying to get the Korean names to match up...
    my $serviceCopy = $service;
    $serviceCopy =~ s/(.|\n)/sprintf("%02lx", ord $1)/eg;  
    $serviceID = $RPS::Import::ServiceMap::SERVICE_ALIASES{ lc $serviceCopy };   
                    
    return $serviceID if( $serviceID );              
    
    if ( $service =~ /[[:^ascii:]]/ ) {
        # Case 15436 - defaulting service names with incompatible characters to ADA
        return Client::Service::DSP_ADA;
    }             
                      
    return $self->handleError("Unknown service: $service", RPS::DB::Item::SaleImportError::kErrorService);
}

my %domesticMappings = (
    'DRMUPGR' => {
        'format' => RPS::File::Sale::FORMAT_DOWNLOADUPGRADE,
        'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'DUALDIST' => {
        'format' => RPS::File::Sale::FORMAT_DUALDOWNLOAD,
        'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'PERMDWNL' => {
        'format' => RPS::File::Sale::FORMAT_DOWNLOAD,
        'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'PERMVDLD' => {
        'format' => RPS::File::Sale::FORMAT_DOWNLOAD,
        'media' => RPS::DB::Item::MediaType::kMediaTypeVideo,
    },
    'SUBASONE' => {
        'format' => RPS::File::Sale::FORMAT_STREAM,
        'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'SUBASPPE' => {
        'format' => RPS::File::Sale::FORMAT_STREAM,
        'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'SUBVSONE' => {
        'format' => RPS::File::Sale::FORMAT_STREAM,
        'media' => RPS::DB::Item::MediaType::kMediaTypeVideo,
    },
    'SUBVSPPE' => {
        'format' => RPS::File::Sale::FORMAT_STREAM,
        'media' => RPS::DB::Item::MediaType::kMediaTypeVideo,
    },
    'UGMV' => {
        'format' => RPS::File::Sale::FORMAT_STREAM,
        'media' => RPS::DB::Item::MediaType::kMediaTypeVideo,
    },
    'UGRWRMST' => {
        'format' => RPS::File::Sale::FORMAT_RINGTONE,
        'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'UGV' => {
        'format' => RPS::File::Sale::FORMAT_STREAM,
        'media' => RPS::DB::Item::MediaType::kMediaTypeVideo,
    },
    'WRMST' => {
        'format' => RPS::File::Sale::FORMAT_RINGTONE,
        'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'WRRNGBK' => {
        'format' => RPS::File::Sale::FORMAT_RINGTONE,
        'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'WRSTREAM' => {
        'format' => RPS::File::Sale::FORMAT_STREAM,
        'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'SUBAICLD' => {
        'format' => RPS::File::Sale::FORMAT_STREAM,
        'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'SUBVICLD' => {
        'format' => RPS::File::Sale::FORMAT_STREAM,
        'media' => RPS::DB::Item::MediaType::kMediaTypeVideo,
    },
);

my %internationalMappings = (
    'emastertone' => {
        'download' => {
            'product' => RPS::File::Sale::TYPE_TRACK,
            'format' => RPS::File::Sale::FORMAT_RINGTONE,
            'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'wireless' => {
            'product' => RPS::File::Sale::TYPE_TRACK,
            'format' => RPS::File::Sale::FORMAT_RINGTONE,
            'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'emdalbum' => {
        'download' => {
            'product' => RPS::File::Sale::TYPE_ALBUM,
            'format' => RPS::File::Sale::FORMAT_DOWNLOAD,
            'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'downloads' => {
            'product' => RPS::File::Sale::TYPE_ALBUM,
            'format' => RPS::File::Sale::FORMAT_DOWNLOAD,
            'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'emdalbumstreaming' => {
        'stream' => {
            'product' => RPS::File::Sale::TYPE_ALBUM,
            'format' => RPS::File::Sale::FORMAT_STREAM,
            'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'streaming' => {
            'product' => RPS::File::Sale::TYPE_ALBUM,
            'format' => RPS::File::Sale::FORMAT_STREAM,
            'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'emdalbumstreamingstreamingstreaming' => {
        'streaming' => {
            'product' => RPS::File::Sale::TYPE_ALBUM,
            'format' => RPS::File::Sale::FORMAT_STREAM,
            'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'emdtrack' => {
        'download' => {
            'product' => RPS::File::Sale::TYPE_TRACK,
            'format' => RPS::File::Sale::FORMAT_DOWNLOAD,
            'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'downloads' => {
            'product' => RPS::File::Sale::TYPE_TRACK,
            'format' => RPS::File::Sale::FORMAT_STREAM,
            'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'emdtrackstreaming' => {
        'streaming' => {
            'product' => RPS::File::Sale::TYPE_TRACK,
            'format' => RPS::File::Sale::FORMAT_STREAM,
            'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'stream' => {
            'product' => RPS::File::Sale::TYPE_TRACK,
            'format' => RPS::File::Sale::FORMAT_STREAM,
            'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'eringback' => {
        'wireless' => {
            'product' => RPS::File::Sale::TYPE_TRACK,
            'format' => RPS::File::Sale::FORMAT_RINGTONE,
            'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'download' => {
            'product' => RPS::File::Sale::TYPE_TRACK,
            'format' => RPS::File::Sale::FORMAT_RINGTONE,
            'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'evd' => {
        'download' => {
            'product' => RPS::File::Sale::TYPE_TRACK,
            'format' => RPS::File::Sale::FORMAT_DOWNLOAD,
            'media' => RPS::DB::Item::MediaType::kMediaTypeVideo,
        },
        'downloads' => {
            'product' => RPS::File::Sale::TYPE_TRACK,
            'format' => RPS::File::Sale::FORMAT_DOWNLOAD,
            'media' => RPS::DB::Item::MediaType::kMediaTypeVideo,
        },
    },
    'evdstreaming' => {
        'streaming' => {
            'product' => RPS::File::Sale::TYPE_TRACK,
            'format' => RPS::File::Sale::FORMAT_STREAM,
            'media' => RPS::DB::Item::MediaType::kMediaTypeVideo,
        },
        'stream' => {
            'product' => RPS::File::Sale::TYPE_TRACK,
            'format' => RPS::File::Sale::FORMAT_STREAM,
            'media' => RPS::DB::Item::MediaType::kMediaTypeVideo,
        },
    },
    'mobile' => {
        'stream' => {
            'product' => RPS::File::Sale::TYPE_TRACK,
            'format' => RPS::File::Sale::FORMAT_STREAM,
            'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'download' => {
            'product' => RPS::File::Sale::TYPE_TRACK,
            'format' => RPS::File::Sale::FORMAT_DOWNLOAD,
            'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'otherdig' => {
        'stream' => {
            'product' => RPS::File::Sale::TYPE_TRACK,
            'format' => RPS::File::Sale::FORMAT_STREAM,
            'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'download' => {
            'product' => RPS::File::Sale::TYPE_TRACK,
            'format' => RPS::File::Sale::FORMAT_DOWNLOAD,
            'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'web' => {
        'stream' => {
            'product' => RPS::File::Sale::TYPE_TRACK,
            'format' => RPS::File::Sale::FORMAT_STREAM,
            'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'download' => {
            'product' => RPS::File::Sale::TYPE_TRACK,
            'format' => RPS::File::Sale::FORMAT_DOWNLOAD,
            'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'wireless' => {
        'download' => {
            'product' => RPS::File::Sale::TYPE_TRACK,
            'format' => RPS::File::Sale::FORMAT_DOWNLOAD,
            'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'stream' => {
            'product' => RPS::File::Sale::TYPE_TRACK,
            'format' => RPS::File::Sale::FORMAT_STREAM,
            'media' => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
);

sub saleDates {
    my $self = shift;

    my $startDate = $self->_getByFieldName('dateBegin');
    if ($startDate =~ /^\d{5}$/ and $startDate > 38716) {
        $startDate = Spreadsheet::ParseExcel::Utility::ExcelFmt("yyyy-mm-dd", $startDate);    
    }
    
    my $endDate   = $self->_getByFieldName('dateEnd');
    if ($endDate =~ /^\d{5}$/ and $endDate > 38716) {
        $endDate = Spreadsheet::ParseExcel::Utility::ExcelFmt("yyyy-mm-dd", $endDate);    
    }    

    if( $startDate =~ /^(\d{4})-(\d{1,2})-(\d{1,2})$/ )
    {
        $startDate = sprintf("%04d-%02d-%02d", $1, $2, 1);
    }
    if( $endDate =~ /^(\d{4})-(\d{1,2})-(\d{1,2})$/ )
    {
        $endDate = sprintf("%04d-%02d-%02d", $1, $2, Days_in_Month($1, $2) );
    }

    return( $startDate, $endDate );
}

sub productType {
    my $self = shift;

    if( exists $self->_fieldMap->{'productType'} )  # domestic
    {
        my $code = $self->_getByFieldName('productType');

        if( !$code )
        {
            return $self->handleError( "Product type missing", RPS::DB::Item::SaleImportError::kErrorNonqualifying );
        }
        elsif( $code =~ /^(d|p|t|s)$/i )
        {
            return RPS::File::Sale::TYPE_TRACK;
        }
        elsif( $code =~ /^a$/i )
        {
            return RPS::File::Sale::TYPE_ALBUM;
        }
        else
        {
            my $msg = "sheet ". $self->{sheetname} . " line ". $self->linenum . ": ".
                "Invalid product type($code)";
            return $self->handleError( $msg, RPS::DB::Item::SaleImportError::kErrorProductType );
        }
    }
    else
    {
        my $mediaCode = lc $self->_getByFieldName('deliveryType'); # mediaCode
        my $emd       = lc $self->_getByFieldName('deliveryFormat');  # emd
        if( exists $internationalMappings{$mediaCode}{$emd} )
        {
            return $internationalMappings{$mediaCode}{$emd}{product};
        }
        else
        {
            my $msg = "sheet ". $self->{sheetname} . " line ". $self->linenum . ": ".
                "Invalid mediaCode($mediaCode) emd($emd)";
            return $self->handleError( $msg, RPS::DB::Item::SaleImportError::kErrorProductType );
        }
    }
}# productType

sub formatType {
    my $self = shift;

    if( exists $self->_fieldMap->{'formatType'} )  # domestic
    {
        my $code = uc $self->_getByFieldName('formatType');
        if( !$code )
        {
            return $self->handleError( "Income type code missing", RPS::DB::Item::SaleImportError::kErrorNonqualifying );
        }
        elsif( exists $domesticMappings{$code} )
        {
            return $domesticMappings{$code}{format};
        }
        else
        {
            my $msg = "sheet ". $self->{sheetname} . " line ". $self->linenum . ": ".
                "Invalid INCOME_TYPE_CD($code)";
            return $self->handleError( $msg, RPS::DB::Item::SaleImportError::kErrorFormatType );
        }
    }
    else
    {
        my $mediaCode = lc $self->_getByFieldName('deliveryType'); # mediaCode
        my $emd       = lc $self->_getByFieldName('deliveryFormat');  # emd
        if( exists $internationalMappings{$mediaCode}{$emd} )
        {
            return $internationalMappings{$mediaCode}{$emd}{format};
        }
        else
        {
            my $msg = "sheet ". $self->{sheetname} . " line ". $self->linenum . ": ".
                "Invalid mediaCode($mediaCode) emd($emd)";
            return $self->handleError( $msg, RPS::DB::Item::SaleImportError::kErrorFormatType );
        }
    }
}# formatType

sub mediaType {
    my $self = shift;
    if( exists $self->_fieldMap->{'formatType'} )  # domestic
    {
        my $code = uc $self->_getByFieldName('formatType');
        if( !$code )
        {
            return $self->handleError( "Income type code missing", RPS::DB::Item::SaleImportError::kErrorNonqualifying );
        }
        elsif( exists $domesticMappings{$code} )
        {
            return $domesticMappings{$code}{media};
        }
        else
        {
            my $msg = "sheet ". $self->{sheetname} . " line ". $self->linenum . ": ".
                "Invalid INCOME_TYPE_CD($code)";
            return $self->handleError( $msg, RPS::DB::Item::SaleImportError::kErrorMediaType );
        }
    }
    else
    {
        my $mediaCode = lc $self->_getByFieldName('deliveryType'); # mediaCode
        my $emd       = lc $self->_getByFieldName('deliveryFormat');  # emd
        if( exists $internationalMappings{$mediaCode}{$emd} )
        {
            return $internationalMappings{$mediaCode}{$emd}{media};
        }
        else
        {
            my $msg = "sheet ". $self->{sheetname} . " line ". $self->linenum . ": ".
                "Invalid mediaCode($mediaCode) emd($emd)";
            return $self->handleError( $msg, RPS::DB::Item::SaleImportError::kErrorMediaType );
        }
    }
}# mediaType

sub _isValidSaleRecord 
{
    my $self = shift;
    my $dateBegin = $self->_getByFieldName( 'dateBegin' );

    return undef if ( !$dateBegin || '' eq $dateBegin );

    return $self->SUPER::_isValidSaleRecord();
}

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

    if( $self->{sheetname} =~ /^(Domestic|Intl Digital)$/i )
    {
        # We only process the 'Domestic' or 'Intl Digital'
        #
        return $self->RPS::Import::Importer::_processSheet( $sheet, $sheetnum );
    }
}

sub units {
    my $self = shift;
    my $units = $self->SUPER::units();
    my $price = $self->SUPER::price();

    # The 'sign' of the units is driven by the price.
    # If the price is negative, we'll store negative units,
    # regardless of whether the units were positive or negative
    # in the sale file.  Accordingly, the price is always
    # positive.  This ensures that returns are recorded correctly.
    #
    if( defined($price) )
    {
        $units = 1 if (!$units); # coerce units since we don't support zero
        return $price < 0 ? abs($units) * -1 : $units;
    }
    else
    {
        return $units;
    }
}


## MapFace Stuff
sub _mapFaceCompatibleVersions {
    return (31,32);
}

sub _mapFaceServiceID {
    return ('serviceID');
}

sub _mapFaceCountryCode {
    return ('countryCode');
}

sub _mapFaceProductType {
    #         DOM-S          INTL-D            INTL-AI
    return ('productType', 'deliveryType', 'deliveryFormat');
}

sub _mapFaceFormatType {
    #        DOM-AQ          INTL-D           INTL-AI
    return ('formatType', 'deliveryType', 'deliveryFormat');
}

sub _mapFaceMediaType {
    #        DOM-AQ          INTL-D           INTL-AI
    return ('formatType', 'deliveryType', 'deliveryFormat');
}


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