#---------------------------------------------------------------
# ____                   _ _         ____  _
#|  _ \ ___  _   _  __ _| | |_ _   _/ ___|| |__   __ _ _ __ ___
#| |_) / _ \| | | |/ _` | | __| | | \___ \| '_ \ / _` | '__/ _ \
#|  _ < (_) | |_| | (_| | | |_| |_| |___) | | | | (_| | | |  __/
#|_| \_\___/ \__, |\__,_|_|\__|\__, |____/|_| |_|\__,_|_|  \___|
#            |___/             |___/
#
# Copyright (C) 2013 RoyaltyShare, Inc.   All Rights Reserved
#---------------------------------------------------------------

package RPS::Import::SoundExchange;

use strict;

use lib '/app/tools/common/lib';
use Common::RSMath qw(round);

use lib '/app/tools/rps/lib';
use base 'RPS::Import::Importer';

sub _fieldMap {
    {

        labelName        => 'F',
        serviceID        => 'J',
        dateBegin        => 'L',
        serviceProductID => 'B',
        artistName       => 'C',
        upc              => 'H',
        albumName        => 'E',
        isrc             => 'G',
        trackName        => 'D',
        price            => 'S',
    };
}

sub _unverifiedFieldMap {
    {
        nonEphemeralRev => 'Q',
        ephemeralRev    => 'R',
        performUnits    => 'N',
        spinUnits       => 'O',
        serviceCategory => 'K',
        typeCol         => 'A',
        thirdParty1     => 'T',
        thirdParty2     => 'U',
        thirdParty3     => 'V',
        thirdParty4     => 'W',
    };
}

sub _headerIdentifier { ( isrc => 'ISRC' ) }
sub countryCode       { 'US' }
sub currencyCode      { 'USD' }
sub mediaType         { RPS::DB::Item::MediaType::kMediaTypeAudio }
sub productType       { RPS::File::Sale::TYPE_TRACK }
sub _dateFormat       { shift->_getByFieldName('dateBegin') =~ /^\d+$/ ? 'iso' : 'text'; }

my %formatTypeMap = (
    'ephemeral' => {
        'admin true up' => {
            format_type => RPS::File::Sale::FORMAT_EPHEMERAL_ATU,
        },
        'bes' => {
            format_type => RPS::File::Sale::FORMAT_EPHEMERAL_BES,
        },
        'cable radio' => {
            format_type => RPS::File::Sale::FORMAT_EPHEMERAL_CABLERAD,
        },
        'international proxies' => {
            format_type => RPS::File::Sale::FORMAT_EPHEMERAL_IP,
        },
        'pes' => {
            format_type => RPS::File::Sale::FORMAT_EPHEMERAL_PES,
        },
        'sdars' => {
            format_type => RPS::File::Sale::FORMAT_EPHEMERAL_SDARS,
        },
        'webcasting' => {
            format_type => RPS::File::Sale::FORMAT_EPHEMERAL_WEBCAST,
        },
        'settlement' => {
            format_type => RPS::File::Sale::FORMAT_EPHEMERAL_SETTLEMENT,
        },
        'settlement and other' => {
            format_type => RPS::File::Sale::FORMAT_EPHEMERAL_SETTLEMENT,
        },
    },
    'non-ephemeral' => {
        'admin true up' => {
            format_type => RPS::File::Sale::FORMAT_NON_EPHEMERAL_ATU,
        },
        'bes' => {
            format_type => RPS::File::Sale::FORMAT_NON_EPHEMERAL_BES,
        },
        'cable radio' => {
            format_type => RPS::File::Sale::FORMAT_NON_EPHEMERAL_CABLERAD,
        },
        'international proxies' => {
            format_type => RPS::File::Sale::FORMAT_NON_EPHEMERAL_IP,
        },
        'pes' => {
            format_type => RPS::File::Sale::FORMAT_NON_EPHEMERAL_PES,
        },
        'sdars' => {
            format_type => RPS::File::Sale::FORMAT_NON_EPHEMERAL_SDARS,
        },
        'webcasting' => {
            format_type => RPS::File::Sale::FORMAT_NON_EPHEMERAL_WEBCAST,
        },
        'settlement' => {
            format_type => RPS::File::Sale::FORMAT_NON_EPHEMERAL_SETTLEMENT,
        },
        'settlement and other' => {
            format_type => RPS::File::Sale::FORMAT_NON_EPHEMERAL_SETTLEMENT,
        },
    },
);

sub upc {
    my $self = shift;
    return Common::Util::normalize_upc( $self->_getByFieldName('upc') );
}

