package RPS::Import::iTunesCloud;

use strict;

use Date::Calc qw(Days_in_Month);

use Data::Dumper;

use lib '/app/tools/common/lib';
use Common::Util;
use Common::Consts;

use lib '/app/tools/data_classes/lib';

use lib '/app/tools/rps/lib';
use RPS::File::Sale;
use RPS::DB::Item::MediaType;

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


sub _fieldMap {
    {
        labelName     => 'N',
        countryCode   => 'R',
        dateBegin     => 'A',
        dateEnd       => 'B',
        productType   => 'P',
        serviceProductID => 'K',
        clientProductID => 'E',
        artistName    => 'L',
        upc           => 'C',
        albumName     => 'M',
        isrc          => 'D',
        trackName     => 'M',
        units         => 'F',
        currencyCode  => 'I',
	}
}

sub _unverifiedFieldMap {{
        # Footer
        footerLabel      => 'A',
        footerAmount     => 'B',
        countryOfSale    => 'A',
        partnerUnitTotal => 'G',
        partnerShare     => 'H',
        publisherShare   => 'I',  # for older-style footer
}}

sub _headerIdentifier { ( dateBegin => 'Start Date' ) }

sub formatType  { return RPS::File::Sale::FORMAT_STREAM; }


sub productType { 
	my $self = shift;
	    
    my $productType = $self->_getByFieldName('productType') || return;
    
    if ($productType eq 'H3' ||
        $productType eq 'J3' ||
        $productType eq 'V3' ||
        $productType eq 'S3')
    {
        return RPS::File::Sale::TYPE_TRACK;
    }
    else
    {
        $self->fail( "Unrecognized product type: $productType" )    
    }     
}

sub mediaType { 
	my $self = shift;
	    
    my $productType = $self->_getByFieldName('productType') || return;
    
    if ($productType eq 'H3' ||
        $productType eq 'S3')
    {
        RPS::DB::Item::MediaType::kMediaTypeAudio;
    }
    elsif ($productType eq 'J3' ||
           $productType eq 'V3')
    {
        RPS::DB::Item::MediaType::kMediaTypeVideo;
    }    
    else
    {
        $self->fail( "Unrecognized product type: $productType" )    
    }     
}

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

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

sub unitPrice {
    my $self = shift;

    if( ref($self->{_price}) eq 'HASH' )
    {
        if( $self->countryCode )
        {
            if( exists %$self->{_price}{$self->countryCode} )
            {
                return %$self->{_price}{$self->countryCode};
            }
        }
    }
    else
    {
        return $self->{_price};
    }
}

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

    Log->info( "Starting _preProcess" );
    $self->SUPER::_preProcess(%args);

    my $partnerShare;
    my $publisherShare;
    my $partnerUnits;
    my $foundSecondHeader;

    my $linenum = 1;

    # A country may appear more than once in the footer.  We'll keep
    # track of the total units and share by country.  After all footer
    # lines have been looked at, we'll then calculate a unit price
    # based on each country's aggregated unit and share information.
    #
    my %countryShareUnitMap;

    foreach my $line(@{ $args{lines} }) {
        $self->{line} = $line;
        
        my $units = $self->_getByFieldName('units');
        if ($units =~ /^\d+$/)
        {   
            $self->{_detailUnits} += $units;        
        }
        
        my $footerLabel = $self->_getByFieldName('footerLabel');
        
        if ($footerLabel =~ /^Cloud Partner Share$/)
        {
            $partnerShare = $self->_getByFieldName('footerAmount');
        }
        elsif ($footerLabel =~ /^Cloud Publisher Share$/)
        {
            $publisherShare = $self->_getByFieldName('footerAmount');
        }
        elsif ($footerLabel =~ /^Partner Converted Unit Total$/)
        {
            $partnerUnits = $self->_getByFieldName('footerAmount');
        }


        # The 'Country of Sale' label is only present if we're processing an iTunes file
        # with a separate footer section with a header row (FB15789, FB17046).
        #
        elsif ($footerLabel =~ /^Country Of Sale$/)
        {
            $foundSecondHeader = 1;
            $linenum++;
            next;
        }

        if ($foundSecondHeader == 1)
        {
            my $_partnerShare  = $self->_getByFieldName('partnerShare');
            my $_partnerUnits  = $self->_getByFieldName('partnerUnitTotal');         
            my $countryOfSale  = $self->_getByFieldName('countryOfSale');         

            if( $countryOfSale =~ /^\w{1,2}$/ )
            {
                $self->fail( "Line $linenum: Unable to determine unit price" )
                    unless( $_partnerShare && $_partnerUnits );

                # Aggregate units and share by country
                #
                $countryShareUnitMap{$countryOfSale}{units} += $_partnerUnits;
                $countryShareUnitMap{$countryOfSale}{share} += $_partnerShare;

            }

            $partnerUnits  += $_partnerUnits;
        }        

        $linenum++;
    }

    # Calculate each country's unit rate
    #
    foreach my $countryOfSale (keys %countryShareUnitMap)
    {
        my $_partnerUnits = $countryShareUnitMap{$countryOfSale}{units};
        my $_partnerShare = $countryShareUnitMap{$countryOfSale}{share};
        $self->{_price}{$countryOfSale} = $_partnerShare / $_partnerUnits;
    }
    
    # We'll compare the units from the footer with the
    # units read from the detail lines (see _postProcess).
    #
    $self->{_partnerUnits} = $partnerUnits;

    # If we did not find a footer with the 'Country Of Sale' column in the
    # header, then we'll store the price information as a scalar instead
    # of a country-based hash table.
    #
    if( !$foundSecondHeader )
    {
        my $price = ($partnerShare + $publisherShare) / $partnerUnits;
        $self->{_price} = $price;
    }

    #print STDERR "D: _preProcess: ". Dumper( \%$self->{_price} ) . "\n";
}

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

	Log->info( "Starting _postProcess" );
    $self->SUPER::_postProcess(%args);   
    
    # Just making sure that the unit total we came up with matches what's in the footer.
    my $footerTotal = $self->{_partnerUnits};
    my $detailTotal = $self->{_detailUnits};

    #$self->fail( "Unit detail total ($detailTotal) differs from unit total listed in footer ($footerTotal)'" ) unless( $footerTotal == $detailTotal );
    if ($footerTotal != $detailTotal)
    {
        $self->errstr("Unit detail total ($detailTotal) differs from unit total listed in footer ($footerTotal)");
        return undef; 
    }           
}

sub _isValidSaleRecord {
	my $self = shift;

	return ( defined($self->units) && ($self->trackName || $self->albumName) && ($self->labelName || $self->productType || $self->countryCode) );
}


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