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

package RPS::Import::Caroline::v3;

use strict;

use Date::Calc qw(Days_in_Month Decode_Month);

use lib '/app/tools/common/lib';
use Common::Assert;

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

use Spreadsheet::ParseExcel;

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

sub _fieldMap {
    my $self = shift;
    my $version = $self->_version;

    my %field_map = (
        3 => {
            labelName     => 'A',
            serviceID     => 'D',
            dateBegin     => 'O',
            dateEnd       => 'P',
            upc           => 'I',
            albumName     => 'H',
            trackName     => 'K',
            isrc          => 'N',
            units         => 'Q',
            price         => 'R',
            productType   => 'F',
        },
        5 => {
            labelName     => 'A',
            serviceID     => 'E',
            upc           => 'J',
            albumName     => 'I',
            trackName     => 'L',
            isrc          => 'N',
            units         => 'P',
            price         => 'Q',
            productType   => 'G',
        },
        12 => {
            labelName     => 'A',
            serviceID     => 'E',
            dateBegin     => 'O',
            upc           => 'J',
            albumName     => 'I',
            trackName     => 'L',
            isrc          => 'N',
            units         => 'P',
            price         => 'O',
            productType   => 'G',
        },
        16 => {
            labelName     => 'B',
            serviceID     => 'V',
            dateBegin     => 'T',
            dateEnd       => 'U',
            upc           => 'M',
            albumName     => 'L',
            trackName     => 'O',
            isrc          => 'Q',
            units         => 'X',
            price         => 'W',
            productType   => 'I',
        },
    );
    return $field_map{$version};
}

sub _unverifiedFieldMap {
    my $self = shift;
    my $version = $self->_version;

    my %field_map = (
        3 => {
            albumArtist   => 'G',
            trackArtist   => 'J',
            deliveryType  => 'C',
        },
        5 => {
            albumArtist   => 'H',
            trackArtist   => 'K',
            deliveryType  => 'D',
        },
        12 => {
            albumArtist   => 'H',
            trackArtist   => 'K',
            deliveryType  => 'D',
        },
        16 => {
            albumArtist   => 'K',
            trackArtist   => 'N',
            deliveryType  => 'E',
        },
    );
    return $field_map{$version};
}

sub serviceID {
    my $self = shift;
    
    my $service = $self->_getByFieldName('serviceID');
    my $serviceID = $self->getServiceID(lc ($service)) || $RPS::Import::ServiceMap::SERVICE_ALIASES{ lc $service };
    return $serviceID if( $serviceID );
    return $self->handleError("Unknown service: $serviceID", RPS::DB::Item::SaleImportError::kErrorService);
}

