package RPS::Import::ADA::v22;

use strict;
use warnings;

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

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

sub _fieldMap {
    {
        labelName        => 'A',
        dateBegin        => 'L',
        serviceID        => 'M',
        countryCode      => 'O',
        productType      => 'G',
        serviceProductID => 'K',
        clientProductID  => 'C',
        artistName       => 'E',
        upc              => 'H',
        albumName        => 'D',
        isrc             => 'I',
        trackName        => 'F',
        units            => 'T',
        price            => 'Y',
    };
}

sub _unverifiedFieldMap {
    {
        deliveryType   => 'P',
        deliveryFormat => 'Q',
        releaseType    => 'G',
        vendor         => 'M',
    };
}

sub _headerIdentifier { isrc => 'ISRC' }

my %productTypeMap = (
    'album'                            => RPS::File::Sale::TYPE_ALBUM,
    'boxed set'                        => RPS::File::Sale::TYPE_ALBUM,
    'digital boxed set (mixed format)' => RPS::File::Sale::TYPE_ALBUM,
    'digital download (2 components)'  => RPS::File::Sale::TYPE_ALBUM,
    'digital download (3 components)'  => RPS::File::Sale::TYPE_ALBUM,
    'digital download (album)'         => RPS::File::Sale::TYPE_ALBUM,
    'digital download (single)'        => RPS::File::Sale::TYPE_ALBUM,
    'ep'                               => RPS::File::Sale::TYPE_ALBUM,
    'single'                           => RPS::File::Sale::TYPE_ALBUM,
    'ringtone'                         => RPS::File::Sale::TYPE_TRACK,
    'track'                            => RPS::File::Sale::TYPE_TRACK,
    'track (step)'                     => RPS::File::Sale::TYPE_TRACK,
    'video'                            => RPS::File::Sale::TYPE_TRACK,
    'video single'                     => RPS::File::Sale::TYPE_TRACK,
);

