#---------------------------------------------------------------
# ____                   _ _         ____  _
#|  _ \ ___  _   _  __ _| | |_ _   _/ ___|| |__   __ _ _ __ ___
#| |_) / _ \| | | |/ _` | | __| | | \___ \| '_ \ / _` | '__/ _ \
#|  _ < (_) | |_| | (_| | | |_| |_| |___) | | | | (_| | | |  __/
#|_| \_\___/ \__, |\__,_|_|\__|\__, |____/|_| |_|\__,_|_|  \___|
#            |___/             |___/
#
# 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.
###
