#---------------------------------------------------------------
# ____                   _ _         ____  _
#|  _ \ ___  _   _  __ _| | |_ _   _/ ___|| |__   __ _ _ __ ___
#| |_) / _ \| | | |/ _` | | __| | | \___ \| '_ \ / _` | '__/ _ \
#|  _ < (_) | |_| | (_| | | |_| |_| |___) | | | | (_| | | |  __/
#|_| \_\___/ \__, |\__,_|_|\__|\__, |____/|_| |_|\__,_|_|  \___|
#            |___/             |___/
#
# Copyright (C) 2014 RoyaltyShare, Inc.   All Rights Reserved
#---------------------------------------------------------------
package RPS::Import::ThirtyTigers::v1;

use strict;

use Date::Calc qw(Days_in_Month Decode_Month);

use lib '/app/tools/rps/lib';
use RPS::Import::ServiceMap;

use base 'RPS::Import::Importer';

sub _fieldMap {
    my $self      = shift;
    my $sheetType = $self->{_sheetType};

    my %field_map = (
        'EU' => {
            labelName   => 'A',
            serviceID   => 'D',
            countryCode => 'E',
            dateBegin   => 'F',
            dateEnd     => 'F',
            artistName  => 'B',
            units       => 'K',
            isrc        => 'H',    # can be ISRC or catalogID
            price       => 'N',
        },
        'US' => {
            labelName => 'A',
            upc       => 'I',
            albumName => 'C',
            isrc      => 'G',
            trackName => 'F',
        },
    );
    return $field_map{$sheetType};
}

sub _unverifiedFieldMap {
    my $self      = shift;
    my $sheetType = $self->{_sheetType};

    my %field_map = (
        'US' => {
            config              => 'D',
            downloadQT          => 'K',
            downloadAM          => 'L',
            streamPremiumQT     => 'M',
            streamPremiumAM     => 'N',
            streamAdSupportedQT => 'O',
            streamAdSupportedAM => 'P',
            lockerQT            => 'Q',
            lockerAM            => 'R',
            otherQT             => 'S',
            otherAM             => 'T',
            trackArtist         => 'E',
            albumArtist         => 'B',
        },
        'EU' => {
            format => 'J',
            title  => 'C',    # album or track title
        },
    );
    return $field_map{$sheetType};
}

sub _headerIdentifier { ( isrc => qr/ISRC/ ) }

sub serviceID {
    my $self = shift;
    return undef if ( !exists $self->_fieldMap->{'serviceID'} );

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

    return $serviceID if ($serviceID);
    return $self->fail("Unknown service: $service");
}

sub countryCode {
    my $self = shift;
    if ( exists $self->_fieldMap->{'countryCode'} ) {
        my $cname = $self->_getByFieldName('countryCode');
        my $o     = Common::Country->Get($cname);
        return ( defined $o ) ? $o->alpha2() : $cname;
    }
    return 'US';
}

sub saleDates {
    my $self = shift;
    my $dateBegin;
    my $dateEnd;

    if ( exists $self->_fieldMap->{'dateBegin'} ) {
        my $sDate = $self->_getByFieldName('dateBegin');
        my $eDate = $self->_getByFieldName('dateEnd');
        ( $dateBegin, $dateEnd ) = $self->_getDates( date_begin => $sDate, date_end => $eDate );
    } else {
        if ( !$self->{_dateBegin} ) {
            my $sheetName = $self->{sheetname};
            if ( $sheetName =~ /^(\d{2})\.(\d{2}) US Digital$/i ) {
                my ( $month, $year ) = ( $1, $2 );
                $year += 2000;
                $dateBegin = sprintf( "%04d-%02d-%02d", $year, $month, 1 );
                $dateEnd = sprintf( "%04d-%02d-%02d", $year, $month, Days_in_Month( $year, $month ) );
            }
            $self->{_dateBegin} = $dateBegin;
            $self->{_dateEnd}   = $dateEnd;
        }
        ( $dateBegin, $dateEnd ) = ( $self->{_dateBegin}, $self->{_dateEnd} );
    }
    return ( $dateBegin, $dateEnd );
}

sub serviceProductID {
    my $self = shift;
    if ( $self->{_sheetType} eq 'EU' ) {
        my $catalogNo = $self->_getByFieldName('isrc');
        return ( $self->productType eq RPS::File::Sale::TYPE_ALBUM ) ? $catalogNo : undef;
    }
}

sub isrc {
    my $self = shift;
    my $isrc = $self->_getByFieldName('isrc');
    return ( $self->productType eq RPS::File::Sale::TYPE_TRACK ) ? $isrc : undef;
}

sub _processHeader {
    my $self = shift;

    unless ( $self->{_currencyCode} ) {
        if ( $self->{_sheetType} eq 'EU' ) {
            my $st = $self->_getByFieldName('price');
            if ( $st =~ /^NET SALES (\w{3})$/i ) {
                $self->{_currencyCode} = $1;
            }
        } elsif ( $self->{_sheetType} eq 'US' ) {
            $self->{_currencyCode} = 'USD';
        }
    }
}