#  the two last hash's keys can have a dedicated names:
# - _empty_      -- an only empty value
# - _no_matter_  -- a cell can contain any value including 'empty'
# deliveryType => deliveryFormat => releaseType => format_type|media_type
my %formatMediaMap = (
    'emastertone' => {
        'wireless' => {
            '_no_matter_' => {
                format_type => RPS::File::Sale::FORMAT_RINGTONE,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
        },
        'download' => {
            '_no_matter_' => {
                format_type => RPS::File::Sale::FORMAT_RINGTONE,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
        },
    },
    'emdalbum' => {
        'downloads' => {
            '_no_matter_' => {
                format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
        },
        'download' => {
            '_no_matter_' => {
                format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
        },
    },
    'emdalbumstreaming' => {
        'streaming' => {
            '_no_matter_' => {
                format_type => RPS::File::Sale::FORMAT_STREAM,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
        },
        'stream' => {
            '_no_matter_' => {
                format_type => RPS::File::Sale::FORMAT_STREAM,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
        }
    },
    'emdtrack' => {
        'downloads' => {
            '_no_matter_' => {
                format_type => RPS::File::Sale::FORMAT_STREAM,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
        },
        'download' => {
            '_no_matter_' => {
                format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
        },
    },
    'emdtrackstreaming' => {
        'streaming' => {
            '_no_matter_' => {
                format_type => RPS::File::Sale::FORMAT_STREAM,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
        },
        'stream' => {
            '_no_matter_' => {
                format_type => RPS::File::Sale::FORMAT_STREAM,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
        },
    },
    'eringback' => {
        'wireless' => {
            '_no_matter_' => {
                format_type => RPS::File::Sale::FORMAT_RINGTONE,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
        },
        'download' => {
            '_no_matter_' => {
                format_type => RPS::File::Sale::FORMAT_RINGTONE,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
        },
    },
    'evd' => {
        'downloads' => {
            '_no_matter_' => {
                format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeVideo,
            },
        },
        'download' => {
            '_no_matter_' => {
                format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeVideo,
            },
        },
    },
    'evdstreaming' => {
        'streaming' => {
            '_no_matter_' => {
                format_type => RPS::File::Sale::FORMAT_STREAM,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeVideo,
            },
        },
        'stream' => {
            '_no_matter_' => {
                format_type => RPS::File::Sale::FORMAT_STREAM,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeVideo,
            },
        },
    },
    'mobile' => {
        'stream' => {
            '_no_matter_' => {
                format_type => RPS::File::Sale::FORMAT_STREAM,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
        },
        'download' => {
            '_no_matter_' => {
                format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
        },
    },
    'otherdig' => {
        'stream' => {
            'track' => {
                format_type => RPS::File::Sale::FORMAT_STREAM,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'track (step)' => {
                format_type => RPS::File::Sale::FORMAT_STREAM,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'video single' => {
                format_type => RPS::File::Sale::FORMAT_STREAM,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeVideo,
            },
        },
        'download' => {
            'track' => {
                format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'album' => {
                format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'ringtone' => {
                format_type => RPS::File::Sale::FORMAT_RINGTONE,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
        },
    },
    'stream' => {
        'emdtrackstreaming' => {
            '_no_matter_' => {
                format_type => RPS::File::Sale::FORMAT_STREAM,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
        },
    },
    'web' => {
        '_no_matter_' => {
            'track (step)' => {
                format_type => RPS::File::Sale::FORMAT_STREAM,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'video single' => {
                format_type => RPS::File::Sale::FORMAT_STREAM,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeVideo,
            },
        },
        'stream' => {
            'track' => {
                format_type => RPS::File::Sale::FORMAT_STREAM,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'track (step)' => {
                format_type => RPS::File::Sale::FORMAT_STREAM,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'video single' => {
                format_type => RPS::File::Sale::FORMAT_STREAM,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeVideo,
            },
            '_empty_' => {
                format_type => RPS::File::Sale::FORMAT_STREAM,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeVideo,
            }
        },
        'download' => {
            'track' => {
                format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'album' => {
                format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'ep' => {
                format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'ringtone' => {
                format_type => RPS::File::Sale::FORMAT_RINGTONE,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'video' => {
                format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeVideo,
            },
            'track (step)' => {
                format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
        },
        'broadcast income' => {
            'track (step)' => {
                format_type => RPS::File::Sale::FORMAT_PERFORMANCE,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
        },
    },
    'wireless' => {
        'download' => {
            'track' => {
                format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'album' => {
                format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'ep' => {
                format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'ringtone' => {
                format_type => RPS::File::Sale::FORMAT_RINGTONE,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
        },
        'stream' => {
            'track' => {
                format_type => RPS::File::Sale::FORMAT_STREAM,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'album' => {
                format_type => RPS::File::Sale::FORMAT_STREAM,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'video' => {
                format_type => RPS::File::Sale::FORMAT_STREAM,
                media_type  => RPS::DB::Item::MediaType::kMediaTypeVideo,
            },
        },
    },
);

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

sub currencyCode {
    return $_[0]->filename =~ /[\s-]USD\..+$/i ? 'USD' : 'GBP';
}

sub saleDates {
    my $self = shift;

    my $date = $self->_getByFieldName('dateBegin') || '';
    my ($year, $month);

    ($year, $month) = ($1, $2) if ($date =~ /^(\d{4})-(\d{2})-(\d{2})$/); # YYYY-MM-DD
    ($year, $month) = ($1, $2) if ($date =~ /^(\d{4})[- ]?(\d{2})$/); # YYYY-MM
    ($year, $month) = ("20".$1, $months{lc($2)}) if ($date =~ /^(\d{2})-(\w{3})$/); # YY-MMM
    ($year, $month) = ($2, $1) if ($date =~ /^(\d{2})\/\d{2}\/(\d{4})$/); # MM/DD/YYYY

    $self->fail("Cannot parse date: $date") unless ($year && $month);

    my $start = sprintf("%04d-%02d-%02d", $year, $month, 1);
    my $end = sprintf("%04d-%02d-%02d", $year, $month, Days_in_Month( $year, $month ));

    return ($start, $end);
}

sub serviceID {
    my $self = shift;

    my $service = lc( $self->_getByFieldName('serviceID') || '' );

    return Client::Service::DSP_ADA if $service =~ /^unknown$/;
    return Client::Service::DSP_SOUNDEXCHANGE if $service =~ /Sound Exchange/i;

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

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

sub productType {
    my $self = shift;

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

    # exception RSD-3195
    return RPS::File::Sale::TYPE_TRACK if $isrc;

    return $productTypeMap{$type} if exists $productTypeMap{$type};

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

sub trackName {
    my $self = shift;

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

    return;
}

sub formatType {
    my $self = shift;

    my ($formatType, undef) = $self->_getFormatMediaTypes();
    return $formatType if $formatType;

    my $deliveryType   = $self->_getByFieldName('deliveryType')   // '';
    my $deliveryFormat = $self->_getByFieldName('deliveryFormat') // '';
    my $releaseType    = $self->_getByFieldName('releaseType')    // '';

    $self->fail("Delivery Format can't be blank.") if $deliveryFormat eq '';

    return $self->handleError(
        "Unknown format type: '$deliveryType' <=> '$deliveryFormat' <=> '$releaseType'",
        RPS::DB::Item::SaleImportError::kErrorFormatType
    );
}

sub mediaType {
    my $self = shift;

    my (undef, $mediaType) = $self->_getFormatMediaTypes();
    return $mediaType if $mediaType;

    my $deliveryType   = $self->_getByFieldName('deliveryType')   // '';
    my $deliveryFormat = $self->_getByFieldName('deliveryFormat') // '';
    my $releaseType    = $self->_getByFieldName('releaseType')    // '';

    $self->fail("Delivery Format can't be blank.") if $deliveryFormat eq '';

    return $self->handleError(
        "Unknown media type: '$deliveryType' <=> '$deliveryFormat' <=> '$releaseType'",
        RPS::DB::Item::SaleImportError::kErrorMediaType
    );
}

sub _getFormatMediaTypes {
    my $self = shift;

    my $deliveryType   = lc( $self->_getByFieldName('deliveryType')   || '_empty_' );
    my $deliveryFormat = lc( $self->_getByFieldName('deliveryFormat') || '_empty_' );
    my $releaseType    = lc( $self->_getByFieldName('releaseType')    || '_empty_' );
    my $vendor         = lc( $self->_getByFieldName('vendor')         || '' );

    my ($formatType, $mediaType);
    # 1 - all three keys are filled or '_empty_'
    if (
           exists $formatMediaMap{$deliveryType}
        && exists $formatMediaMap{$deliveryType}{$deliveryFormat}
        && exists $formatMediaMap{$deliveryType}{$deliveryFormat}{$releaseType}
    ) {
        $formatType = $formatMediaMap{$deliveryType}{$deliveryFormat}{$releaseType}{format_type};
        $mediaType  = $formatMediaMap{$deliveryType}{$deliveryFormat}{$releaseType}{media_type};
    }
    # 2 - the second key = '_no_matter_'
    elsif (
           exists $formatMediaMap{$deliveryType}
        && exists $formatMediaMap{$deliveryType}{_no_matter_}
        && exists $formatMediaMap{$deliveryType}{_no_matter_}{$releaseType}
    ) {
        $formatType = $formatMediaMap{$deliveryType}{_no_matter_}{$releaseType}{format_type};
        $mediaType  = $formatMediaMap{$deliveryType}{_no_matter_}{$releaseType}{media_type};
    }
    # 3 - the third key = '_no_matter_'
    elsif (
           exists $formatMediaMap{$deliveryType}
        && exists $formatMediaMap{$deliveryType}{$deliveryFormat}
        && exists $formatMediaMap{$deliveryType}{$deliveryFormat}{_no_matter_}
    ) {
        $formatType = $formatMediaMap{$deliveryType}{$deliveryFormat}{_no_matter_}{format_type};
        $mediaType  = $formatMediaMap{$deliveryType}{$deliveryFormat}{_no_matter_}{media_type};
    }

    # exception RSD-2871
    if ( $deliveryType =~ /^web$/i && $deliveryFormat =~ /^stream$/i && $vendor =~ /vevo/i ) {
        $mediaType = RPS::DB::Item::MediaType::kMediaTypeVideo;
    }

    # exception RSD-6485, RSD-8929
    if ( $vendor =~ /(?:Pandora Radio-Non Royalty|Sound Exchange)/i ) {
        $formatType = RPS::File::Sale::FORMAT_PERFORMANCE;
    }

    # exception RSD-11782
    if ( $vendor =~ /^Sound Exchange - Sound Exchange DMCA Ephemeral/i ) {
        $formatType = RPS::File::Sale::FORMAT_EPHEMERAL;
    }
    if ($vendor =~ /^Sound Exchange - Sound Exchange DMCA NonRoyalty/i ) {
        $formatType = RPS::File::Sale::FORMAT_NON_EPHEMERAL;
    }

    return $formatType, $mediaType;
}

sub price     { sprintf( "%.8f", 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 _mapFaceCompatibleVersions { 22 }
sub _mapFaceServiceID          { 'serviceID' }
sub _mapFaceCountryCode        { 'countryCode' }
sub _mapFaceProductType        { 'productType' }
sub _mapFaceFormatType         { 'deliveryType', 'deliveryFormat', 'releaseType' }
sub _mapFaceMediaType          { 'deliveryType', 'deliveryFormat', 'releaseType' }

sub _isValidSaleRecord {
    my $self = shift;
    return defined $self->units && defined $self->price && ( $self->_getByFieldName('upc') || $self->_getByFieldName('isrc') );
}


1;