sub isrc {
    my $self = shift;
    return Common::Util::normalize_isrc( $self->_getByFieldName('isrc') );
}

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 saleDates {
    my $self = shift;

    my $date = $self->_getByFieldName("dateBegin");

    if ( $date =~ m/^(\d+)$/ ) {
        $date = Spreadsheet::ParseExcel::Utility::ExcelFmt( "yyyy-mm-dd", $date );
    }
	# MM/DD/YYYY:
	elsif ( $date =~ /(\d\d?)\/(\d\d?)\/(\d{4})/) {
		$date = sprintf("%04d-%02d-%02d", $3, $1, $2);
	}
	# DD?-MMM-YY
	elsif ( $date =~ /(\d\d?)-(\w{3})-(\d{2,4})/) {
        my $year = (length($3) == 2) ? "20$3" : $3;
		$date = sprintf("%04d-%02d-%02d", $year, $months{lc($2)}, $1);
	}

    my ( $dateBegin, $dateEnd ) = $self->SUPER::_getDates( date_begin => $date, type => 'iso' );

    return ($dateBegin, $dateEnd) if ($dateBegin);

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

# The following accessors are used in our parent's (SUPER) _saveLine
#
sub formatType {
    return shift->{_formatType};    # set in _saveLine (below)
}

sub unitPrice {
    return shift->{_unitPrice};     # set in _saveLine (below)
}

sub units {
    return shift->{_units};         # set in _saveLine (below)
}

sub _isValidSaleRecord {
    my $self = shift;

    if ( $self->serviceProductID =~ /Tracks Under One Cent/i ) {
        return;
    }

    if ( $self->_getByFieldName('typeCol') =~ /^(?:Tracks Under One Cent|Foreign Cost Deduction|Foreign Withholding Amount)$/i ) {
        return;
    }

    if ( !$self->_getByFieldName('nonEphemeralRev') && !$self->_getByFieldName('ephemeralRev') && $self->price &&
         !$self->_getByFieldName('albumName') && !$self->_getByFieldName('artistName') && !$self->_getByFieldName('trackName') ) {
           $self->fail("No album, artist, or track name found but price defined.");
    }

    return 1 if !($self->_getByFieldName('nonEphemeralRev') && $self->_getByFieldName('ephemeralRev')) && $self->price;

    return ( $self->_getByFieldName('nonEphemeralRev') || $self->_getByFieldName('ephemeralRev') );
}

# By default, _saveLine will create a single sale record.  Here, we may
# have multiple sales per line (ephemeral and non-ephemeral).  To accomodate
# these we'll override _saveLine and create multiple sales records as
# needed.
#
sub _saveLine {
    my $self = shift;

    if (   $self->_getByFieldName('thirdParty1')
        || $self->_getByFieldName('thirdParty2')
        || $self->_getByFieldName('thirdParty3')
        || $self->_getByFieldName('thirdParty4') ) {

        $self->fail("Found third party revenue");
    }

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

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

    # Let's make sure everything adds up.
    if ($nonEphemeralRev || $ephemeralRev) {
        if ( round( $nonEphemeralRev + $ephemeralRev, 2 ) != round( $price, 2 ) ) {
            $self->fail("Could not reconcile revenue columns");
        }
    }

    my $performUnits = $self->_getByFieldName('performUnits') || 0;
    my $spinUnits    = $self->_getByFieldName('spinUnits')    || 0;

    # Calculate the unit price (if we can).
    my $unitPrice = 0;
    if ( my $totalUnits = abs $performUnits + abs $spinUnits ) {
        $unitPrice = abs($price / $totalUnits);
    }

    if (!$nonEphemeralRev && !$ephemeralRev) {
        $self->{_formatType} = RPS::File::Sale::FORMAT_PERFORMANCE;
        if ($unitPrice) {
            my $units = abs round($price / $unitPrice) || 1;
            $units *= -1 if $price < 0;
            $self->{_units}     = $units;
            $self->{_unitPrice} = abs($price / $units);
        } else {
            $self->{_units}     = $price < 0 ? -1 : 1;
            $self->{_unitPrice} = abs($price);
        }

        $self->SUPER::_saveLine();
    }

    if ($nonEphemeralRev) {
        if ($serviceCategory) {
            $self->{_formatType} = $formatTypeMap{"non-ephemeral"}{ lc($serviceCategory) }->{format_type};
            $self->fail("Could not determine format type from '$serviceCategory'") unless  $self->{_formatType};

        } else {
            $self->{_formatType} = RPS::File::Sale::FORMAT_NON_EPHEMERAL;
        }

        if ($unitPrice) {
            my $nonEphUnits = abs round($nonEphemeralRev / $unitPrice) || 1;
            $nonEphUnits *= -1 if $nonEphemeralRev < 0;
            $self->{_units}     = $nonEphUnits;
            $self->{_unitPrice} = abs($nonEphemeralRev / $nonEphUnits);
        } else {
            $self->{_units}     = $nonEphemeralRev < 0 ? -1 : 1;
            $self->{_unitPrice} = abs($nonEphemeralRev);
        }

        $self->SUPER::_saveLine();
    }

    if ($ephemeralRev) {
        if ($serviceCategory) {
            $self->{_formatType} = $formatTypeMap{"ephemeral"}{ lc($serviceCategory) }->{format_type};
            $self->fail("Could not determine format type from '$serviceCategory'") unless $self->{_formatType};
        } else {
             $self->{_formatType} = RPS::File::Sale::FORMAT_EPHEMERAL;
        }

        if ($unitPrice) {
            my $ephUnits = abs round($ephemeralRev / $unitPrice) || 1;
            $ephUnits *= -1 if $ephemeralRev < 0;
            $self->{_units}     = $ephUnits;
            $self->{_unitPrice} = abs($ephemeralRev / $ephUnits);
        } else {
            $self->{_units}     = $ephemeralRev < 0 ? -1 : 1;
            $self->{_unitPrice} = abs($ephemeralRev);
        }

        $self->SUPER::_saveLine();
    }
}

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