sub currencyCode {
    shift->{_currencyCode};    # set in _processHeader
}

sub trackName {
    my $self = shift;
    my $title;
    if ( exists $self->_fieldMap->{'trackName'} ) {
        $title = $self->_getByFieldName('trackName');
    } else {
        $title = $self->_getByFieldName('title');
    }
    return ( $self->productType eq RPS::File::Sale::TYPE_TRACK ) ? $title : undef;
}

sub albumName {
    my $self = shift;
    if ( exists $self->_fieldMap->{'albumName'} ) {
        return $self->_getByFieldName('albumName');
    }
    my $title = $self->_getByFieldName('title');
    return ( $self->productType eq RPS::File::Sale::TYPE_ALBUM ) ? $title : undef;
}

sub artistName {
    my $self = shift;
    return $self->SUPER::artistName() if ( exists $self->_fieldMap->{'artistName'} );    # EU sales

    # US sales
    my $albumArtist = $self->_getByFieldName('albumArtist');
    my $trackArtist = $self->_getByFieldName('trackArtist');
    return ( $self->productType eq RPS::File::Sale::TYPE_ALBUM ) ? $albumArtist : $trackArtist;
}

sub productType {
    my $self = shift;
    my $type;
    if ( exists $self->_unverifiedFieldMap->{format} )                                   # EU sales
    {
        $type = $self->_getByFieldName('format');
        if (   $type =~ /^AD-FUNDED STREAM$/i
            || $type =~ /^DIGITAL (SINGLE|STREAM|TRACK|VIDEO)$/i
            || $type =~ /^PREMIUM STREAM$/i ) {
            return RPS::File::Sale::TYPE_TRACK;
        } elsif ( $type =~ /^DIGITAL ALBUM$/i ) {
            return RPS::File::Sale::TYPE_ALBUM;
        }
    } elsif ( exists $self->_unverifiedFieldMap->{config} )                              # US sales
    {
        $type = $self->_getByFieldName('config');
        if (   $type =~ /^Digital Audio Extended Play$/i
            || $type =~ /^Digital Audio LongPlay$/i ) {
            return RPS::File::Sale::TYPE_ALBUM;
        } elsif ( $type =~ /^Digital (Audio|Video) Track$/i ) {
            return RPS::File::Sale::TYPE_TRACK;
        }
    }
    return $self->fail("Unable to determine product type from '$type'");
}

sub formatType {
    my $self = shift;

    if ( $self->{_sheetType} eq 'EU' ) {
        my $type;
        if ( exists $self->_unverifiedFieldMap->{format} )    # EU sales
        {
            $type = $self->_getByFieldName('format');

            if (   $type =~ /^AD-FUNDED STREAM$/i
                || $type =~ /^DIGITAL (STREAM|VIDEO)$/i
                || $type =~ /^PREMIUM STREAM$/i ) {
                return RPS::File::Sale::FORMAT_STREAM;
            } elsif ( $type =~ /^DIGITAL (ALBUM|SINGLE|TRACK)$/i ) {
                return RPS::File::Sale::FORMAT_DOWNLOAD;
            }
        }
        return $self->fail("Unable to determine format type from '$type'");
    }
    return $self->{_formatType};    # set in _saveLine for US sales (below)
}

sub mediaType {
    my $self = shift;

    if ( $self->{_sheetType} eq 'EU' ) {
        my $type = $self->_getByFieldName('format');

        if (   $type =~ /^AD-FUNDED STREAM$/i
            || $type =~ /^DIGITAL (ALBUM|SINGLE|STREAM|TRACK)$/i
            || $type =~ /^PREMIUM STREAM$/i ) {
            return RPS::DB::Item::MediaType::kMediaTypeAudio;
        } elsif ( $type =~ /^DIGITAL VIDEO$/i ) {
            return RPS::DB::Item::MediaType::kMediaTypeVideo;
        }
        return $self->fail("Unable to determine media type from '$type'");
    } else {

        # (US) sales
        my $type = $self->_getByFieldName('config');
        if (   $type =~ /^Digital Audio Extended Play$/i
            || $type =~ /^Digital Audio LongPlay$/i
            || $type =~ /^Digital Audio Track$/i ) {
            return RPS::DB::Item::MediaType::kMediaTypeAudio;
        } elsif ( $type =~ /^Digital Video Track$/i ) {
            return RPS::DB::Item::MediaType::kMediaTypeVideo;
        }
    }
}

sub _processSheet {
    my $self     = shift;
    my $sheet    = shift;
    my $sheetnum = shift;

    my $num = scalar @$sheet;

    # If we have a physical tab, make sure it doesn't have any lines in it.
    # if it's empty then we'll skip it and go on processing the rest of the
    # file, otherwise we'll error out.
    #
    if ( $self->{sheetname} =~ /us digital/i ) {
        $self->{_sheetType} = 'US';
        return $self->SUPER::_processSheet( $sheet, $sheetnum );
    } elsif ( $self->{sheetname} =~ /eu digital/i ) {
        $self->{_sheetType} = 'EU';
        return $self->SUPER::_processSheet( $sheet, $sheetnum );
    } else {
        $self->fail( "Found unknown sheet '" . $self->{sheetname} . "'" );
    }
}

