package RPS::Import::ADA::v14;
#
# This importer is similar to v12.pm.  The difference is that the
# international digital sales tab is slightly different in this
# version (the domestic sales tab, however, is the same).
#
use strict;

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

use lib '/app/tools/data_classes/lib';

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 { ( units => qr/UNITS$/ ) }

sub _validateFieldMap { }

sub _fieldMap {

    my $self = shift;

    my $sheetName = $self->_normalizeSheetName( lc $self->{sheetname} );

    my %fieldMaps = (
        'domestic' => {
            label       => 28,    # AC
            serviceID   => 2,     # C
            dateBegin   => 3,     # D
            dateEnd     => 4,     # E
            productType => 17,    # R
            formatType  => 41,    # AP
            artistName  => 7,     # H
            upc         => 20,    # U
            albumName   => 22,    # W
            isrc        => 18,    # S
            trackName   => 9,     # J
            units       => 10,    # K
            price       => 15,    # P
            mediaType   => 17,    # R
        },
        'international' => {
            label       => 0,     # A
            serviceID   => 5,     # F
            countryCode => 7,     # H

            artistName => 1,      # B
            albumName  => 2,      # C
            trackName  => 2,      # C

            isrc => 3,            # D
            upc  => 3,            # D

            units => 12,          # M
            price => 13,          # N
        },
    );

    if ( $fieldMaps{$sheetName} ) {
        return $fieldMaps{$sheetName};
    }
}

sub _unverifiedFieldMap {

    my $self = shift;

    my $sheetName = $self->_normalizeSheetName( lc $self->{sheetname} );

    my %fieldMaps = (
        'domestic' => {
            mediaCode  => 41,    # AP
            streamFlag => 44,    # AS
        },
        'international' => {
            deliveryType   => 9,     # J
            deliveryFormat => 10,    # K
        },
    );

    if ( $fieldMaps{$sheetName} ) {
        return $fieldMaps{$sheetName};
    }
}

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

