package RPS::Import::Sony::v47;

use strict;
use warnings;

use lib '/app/tools/rps/lib';
use RPS::Import::ServiceMap;
use Date::Calc qw(Days_in_Month Add_Delta_Days Decode_Month);

use parent qw/RPS::Import::MapFaceBase RPS::Import::ImporterMixed/;

sub physical { 0 }

sub _fieldMapExtended {
    {
        digital => {
            option1 => {    # has two additional field date_begin and date_end
                serviceID       => 'I',
                dateBegin       => 'J',
                dateEnd         => 'K',
                productType     => 'F',
                formatType      => 'H',
                clientProductID => 'B',
                artistName      => 'A',
                albumName       => 'C',
                isrc            => 'D',
                trackName       => 'C',
                units           => 'M',
                price           => 'L',
                mediaType       => 'F',
            },
            option2 => {    # doesn't contain date_begin and date_end fieldss
                serviceID       => 'I',
                dateBegin       => 'A4',
                productType     => 'F',
                formatType      => 'H',
                clientProductID => 'B',
                artistName      => 'A',
                albumName       => 'C',
                isrc            => 'D',
                trackName       => 'C',
                units           => 'K',
                price           => 'J',
                mediaType       => 'F',
            },
        }
    };
}

sub _unverifiedFieldMapExtended { {} }

sub _headerIdentifierExtended {
    {
        digital => {
            option1 => {    # should be first as has extra fields
                dateBegin => 'Sales Reporting Date: From',
            },
            option2 => {
                productType => 'Product Type',
            },
        }
    };
}

my %monthes = (
    jan => 1, feb => 2, mar => 3, apr => 4,  may => 5,  jun => 6,
    jul => 7, aug => 8, sep => 9, oct => 10, nov => 11, dec => 12,
);