sub _unitPrice {
    my $self = shift;
    return $self->SUPER::_unitPrice() if ( exists $self->_fieldMap->{units} );    # EU
    return $self->{_unitPrice};                                                   # set in _saveLine (below)
}

sub units {
    my $self = shift;
    return $self->_getByFieldName('units') if ( exists $self->_fieldMap->{units} );    # EU
    return $self->{_units};                                                            # set in _saveLine (below)
}

sub price {
    my $self = shift;
    return $self->_getByFieldName('price') if ( exists $self->_fieldMap->{price} );    # EU
    return $self->{_price};                                                            # set in _saveLine (below)
}

# We can have units from two different columns so we need to override
# _isValidSaleRecord to process lines with units in either location.
#
sub _isValidSaleRecord {
    my $self = shift;
    my $title;
    my $revenue = 0;
    my $units   = 0;

    if ( $self->{_sheetType} eq 'EU' ) {
        $revenue = $self->_getByFieldName('price');
        $units   = $self->_getByFieldName('units');
        $title   = $self->_getByFieldName('title');
    } else {

        # gather units...
        my $downloadQT          = $self->_getByFieldName('downloadQT');
        my $streamPremiumQT     = $self->_getByFieldName('streamPremiumQT');
        my $streamAdSupportedQT = $self->_getByFieldName('streamAdSupportedQT');
        my $lockerQT            = $self->_getByFieldName('lockerQT');
        my $otherQT             = $self->_getByFieldName('otherQT');

        # gather revenue...
        my $downloadAM          = $self->_getByFieldName('downloadAM');
        my $streamPremiumAM     = $self->_getByFieldName('streamPremiumAM');
        my $streamAdSupportedAM = $self->_getByFieldName('streamAdSupportedAM');
        my $lockerAM            = $self->_getByFieldName('lockerAM');
        my $otherAM             = $self->_getByFieldName('otherAM');

        $units   = $downloadQT + $streamPremiumQT + $streamAdSupportedQT + $lockerQT + $otherQT;
        $revenue = $downloadAM + $streamPremiumAM + $streamAdSupportedAM + $lockerAM + $otherAM;
        $title   = $self->_getByFieldName('albumName') || $self->_getByFieldName('trackName');
    }

    # line is valid if it has units and/or revenue, and a title
    #
    return ( ( $revenue || $units ) && $title );
}

# By default, _saveLine will create a single sale record.  The 'US'
# tab may have multiple formats on a single line, so we'll need to create
# multiple sale records for a line (one per format) in order to capture
# those sales.
#
sub _saveLine {
    my $self = shift;

    # For the EU tab, just call normal _saveLine, otherwise we'll have to do a
    # little juggling before we save anything (this is so we can create separate
    # sale records records for download and/or stream sales).
    #
    if ( $self->{_sheetType} eq 'EU' ) {
        $self->SUPER::_saveLine();
    } else {

        # gather units...
        my $downloadQT          = $self->_getByFieldName('downloadQT');
        my $streamPremiumQT     = $self->_getByFieldName('streamPremiumQT');
        my $streamAdSupportedQT = $self->_getByFieldName('streamAdSupportedQT');
        my $lockerQT            = $self->_getByFieldName('lockerQT');
        my $otherQT             = $self->_getByFieldName('otherQT');

        my $downloadUnits = $downloadQT;
        my $streamUnits   = $streamPremiumQT + $streamAdSupportedQT + $lockerQT + $otherQT;

        # gather revenue...
        my $downloadAM          = $self->_getByFieldName('downloadAM');
        my $streamPremiumAM     = $self->_getByFieldName('streamPremiumAM');
        my $streamAdSupportedAM = $self->_getByFieldName('streamAdSupportedAM');
        my $lockerAM            = $self->_getByFieldName('lockerAM');
        my $otherAM             = $self->_getByFieldName('otherAM');

        my $downloadRevenue = $downloadAM;
        my $streamRevenue   = $streamPremiumAM + $streamAdSupportedAM + $lockerAM + $otherAM;

        if ( $downloadUnits || $downloadRevenue ) {
            $self->{_formatType} = RPS::File::Sale::FORMAT_DOWNLOAD;
            $self->{_units}      = $downloadUnits;
            $self->{_price}      = $downloadRevenue;
            my $unitPrice = ($downloadUnits) ? $downloadRevenue / $downloadUnits : $downloadRevenue;
            $self->{_unitPrice} = $unitPrice;
            $self->SUPER::_saveLine();
        }

        if ( $streamUnits || $streamRevenue ) {
            $self->{_formatType} = RPS::File::Sale::FORMAT_STREAM;
            $self->{_units}      = $streamUnits;
            $self->{_price}      = $streamRevenue;
            my $unitPrice = ($streamUnits) ? $streamRevenue / $streamUnits : $streamRevenue;
            $self->{_unitPrice} = $unitPrice;
            $self->SUPER::_saveLine();
        }
    }
}

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