package RPS::Import::Universal::v72;

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 'RPS::Import::ImporterMixed';

sub physical { 2 }

sub _fieldMapExtended {
    {
        digital => {
            option1 => {    # Digital Sales
                labelName   => 'B',
                serviceID   => 'D',
                dateBegin   => 'O1',
                dateEnd     => 'O1',
                productType => 'F',
                formatType  => 'C',
                upc         => 'I',
                albumName   => 'H',
                isrc        => 'N',
                trackName   => 'K',
                units       => 'P',
                price       => 'O',
                mediaType   => 'C',
            }
        }
    }
}

sub _unverifiedFieldMapExtended {
    {
        digital => {
            option1 => {   # Digital Sales
                _albumArtist => 'G',
                _trackArtist => 'J',
                _salesType   => 'E',
            }
        }
    }
}

sub _headerIdentifierExtended {
    {
        digital => {
            option1 => {    # Digital
                productType => 'Sold As',
            }
        }
    }
}

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,
);

my %mapping = (
    'digital_sales' => {
        countryCode  => 'US',
	    currencyCode => 'USD',
        productType  => {
            'complete album' => RPS::File::Sale::TYPE_ALBUM,
            'track'          => RPS::File::Sale::TYPE_TRACK,
        },
        types => {
            'ad supported streams' => {
                formatType => RPS::File::Sale::FORMAT_STREAM,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'conditional mastertone' => {
                formatType => RPS::File::Sale::FORMAT_STREAM,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'ephemeral plays' => {
                formatType => RPS::File::Sale::FORMAT_STREAM,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'fixed plays' => {
                formatType => RPS::File::Sale::FORMAT_STREAM,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'jukebox' => {
                formatType => RPS::File::Sale::FORMAT_JUKEBOX,
	            mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'kiosk' => {
                formatType => RPS::File::Sale::FORMAT_JUKEBOX,
	            mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'internet broadcast radio' => {
                formatType => RPS::File::Sale::FORMAT_STREAM,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'mobile audio streams' => {
                formatType => RPS::File::Sale::FORMAT_STREAM,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'ota permanent downloads' => {
                formatType => RPS::File::Sale::FORMAT_DOWNLOAD,
	            mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'permanent downloads' => {
                formatType => RPS::File::Sale::FORMAT_DOWNLOAD,
	            mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'portable sub client plays' => {
                formatType => RPS::File::Sale::FORMAT_STREAM,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'portable sub device plays' => {
                formatType => RPS::File::Sale::FORMAT_STREAM,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'portable sub programmed plays' => {
                formatType => RPS::File::Sale::FORMAT_STREAM,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'portable sub streams' => {
                formatType => RPS::File::Sale::FORMAT_STREAM,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'portable sub video dvc plays' => {
                formatType => RPS::File::Sale::FORMAT_STREAM,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeVideo,
            },
            'programmed streaming' => {
                formatType => RPS::File::Sale::FORMAT_STREAM,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'programmed streaming (non-royalty bearing)' => {
                formatType => RPS::File::Sale::FORMAT_STREAM,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'programmed streaming (soundexchange administered)' => {
                formatType => RPS::File::Sale::FORMAT_PERFORMANCE,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'ringbacks' => {
                formatType => RPS::File::Sale::FORMAT_RINGTONE,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'standard mobile ringsounds' => {
                formatType => RPS::File::Sale::FORMAT_RINGTONE,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'streams' => {
                formatType => RPS::File::Sale::FORMAT_STREAM,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'subscription limited catalog' => {
                formatType => RPS::File::Sale::FORMAT_STREAM,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'subscription ota permanent downloads (audio)' => {
                formatType => RPS::File::Sale::FORMAT_DOWNLOAD,
	            mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'subscription programmed streaming' => {
                formatType => RPS::File::Sale::FORMAT_STREAM,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'sub user generated streams (umg audio)' => {
                formatType => RPS::File::Sale::FORMAT_STREAM,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'tethered/conditional downloads' => {
                formatType => RPS::File::Sale::FORMAT_TETHERED,
	            mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'user generated streams (umg audio / user video)' => {
                formatType => RPS::File::Sale::FORMAT_STREAM,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'video downloads' => {
                formatType => RPS::File::Sale::FORMAT_DOWNLOAD,
	            mediaType  => RPS::DB::Item::MediaType::kMediaTypeVideo,
            },
            'video fixed play' => {
                formatType => RPS::File::Sale::FORMAT_STREAM,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeVideo,
            },
            'video streams' => {
                formatType => RPS::File::Sale::FORMAT_STREAM,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeVideo,
            },
            'allocation audio streams true up' => {
                formatType => RPS::File::Sale::FORMAT_STREAM,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
            'icloud channel' => {
                formatType => RPS::File::Sale::FORMAT_STREAM,
                mediaType  => RPS::DB::Item::MediaType::kMediaTypeAudio,
            },
        },
    },
);

sub _processHeader {
    my ($self, %args) = @_;

    if ( $self->{_dateBegin} && $self->{_dateEnd} ) {
        return $self->{_dateBegin}, $self->{_dateEnd};
    }

    ($self->{_dateBegin}, $self->{_dateEnd}) = $self->_getPeriod();

    return 1;
}

sub _getPeriod {
    my $self = shift;

    my $dt = $self->_getByFieldName('dateBegin');
    if ( $dt =~ /revenue umg \w{2,3} \d{2} \((\w{3,9})\s*(\d{2})\)?/i ) {

        # if it's the whole month name, we need to strip off the first 3 chars
        my $_month = lc( substr( $1, 0, 3 ) );
        my $year = $2;

        my $month = $months{$_month};
        $year += 2000;

        my $sdate = sprintf( "%04d-%02d-01", $year, $month );
        my $edate = sprintf( "%04d-%02d-%02d", $year, $month, Days_in_Month( $year, $month ) );
        return ($sdate, $edate);
    }
}

sub saleDates {
    my $self = shift;

    return ($self->{_dateBegin}, $self->{_dateEnd}) if $self->{_dateBegin};

    $self->fail("Unable to determine sale period.");
}

sub serviceID {
    my $self = shift;

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

    $self->fail("Unable to determine service from '$service'.");
}

sub countryCode {
    my $self = shift;

    if ( exists $mapping{digital_sales}{countryCode} && exists $mapping{digital_sales}{countryCode} ) {
        return $mapping{digital_sales}{countryCode};
    }

    $self->fail("Unable to determine country code.");
}

sub currencyCode {
    my $self = shift;

    if ( exists $mapping{digital_sales}{currencyCode} && exists $mapping{digital_sales}{currencyCode} ) {
        return $mapping{digital_sales}{currencyCode};
    }

    $self->fail("Unable to determine country code.");
}

sub productType {
    my $self = shift;

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

    return RPS::File::Sale::TYPE_TRACK if $type eq 'not applicable' && $isrc;

    if ( exists $mapping{digital_sales}{productType}{$type} && $mapping{digital_sales}{productType}{$type} ) {
        return $mapping{digital_sales}{productType}{$type};
    }

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

sub formatType {
    my $self = shift;

    my $type = lc( $self->_getByFieldName('formatType') || '' );         # C
    my $service = $self->_getByFieldName('serviceID')  || '';            # D
    my $salesType = lc( $self->_getByFieldName('_salesType') || '' );    # E

    if ( $type eq 'gift card - unredeemed non-artist specific' && $salesType eq 'user generated streams' ) {
        return RPS::File::Sale::FORMAT_STREAM;
    }

    if ( exists $mapping{digital_sales}{types}{$type}{formatType} && $mapping{digital_sales}{types}{$type}{formatType} ) {
        return $mapping{digital_sales}{types}{$type}{formatType};
    }

    return RPS::File::Sale::FORMAT_STREAM if ($service =~ /^Soundtrack Your Brand$/i && $type =~ /^Not Applicable$/i);

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

sub mediaType {
    my $self = shift;

    my $type = lc( $self->_getByFieldName('mediaType') || '' );         # C
    my $service = $self->_getByFieldName('serviceID') || '';            # D
    my $salesType = lc( $self->_getByFieldName('_salesType') || '' );   # E

    if ( $type eq 'gift card - unredeemed non-artist specific' && $salesType eq 'user generated streams' ) {
        return RPS::DB::Item::MediaType::kMediaTypeAudio;
    }

    if ( $service =~ /^Soundtrack Your Brand$/i && $type =~ /^Not Applicable$/i ) {
        return RPS::DB::Item::MediaType::kMediaTypeAudio;
    }

    if ( exists $mapping{digital_sales}{types}{$type}{mediaType} && $mapping{digital_sales}{types}{$type}{mediaType} ) {
        return $mapping{digital_sales}{types}{$type}{mediaType};
    }

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

sub artistName {
    my $self = shift;

    return $self->productType eq RPS::File::Sale::TYPE_ALBUM
        ? $self->_getByFieldName('_albumArtist')
        : $self->_getByFieldName('_trackArtist');
}

sub upc {
    my $self = shift;

    my $upc = $self->_getByFieldName('upc') || '';
    $upc =~ s/^(?:00)?(.*)$/$1/;

    return $upc;
}

sub isrc {
    my $self = shift;

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

    return $self->productType eq RPS::File::Sale::TYPE_TRACK ? $isrc : undef;
}

sub trackName {
    my $self = shift;

    my $trackName = $self->_getByFieldName('trackName') || '';

    return $self->productType eq RPS::File::Sale::TYPE_TRACK ? $trackName : undef;
}

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;

    my $upc = $self->_getByFieldName('upc') || '';
    # skip multiline header
    return if $upc =~ /UPC/i;

    return ( $self->_getByFieldName('albumName') || $self->_getByFieldName('artistName') )
        && ( $self->price || $self->units );
}

1;