my %mapProductMedia = (
    'digital audio bundle' => {
        product_type => RPS::File::Sale::TYPE_ALBUM,
        media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'digital audio extended play' => {
        product_type => RPS::File::Sale::TYPE_ALBUM,
        media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'digital audio longplay' => {
        product_type => RPS::File::Sale::TYPE_ALBUM,
        media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'digital combo longplay' => {
        product_type => RPS::File::Sale::TYPE_ALBUM,
        media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'digital audio ep' => {
        product_type => RPS::File::Sale::TYPE_ALBUM,
        media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'digital combo bundle' => {
        product_type => RPS::File::Sale::TYPE_ALBUM,
        media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'digital audio track' => {
        product_type => RPS::File::Sale::TYPE_TRACK,
        media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'digital video track' => {
        product_type => RPS::File::Sale::TYPE_TRACK,
        media_type   => RPS::DB::Item::MediaType::kMediaTypeVideo,
    },
    'mastertone' => {
        product_type => RPS::File::Sale::TYPE_TRACK,
        media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'ringback tone' => {
        product_type => RPS::File::Sale::TYPE_TRACK,
        media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
);

my %mapFormat = (
    'online permanent download' => {
        format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
    },
    'mobile permanent download' => {
        format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
    },
    'kiosk' => {
        format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
    },
    'other' => {
        format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
    },
    'metadata earnings' => {
        format_type => RPS::File::Sale::FORMAT_STREAM,
    },
    'locker' => {
        format_type => RPS::File::Sale::FORMAT_STREAM,
    },
    'locker streaming' => {
        format_type => RPS::File::Sale::FORMAT_STREAM,
    },
    'mobile stream (ad supported)' => {
        format_type => RPS::File::Sale::FORMAT_STREAM,
    },
    'mobile stream (non-ad supported)' => {
        format_type => RPS::File::Sale::FORMAT_STREAM,
    },
    'mobile tethered (non-ad supported)' => {
        format_type => RPS::File::Sale::FORMAT_STREAM,
    },
    'mobile tethered (ad supported)' => {
        format_type => RPS::File::Sale::FORMAT_STREAM,
    },
    'multi-platform stream (non-ad supported)' => {
        format_type => RPS::File::Sale::FORMAT_STREAM,
    },
    'multi-platform stream (ad supported)' => {
        format_type => RPS::File::Sale::FORMAT_STREAM,
    },
    'online stream (ad supported)' => {
        format_type => RPS::File::Sale::FORMAT_STREAM,
    },
    'online stream (non-ad supported)' => {
        format_type => RPS::File::Sale::FORMAT_STREAM,
    },
    'online tethered (ad supported)' => {
        format_type => RPS::File::Sale::FORMAT_STREAM,
    },
    'online tethered (non-ad supported)' => {
        format_type => RPS::File::Sale::FORMAT_STREAM,
    },
    'ephemeral' => {
        format_type => RPS::File::Sale::FORMAT_EPHEMERAL,
    },
    'mobile ephemeral' => {
        format_type => RPS::File::Sale::FORMAT_EPHEMERAL,
    },
    'jukebox' => {
        format_type => RPS::File::Sale::FORMAT_JUKEBOX,
    },
    'mobile webcasting' => {
        format_type => RPS::File::Sale::FORMAT_PERFORMANCE,
    },
    'online audio track broadcast webcasting' => {
        format_type => RPS::File::Sale::FORMAT_PERFORMANCE,
    },
    'mobile subscription permanent' => {
        format_type => RPS::File::Sale::FORMAT_TETHERED,
    },
    'multi-platform tethered (non-ad supporte' => {
        format_type => RPS::File::Sale::FORMAT_TETHERED,
    },
);

my %allowedSheets = (
    'pandora streams'                    => 1,
    'digital sales - streams'            => 1,
    'digital sales-mobile&nonstream'     => 1,
    'digital sales-mobile&amp;nonstream' => 1,
    'digital sales - perm downloads'     => 1,
);

sub _getServiceID {
    my ($self, $service) = @_;

    return Client::Service::DSP_YOUTUBE if $service =~ /^vevo - youtube streams/i;

    return Client::Service::DSP_AMAZON              if $service =~ /^amazon/i;
    return Client::Service::DSP_APPLE_MUSIC         if $service =~ /^apple/i;
    return Client::Service::DSP_CHRISTIANBOOK       if $service =~ /^christian book/i;
    return Client::Service::DSP_GOOGLE              if $service =~ /^google/i;
    return Client::Service::DSP_MEDIANET            if $service =~ /^medianet/i;
    return Client::Service::DSP_NEUROTICMEDIA       if $service =~ /^neurotic/i;
    return Client::Service::DSP_PANDORA             if $service =~ /^pandora/i;
    return Client::Service::DSP_VERVELIFE           if $service =~ /^vervelife/i;
    return Client::Service::DSP_VEVO                if $service =~ /^vevo/i;
    return Client::Service::DSP_YOUTUBE             if $service =~ /^youtube/i;
    return Client::Service::DSP_ACOUSTIC_SOUNDS_INC if $service =~ /^acoustic sounds/i;
}

sub countryCode  { 'US' }
sub currencyCode { 'USD' }

sub saleDates {
    my $self = shift;

    my $beginDate = lc( $self->_getByFieldName('dateBegin') || '' );

    # "APRIL 30, 2020"
    if ( $beginDate =~ m/^([a-zA-Z]{3,9}) (\d{1,2}), (\d{4})$/ ) {
        my $month = $monthes{ substr( $1, 0, 3 ) } if exists $monthes{ substr( $1, 0, 3 ) };
        return $self->_getDates( date_begin => sprintf( "%04d-%02d-%02d", $3, $month, 1 ) )
    }

    # alternative header MM/DD/YYY
    if ( my $endDate = $self->_getByFieldName('dateEnd') ) {
        my ($bm, $bd, $by) = $beginDate =~ /^(\d{1,2})[\/.-](\d{1,2})[\/.-](\d{4})$/;
        my ($em, $ed, $ey) = $endDate   =~ /^(\d{1,2})[\/.-](\d{1,2})[\/.-](\d{4})$/;
        if ( $em > 12 ) {
            ($bm, $bd) = ($bd, $bm);
            ($em, $ed) = ($ed, $em);
        }
        return $self->_getDates(
            date_begin => sprintf("%04d-%02d-%02d", $by, $bm, $bd),
            date_end   => sprintf("%04d-%02d-%02d", $ey, $em, $ed)
        );
    }

    $self->fail("Unable to determine dateBegin from: '$beginDate'");
}

sub serviceID {
    my $self = shift;

    my $service = lc( $self->_getByFieldName('serviceID') || '' );
    my $serviceID = $self->getServiceID($service) || $RPS::Import::ServiceMap::SERVICE_ALIASES{$service} || $self->_getServiceID($service);
    return $serviceID if $serviceID;

    $self->handleError( "Unknown service: '$service'", RPS::DB::Item::SaleImportError::kErrorService );
}

sub productType {
    my $self = shift;

    my $type = lc( $self->_getByFieldName('productType') || '' );

    if ( exists $mapProductMedia{$type} ) {
        return $mapProductMedia{$type}{product_type};
    }

    $self->handleError( "Unknown product type: '$type'", RPS::DB::Item::SaleImportError::kErrorProductType );
}

sub clientProductID {
    my $self = shift;

    return if $self->sheetname =~ /^Pandora Streams$/;

    my $id = $self->_getByFieldName('clientProductID') || '';
    return $id;
}

sub mediaType {
    my $self = shift;

    my $type = lc( $self->_getByFieldName('mediaType') || '' );

    if ( exists $mapProductMedia{$type} ) {
        return $mapProductMedia{$type}{media_type};
    }

    $self->handleError( "Unknown media_type: '$type'", RPS::DB::Item::SaleImportError::kErrorMediaType );
}

sub formatType {
    my $self = shift;

    my $type = lc( $self->_getByFieldName('formatType') || '' );

    # additional rules
    if ( $self->sheetname =~ /^Digital Sales\-Mobile&(?:amp;)?NonStream$/i ) {
        return RPS::File::Sale::FORMAT_RINGTONE if $self->_getByFieldName('productType') =~ /^'?Mastertone$/i;
    }

    if ( $self->sheetname =~ /^Pandora Streams$/i && $type =~ /^Online Audio Track Broadcast Webcasting$/i ) {
        return RPS::File::Sale::FORMAT_EPHEMERAL;
    }

    if ( $self->serviceID == Client::Service::DSP_PANDORA && $type =~ /^online stream \(ad supported\)$/i) {
        return RPS::File::Sale::FORMAT_PERFORMANCE;
    }

    # the common mapping
    if ( exists $mapFormat{$type} ) {
        return $mapFormat{$type}{format_type};
    }

    $self->handleError( "Unable to determine format type: '$type'", RPS::DB::Item::SaleImportError::kErrorFormatType );
}

sub albumName {
    my $self = shift;

    my $name = $self->_getByFieldName('albumName') || '';
    return $name if $self->productType eq RPS::File::Sale::TYPE_ALBUM;
}

sub trackName {
    my $self = shift;

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

sub price     { abs( shift->_getByFieldName('price') || 0 ) }
sub unitPrice { abs shift->SUPER::unitPrice }
sub units {
    my $self = shift;

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

    if ( $price > 0 ) {
        $units = $units ? abs($units) : 1;
    } elsif ( $price < 0 ) {
       $units = $units ? -1 * abs($units) : -1;
    }

    return $units;
}

sub _isValidSaleRecord {
    my $self = shift;

    return 1 if ( $self->price || $self->units ) && $self->isrc;
    return;
}

sub _processSheet {
    my ( $self, $sheet, $sheetnum ) = @_;

    if ( !exists $allowedSheets{ lc $self->sheetname } ) {
        $self->fail( "Encountered unrecognized sheet '" . $self->{sheetname} . "'" );
    } else {
        my $headerFound = $self->SUPER::_processSheet( $sheet, $sheetnum );
        if ( !$headerFound ) {
            $self->fail( "Unable to find header for '$self->{sheetname}' sheet" );
        }
    }

    return 1;
}

sub _mapFaceProductType { 'productType' }
sub _mapFaceServiceID   { 'serviceID' }
sub _mapFaceCountryCode { 'countryCode' }
sub _mapFaceFormatType  { 'formatType' }
sub _mapFaceMediaType   { 'mediaType' }

1;