# International delivery format mappings
#
# $deliveryFormatMap{$deliveryFormat}{$deliveryType}
#
my %deliveryFormatMap = (
    'emastertone' => {
        'download' => {
            product_type => RPS::File::Sale::TYPE_ALBUM,
            format_type  => RPS::File::Sale::FORMAT_RINGTONE,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'wireless' => {
            product_type => RPS::File::Sale::TYPE_TRACK,
            format_type  => RPS::File::Sale::FORMAT_RINGTONE,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'emdalbum' => {
        'download' => {
            product_type => RPS::File::Sale::TYPE_ALBUM,
            format_type  => RPS::File::Sale::FORMAT_DOWNLOAD,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'downloads' => {
            product_type => RPS::File::Sale::TYPE_ALBUM,
            format_type  => RPS::File::Sale::FORMAT_DOWNLOAD,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'emdalbumstreaming' => {
        'stream' => {
            product_type => RPS::File::Sale::TYPE_ALBUM,
            format_type  => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'streaming' => {
            product_type => RPS::File::Sale::TYPE_ALBUM,
            format_type  => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'emdalbumstreamingstreamingstreaming' => {
        'streaming' => {
            product_type => RPS::File::Sale::TYPE_ALBUM,
            format_type  => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'emdtrack' => {
        'download' => {
            product_type => RPS::File::Sale::TYPE_TRACK,
            format_type  => RPS::File::Sale::FORMAT_DOWNLOAD,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'downloads' => {
            product_type => RPS::File::Sale::TYPE_TRACK,
            format_type  => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'emdtrackstreaming' => {
        'stream' => {
            product_type => RPS::File::Sale::TYPE_TRACK,
            format_type  => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'streaming' => {
            product_type => RPS::File::Sale::TYPE_TRACK,
            format_type  => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'eringback' => {
        'download' => {
            product_type => RPS::File::Sale::TYPE_TRACK,
            format_type  => RPS::File::Sale::FORMAT_RINGTONE,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'wireless' => {
            product_type => RPS::File::Sale::TYPE_TRACK,
            format_type  => RPS::File::Sale::FORMAT_RINGTONE,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'evd' => {
        'download' => {
            product_type => RPS::File::Sale::TYPE_TRACK,
            format_type  => RPS::File::Sale::FORMAT_DOWNLOAD,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeVideo,
        },
        'downloads' => {
            product_type => RPS::File::Sale::TYPE_TRACK,
            format_type  => RPS::File::Sale::FORMAT_DOWNLOAD,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeVideo,
        },
    },
    'evdstreaming' => {
        'stream' => {
            product_type => RPS::File::Sale::TYPE_TRACK,
            format_type  => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeVideo,
        },
        'streaming' => {
            product_type => RPS::File::Sale::TYPE_TRACK,
            format_type  => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeVideo,
        },
    },
    'mobile' => {
        'download' => {    # FB2929
            product_type => RPS::File::Sale::TYPE_TRACK,
            format_type  => RPS::File::Sale::FORMAT_DOWNLOAD,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'stream' => {      # FB2929
            product_type => RPS::File::Sale::TYPE_TRACK,
            format_type  => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'otherdig' => {
        'download' => {    # FB2929
            product_type => RPS::File::Sale::TYPE_TRACK,
            format_type  => RPS::File::Sale::FORMAT_DOWNLOAD,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'stream' => {      # FB2929
            product_type => RPS::File::Sale::TYPE_TRACK,
            format_type  => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'stream' => {
        'emdtrackstreaming' => {
            product_type => RPS::File::Sale::TYPE_TRACK,
            format_type  => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'unknown' => {
        'download' => {
            product_type => RPS::File::Sale::TYPE_TRACK,                 # only if ISRC present, album otherwise
            format_type  => RPS::File::Sale::FORMAT_DOWNLOAD,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'usergenmastertone' => {
        'wireless' => {
            product_type => RPS::File::Sale::TYPE_TRACK,
            format_type  => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'web' => {
        'download' => {    # FB2929
            product_type => RPS::File::Sale::TYPE_TRACK,
            format_type  => RPS::File::Sale::FORMAT_DOWNLOAD,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'stream' => {      # FB2929
            product_type => RPS::File::Sale::TYPE_TRACK,
            format_type  => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
    'wireless' => {
        'download' => {    # FB2929
            product_type => RPS::File::Sale::TYPE_TRACK,
            format_type  => RPS::File::Sale::FORMAT_DOWNLOAD,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'stream' => {      # FB2929
            product_type => RPS::File::Sale::TYPE_TRACK,
            format_type  => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
    },
);

# Doing this so that version that inherit from this one can pull stuff out of the hash.
sub _getMediaType {
    my $self = shift;
    my %args = @_;

    my $deliveryType   = $args{deliveryType};
    my $deliveryFormat = $args{deliveryFormat};
    return $deliveryFormatMap{$deliveryFormat}{$deliveryType}{media_type};
}

sub currencyCode { 'USD' }

sub _preProcess {
    my $self = shift;
    my %args = @_;

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

    my $fileName = $args{file}->OrigFileName();
    my ( $dateBegin, $dateEnd ) = $self->_getDatesFromFileName($fileName);
    $self->{_fileDateBegin} = $dateBegin;
    $self->{_fileDateEnd}   = $dateEnd;
}

sub _getDateBegin {
    my $self = shift;

    if ( defined $self->_getByFieldName('dateBegin') ) {
        my $saleDateBegin = _normalizeDate( $self->_getByFieldName('dateBegin') );
        my ( $dateBegin, $dateEnd ) = $self->_getDates( date_begin => $saleDateBegin );
        return $dateBegin;
    } else {
        return $self->{_fileDateBegin};
    }
}

sub _getDateEnd {
    my $self = shift;

    if ( defined $self->_getByFieldName('dateBegin') ) {
        my $saleDateBegin = _normalizeDate( $self->_getByFieldName('dateBegin') );
        my ( $dateBegin, $dateEnd ) = $self->_getDates( date_begin => $saleDateBegin );
        return $dateEnd;
    } else {
        return $self->{_fileDateEnd};
    }
}

sub countryCode {
    my $self = shift;

    if ( defined $self->_getByFieldName('countryCode') ) {
        my $name = $self->_getByFieldName('countryCode');
        return $name;
    } else {
        return 'US';
    }
}

sub formatType {
    my $self = shift;
    my $formatType;

    if ( defined $self->_getByFieldName('mediaCode') ) {
        my $mediaCode = $self->_getByFieldName('mediaCode');
        if ( !$mediaCode ) {
            return $self->handleError( "Media code missing", RPS::DB::Item::SaleImportError::kErrorNonqualifying );
        }

        $formatType = $mediaCodeMap{ uc $mediaCode }->{format_type};
        if ($formatType) {
            return $formatType;
        } else {
            return $self->handleError( "Unknown mediaCode: $mediaCode", RPS::DB::Item::SaleImportError::kErrorFormatType );
        }
    } else {
        my $deliveryType = lc $self->_getByFieldName('deliveryType');
        if ( !$deliveryType ) {
            return $self->handleError( "Delivery type missing", RPS::DB::Item::SaleImportError::kErrorNonqualifying );
        }

        my $deliveryFormat = lc $self->_getByFieldName('deliveryFormat');
        if ( !$deliveryFormat ) {
            return $self->handleError( "Delivery format missing", RPS::DB::Item::SaleImportError::kErrorNonqualifying );
        }

        $formatType = $deliveryFormatMap{$deliveryFormat}{$deliveryType}{format_type};
        if ($formatType) {
            return $formatType;
        } else {
            return $self->handleError( "Unknown deliveryType($deliveryType) deliveryFormat($deliveryFormat)",
                RPS::DB::Item::SaleImportError::kErrorFormatType );
        }
    }
}

sub mediaType {
    my $self = shift;
    my $mediaType;

    if ( defined $self->_getByFieldName('mediaCode') ) {
        my $mediaCode = $self->_getByFieldName('mediaCode');
        if ( !$mediaCode ) {
            return $self->handleError( "Media code missing", RPS::DB::Item::SaleImportError::kErrorNonqualifying );
        }

        $mediaType = $mediaCodeMap{ uc $mediaCode }->{media_type};
        if ($mediaType) {
            return $mediaType;
        } else {
            return $self->handleError( "Unknown mediaCode: $mediaCode", RPS::DB::Item::SaleImportError::kErrorMediaType );
        }
    } else {
        my $deliveryType = lc $self->_getByFieldName('deliveryType');
        if ( !$deliveryType ) {
            return $self->handleError( "Delivery type missing", RPS::DB::Item::SaleImportError::kErrorNonqualifying );
        }

        my $deliveryFormat = lc $self->_getByFieldName('deliveryFormat');
        if ( !$deliveryFormat ) {
            return $self->handleError( "Delivery format missing", RPS::DB::Item::SaleImportError::kErrorNonqualifying );
        }

        $mediaType = $deliveryFormatMap{$deliveryFormat}{$deliveryType}{media_type};
        if ($mediaType) {
            return $mediaType;
        } else {
            return $self->handleError( "Unknown deliveryType($deliveryType) deliveryFormat($deliveryFormat)",
                RPS::DB::Item::SaleImportError::kErrorMediaType );
        }
    }
}

sub productType {
    my $self = shift;
    my $productType;

    if ( defined $self->_getByFieldName('mediaCode') ) {
        $productType = $self->_getByFieldName('productType');

        if ( !$productType ) {
            return $self->handleError( "Product type missing", RPS::DB::Item::SaleImportError::kErrorNonqualifying );
        } elsif ( $productType eq 'D' || $productType eq 'P' || $productType eq 'T' || $productType eq 'S' || $productType eq 'DL' ) {
            $productType = RPS::File::Sale::TYPE_TRACK;
        } elsif ( $productType eq 'A' ) {
            $productType = RPS::File::Sale::TYPE_ALBUM;
        } else {
            return $self->handleError( "Unknown product type: $productType", RPS::DB::Item::SaleImportError::kErrorProductType );
        }
    } else {
        my $deliveryType = lc $self->_getByFieldName('deliveryType');
        if ( !$deliveryType ) {
            return $self->handleError( "Delivery type missing", RPS::DB::Item::SaleImportError::kErrorNonqualifying );
        }

        my $deliveryFormat = lc $self->_getByFieldName('deliveryFormat');
        if ( !$deliveryFormat ) {
            return $self->handleError( "Delivery format missing", RPS::DB::Item::SaleImportError::kErrorNonqualifying );
        }

        $productType = $deliveryFormatMap{$deliveryFormat}{$deliveryType}{product_type};
        if ($productType) {

            # Adding an exception for the unknown.
            if ( $deliveryType =~ /unknown/i && $deliveryFormat =~ /download/i && !$self->isrc() ) {
                return RPS::File::Sale::TYPE_ALBUM;
            } else {
                return $productType;
            }
        } else {
            return $self->handleError( "Unknown deliveryType($deliveryType) deliveryFormat($deliveryFormat)",
                RPS::DB::Item::SaleImportError::kErrorProductType );
        }
    }
}

sub free {
    my $self  = shift;
    my $price = $self->price;
    return ( $price == 0 ) ? 1 : 0;
}

sub price {
    my $self = shift;

    my $price = $self->_getByFieldName('price');

    if ( $price =~ /e-/ ) {

        # Note: the high precision is so that we can capture revenue like .00000000003
        # Effectively we'll store this as a zero since the DB only has 8 digits, but
        # for calculation purposes it'll let us assign a unit to a "zero" revenue line.
        #
        $price = sprintf( "%.18f", $price );    # convert scientific notation to decimal
    }

    if ( $price =~ /^\((\d*\.?\d*)\)$/ ) {
        $price = $1 * -1;
    }

    return $price;
}

sub units {
    my $self = shift;
    my $units = $self->_getByFieldName('units') || return;
    $units =~ s/,//g;
    $units =~ s/\s+//g;
    if ( $units =~ /^\((\d*\.?\d*)\)$/ ) {
        $units = $1 * -1;
    }

    my $price = $self->price;

    # For this importer, We'll follow the sign of the revenue to determine
    # the sign of the units (FB1168).
    #
    if ( $price && $units ) {
        if ( $price < 0 ) {
            $units = 0 - $units if ( $units > 0 );    # price is negative, force negative units
        } else {
            $units = abs($units) if ( $units < 0 );    # price is positive, force positive units
        }
    }

    return $units;
}

sub unitPrice {
    my $self = shift;
    return 0 if ( $self->price == 0 );
    return $self->SUPER::unitPrice();
}

sub isrc {
    my $self = shift;

    my $isrc = $self->_getByFieldName('isrc');

    if ($isrc) {
        $isrc = Common::Util::normalize_isrc($isrc);
        if ( $isrc =~ /^\w/ ) {
            return $isrc;
        }
    }
}

sub upc {
    my $self = shift;

    my $upc = $self->_getByFieldName('upc');

    if ($upc) {
        $upc = Common::Util::normalize_upc($upc);
        if ( $upc =~ /^\d/ ) {
            return $upc;
        }
    }

    # This also catches UPC eq '0', which we don't
    # want either (FBoD15108). Besides, it's always
    # good to return something explicitly.
    return undef;
}

sub albumName {
    my $self      = shift;
    my $isrc      = $self->isrc();
    my $name      = $self->_getByFieldName('albumName');
    my $sheetName = lc $self->{sheetname};

    # On the domestic sheet, album name is always included.
    #
    if ( !$isrc || $sheetName eq 'domestic' ) {
        return $name;
    }
}

sub trackName {
    my $self = shift;
    my $isrc = $self->isrc();
    my $name = $self->_getByFieldName('trackName');
    if ($isrc) {
        return $name;
    }
}

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 _normalizeSheetName {
    my $self  = shift;
    my $sname = shift;
    my $name;

    $name = $sname;
    if ( $sname =~ /domestic digital/i ) {
        $name = "domestic";
    } elsif ( $sname =~ /int\'l digital/i ) {
        $name = "international";
    }

    return $name;
}

sub _normalizeDate {
    my ($dt) = @_;
    my $date = $dt;
    if ( $dt =~ m/^\d{5}$/ ) {
        $date = Spreadsheet::ParseExcel::Utility::ExcelFmt( "yyyy-mm-dd", $dt );
    }
    return $date;
}

sub _getDatesFromFileName {
    my $self = shift;
    my $date = shift;

    my ( $dateBegin, $dateEnd, $month, $year );

    if ( $date =~ m/(january|february|march|april|may|june|july|august|september|october|november|december)[_ ](\d{4})/i ) {
        $month = Decode_Month($1);
        $year  = $2;

        #print STDERR "DEBUG: _getDatesFromFileName: fmonth($1) month($month) year($year)\n";
        $dateBegin = sprintf( "%04d-%02d-%02d", $year, $month, 1 );
        $dateEnd = sprintf( "%04d-%02d-%02d", $year, $month, Days_in_Month( $year, $month ) );
    } elsif ( $date =~ m/([a-z]+)\s*(\d{4})\./i ) {

        $month = Decode_Month($1);
        $year  = $2;

        $dateBegin = sprintf( "%04d-%02d-%02d", $year, $month, 1 );
        $dateEnd = sprintf( "%04d-%02d-%02d", $year, $month, Days_in_Month( $year, $month ) );
    } elsif ( $date =~ m/(\d{4})-(\d{1,2})/ ) {
        $year  = $1;
        $month = $2;

        $dateBegin = sprintf( "%04d-%02d-%02d", $year, $month, 1 );
        $dateEnd = sprintf( "%04d-%02d-%02d", $year, $month, Days_in_Month( $year, $month ) );
    } elsif ( $date =~ m/(\d{2})-(\w{3})/ ) {

        $month = Decode_Month($2);
        $year  = "20" . $1;

        $dateBegin = sprintf( "%04d-%02d-%02d", $year, $month, 1 );
        $dateEnd = sprintf( "%04d-%02d-%02d", $year, $month, Days_in_Month( $year, $month ) );
    } else {
        return undef;
    }

    return ( $dateBegin, $dateEnd );
}

sub _isValidSaleRecord {
    my $self  = shift;
    my $units = $self->units;
    my $price = $self->price;

    return undef if ( !$units && $price && $price < 0 );

    # We're going to skip the tabs we don't care about.
    my $sheetName = $self->_normalizeSheetName( lc $self->{sheetname} );
    return undef if ( $sheetName ne 'domestic' && $sheetName ne 'international' );
    return $self->SUPER::_isValidSaleRecord();
}

## MapFace Stuff

sub _mapFaceServiceID {
    return ( 'serviceID', 'countryCode' );
}

sub _mapFaceCountryCode {
    return ('countryCode');
}

sub _mapFaceProductType {
    return ( 'productType', 'deliveryType', 'deliveryFormat' );
}

sub _mapFaceFormatType {
    return ( 'mediaCode', 'deliveryType', 'deliveryFormat' );
}

sub _mapFaceMediaType {
    return ( 'mediaCode', 'deliveryType', 'deliveryFormat' );
}

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