# Note: keys must be lowercase
#
my %gFormatMediaMap  = (
    'ad supported streams' =>
    {
        formatType  => RPS::File::Sale::FORMAT_STREAM,
        mediaType   => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'broadcast vod' =>
    {
        formatType  => RPS::File::Sale::FORMAT_STREAM,
        mediaType   => RPS::DB::Item::MediaType::kMediaTypeVideo,
    },
    'conditional mastertone' =>
    {
        formatType  => RPS::File::Sale::FORMAT_STREAM,
        mediaType   => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'drm-free upgrade transactions' =>
    {
        formatType  => RPS::File::Sale::FORMAT_DOWNLOADUPGRADE,
        mediaType   => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'ephemeral plays' =>
    {
        formatType  => RPS::File::Sale::FORMAT_STREAM,
        mediaType   => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'film non-music video rental' =>
    {
        formatType  => RPS::File::Sale::FORMAT_DOWNLOAD,
        mediaType   => RPS::DB::Item::MediaType::kMediaTypeVideo,
    },    
    'fixed plays' =>
    {
        formatType  => RPS::File::Sale::FORMAT_STREAM,
        mediaType   => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'kiosk' =>
    {
        formatType  => RPS::File::Sale::FORMAT_DOWNLOAD,
        mediaType   => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'long form music video rental' =>
    {
        formatType  => RPS::File::Sale::FORMAT_DOWNLOAD,
        mediaType   => RPS::DB::Item::MediaType::kMediaTypeVideo,
    },      
    'mobile audio streams' =>
    {
        formatType  => RPS::File::Sale::FORMAT_STREAM,
        mediaType   => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'mobile video streaming' =>
    {
        formatType  => RPS::File::Sale::FORMAT_STREAM,
        mediaType   => RPS::DB::Item::MediaType::kMediaTypeVideo,
    },
    'non-music video sell-thru' =>
    {
        formatType  => RPS::File::Sale::FORMAT_DOWNLOAD,
        mediaType   => RPS::DB::Item::MediaType::kMediaTypeVideo,
    },      
    '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,
    },
    'permanent downloads promo' =>
    {
        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-capped (non-royalty bearing)' =>
    {
        formatType  => RPS::File::Sale::FORMAT_STREAM,
        mediaType   => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'programmed video streaming' =>
    {
        formatType  => RPS::File::Sale::FORMAT_STREAM,
        mediaType   => RPS::DB::Item::MediaType::kMediaTypeVideo,
    },
    'ringbacks' =>
    {
        formatType  => RPS::File::Sale::FORMAT_RINGTONE,
        mediaType   => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'ringback - no copyright' =>
    {
        formatType  => RPS::File::Sale::FORMAT_STREAM,
        mediaType   => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'ringbacks (no cprt liability)' =>
    {
        formatType  => RPS::File::Sale::FORMAT_STREAM,
        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,
    },
    'sub user generated streams (umg audio)' =>
    {
        formatType  => RPS::File::Sale::FORMAT_STREAM,
        mediaType   => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },    
    'subscription mastertones' =>
    {
        formatType  => RPS::File::Sale::FORMAT_DOWNLOAD,
        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,
    },
    '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,
    },
    'video streams (sponsorship)' =>
    {
        formatType  => RPS::File::Sale::FORMAT_STREAM,
        mediaType   => RPS::DB::Item::MediaType::kMediaTypeVideo,
    },
);

sub _headerIdentifier { ( upc => qr/UPC(?: ID)?/ ) } # "UPC" or "UPC ID"

sub currencyCode { "USD" }

sub countryCode {

    my $self = shift;
    if( $self->_version == 12 )
    {
        if( !exists $self->{_countryCode} )
        {
            if( $self->filename =~ /_US/i )
            {
                $self->{_countryCode} = 'US';
            }
            elsif( $self->filename =~ /_CA/i )
            {
                $self->{_countryCode} = 'CA';
            }
            else
            {
                return $self->handleError( "Unable to determine country code from ". $self->filename, RPS::DB::Item::SaleImportError::kErrorNonqualifying );
                
            }
        }
        return $self->{_countryCode};
    }
    return "US";
}


sub saleDates {
    my $self  = shift;
    my $version = $self->_version;

    my $dateBegin;
    my $dateEnd;

    if( $version == 5 || $version == 12 )
    {
        # version 5:  date from filename (see _preProcess)
        # version 12: date from header (see _processHeader)
        #
        $dateBegin = $self->{_dateBegin};
        $dateEnd   = $self->{_dateEnd};
    }
    elsif( exists $self->_fieldMap->{'dateBegin'} )
    {
        my $sdate = $self->_getByFieldName('dateBegin');
        my $edate = $self->_getByFieldName('dateEnd');

        if( $sdate =~ /(\d{4})-(\d{1,2})-(\d{1,2})/ ) # YYYY-MM-DD
        {
            $dateBegin = sprintf("%04d-%02d-%02d", $1, $2, 1);

        }
        elsif( $sdate =~ /^(\d{5})$/ )
        {
            $dateBegin = Spreadsheet::ParseExcel::Utility::ExcelFmt("yyyy-mm-dd", $sdate );
            my($year, $month, $day) = split("-", $dateBegin );
            $dateBegin = sprintf("%04d-%02d-01", $year, $month );
        }

        if( $edate =~ /(\d{4})-(\d{1,2})-(\d{1,2})/ ) # YYYY-MM-DD
        {
            $dateEnd   = sprintf("%04d-%02d-%02d", $1, $2, Days_in_Month($1, $2) );
        }
        elsif( $edate =~ /^(\d{5})$/ )
        {
            $dateEnd = Spreadsheet::ParseExcel::Utility::ExcelFmt("yyyy-mm-dd", $edate );
            my($year, $month, $day) = split("-", $dateEnd );
            $dateEnd = sprintf("%04d-%02d-%02d", $year, $month, Days_in_Month( $year, $month ) );
        }
    }

    return ($dateBegin, $dateEnd);

}

sub _processHeader {
    my $self = shift;
    my %args = @_;

    $self->SUPER::_processHeader(%args);

    if( $self->_version == 12 )
    {
        # For version 12, the date is actually in the header
        #
        return if( !$self->{_headerFound} );

        my $dt = $self->_getByFieldName('dateBegin');

        if( $dt =~ /revenue umg \w{2} \d{2} \((\w{3}) (\d{2})\)/i )
        {
            my $_month = lc $1;
            my $year   = $2;

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

            $self->{_dateBegin} = $sdate;
            $self->{_dateEnd}   = $edate;
        }
        else
        {
            return $self->handleError( "Unable to determine date", RPS::DB::Item::SaleImportError::kErrorNonqualifying );
        }
    }
}

sub _preProcess {
    my $self = shift;
    my %args = @_;

    $self->SUPER::_preProcess(%args);

    if( $self->_version == 5 )
    {
        if( $self->filename =~ /(\d{4})_(\d{2})(\s|_)/ )
        {
            $self->{_dateBegin} = sprintf("%04d-%02d-%02d", $1, $2, 1);
            $self->{_dateEnd}   = sprintf("%04d-%02d-%02d", $1, $2, Days_in_Month($1, $2) );
        }
    }
}

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

    if( $self->version == 12 )
    {
        return $self->SUPER::_processSheet( $sheet, $sheetnum ) if( $self->{sheetname} =~ /digital sales/i );
    }
    else
    {
        return $self->SUPER::_processSheet( $sheet, $sheetnum );
    }
}

sub artistName {
    my $self = shift;
    if( $self->upc eq $self->isrc )
    {
        return $self->_getByFieldName('albumArtist');
    }
    else
    {
        my $name = $self->_getByFieldName('trackArtist');
        if( $name =~ /(\w+),\s*(\w+)/ )
        {
            $name = "$2 $1";
        }
        elsif( $name =~ /^-+$/ ) # bunch 'o hyphens ...
        {
            $name = $self->_getByFieldName('albumArtist');
        }
        return $name;
    }
}

sub productType {
    my $self = shift;
    my $type = $self->_getByFieldName('productType') || return;

    if( $type =~ /^track$/i )
    {
        return RPS::File::Sale::TYPE_TRACK;
    }
    elsif( $type =~ /^bundles$/i )
    {
        # Bundles are albums unless they have an isrc that looks like an isrc
        # (as opposed to something like an upc)

        return ( $self->SUPER::isrc =~ /^[a-z]{2}.+/i ) ?  RPS::File::Sale::TYPE_TRACK : RPS::File::Sale::TYPE_ALBUM;
    }
    elsif( $type =~ /^complete album$/i )
    {
        return RPS::File::Sale::TYPE_ALBUM;
    }
    return $self->handleError("Unable to determine product type from '$type'", RPS::DB::Item::SaleImportError::kErrorProductType);
}

sub units {
    my $self = shift;
    my $u = $self->_getByFieldName('units') || 0;
    my $p = $self->_getByFieldName('price');

    # Follow the sign of the revenue...
    #
    if( $p > 0 )
    {
        return 1 if (!$u);  # force a unit if there's revenue
        return ( $u < 0 ) ? abs($u) : $u;
    }
    elsif( $p < 0 )
    {
        return -1 if (!$u); # force a unit if there's revenue
        return ( $u < 0 ) ? $u : ($u * -1);
    }
    return $u;
}

sub unitPrice { abs( shift->SUPER::unitPrice ) }

# Don't flag free sales (FB15405)
#sub free {
#    my $self = shift;
#    my $u = $self->_getByFieldName('units') || 0;
#    my $p = $self->_getByFieldName('price');
#    return ($u != 0 && $p == 0) ? 1 : 0;
#}

sub _isValidSaleRecord {
    my $self = shift;
    
    # We may not know if this is an album or track, so we need to be a bit
    # more agnostic with out tests,
    if ( $self->albumName || $self->upc || $self->trackName || $self->isrc ) {
        return 1;
    } 
    
    # How would we ever get here?
    if( $self->_version == 12 )
    {
        my $u = $self->_getByFieldName('units') || 0;
        my $p = $self->_getByFieldName('price');

        return 1 if ( !$p && $u ); # ok if units but no revenue (will be marked free)
    }

    return $self->SUPER::_isValidSaleRecord();
}

sub formatType {
    my $self = shift;
    my($formatID, $mediaType) = $self->_getFormatMedia();

    if (!$formatID) {
        my $deliveryType = lc $self->_getByFieldName('deliveryType');
        return $self->handleError("Unrecognized channel '$deliveryType", RPS::DB::Item::SaleImportError::kErrorFormatType); 
    } 
    
    return $formatID;
}

sub mediaType {
    my $self = shift;
    my($formatID, $mediaType) = $self->_getFormatMedia();
    
    if (!$mediaType) {
        my $deliveryType = lc $self->_getByFieldName('deliveryType');
        return $self->handleError("Unrecognized channel '$deliveryType", RPS::DB::Item::SaleImportError::kErrorMediaType);
    }     
    
    return $mediaType;
}

sub _getFormatMedia {
    my($self) = @_;
    my $deliveryType = lc $self->_getByFieldName('deliveryType');

    my $formatID;
    my $mediaType;
    if ( exists $gFormatMediaMap{$deliveryType} )
    {
        $formatID    = $gFormatMediaMap{$deliveryType}->{formatType};
        $mediaType   = $gFormatMediaMap{$deliveryType}->{mediaType};
    }

    return( $formatID, $mediaType );
}

sub trackName {
    my $self = shift;
    my $title = $self->SUPER::trackName;

    return ($self->upc ne $self->isrc && $title ne 'NA' && $self->isrc ne '-')
        ? $title : undef;
}

sub isrc {
    my $self = shift;
    my $title = $self->SUPER::trackName;

    return ($self->upc ne $self->SUPER::isrc && $title ne 'NA' && $self->SUPER::isrc ne '-')
        ? $self->SUPER::isrc : undef;
}


## MapFace Stuff

sub _mapFaceServiceID {
	return ('serviceID');
}

sub _mapFaceCountryCode {
	return;
}

sub _mapFaceProductType {
	return ('productType');
}

sub _mapFaceFormatType {
	return ('deliveryType');
}

sub _mapFaceMediaType {
	return ('deliveryType');
}

sub _mapFaceCompatibleVersions {
	return (3,5,9,12,16);
}

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