package RPS::Import::Revolver;

use strict;

use Date::Calc qw(Days_in_Month Decode_Month);

use lib '/app/tools/common/lib';
use Common::Util;
use Common::Consts qw(%COUNTRY_CODE);
use Common::Country;

use lib '/app/tools/data_classes/lib';
use Client::Service;

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

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

my %field_map = (
    1 => {
        month          => 1,  # B
        year           => 2,  # C
        catalog_number => 3,  # D
        upc            => 4,  # E
        isrc           => 5,  # F
        artist         => 6,  # G
        album          => 7,  # H
        track          => 8,  # I
        country        => 10, # K
        service        => 11, # L
        units          => 12, # M
        revenue        => 16, # Q       
    },

);

my %gServiceFormatMap = (
    'rhapsody - streams'      => RPS::File::Sale::FORMAT_STREAM,
    'xbox music \(zune\)'     => RPS::File::Sale::FORMAT_STREAM,
    'amazonmp3 cloud us'      => RPS::File::Sale::FORMAT_STREAM,
    'amazonmp3 us'            => RPS::File::Sale::FORMAT_DOWNLOAD,
    'amazon cloud us'         => RPS::File::Sale::FORMAT_DOWNLOAD,
    'itunes match (us|ca|mx)' => RPS::File::Sale::FORMAT_STREAM,
    'itunes (us|ca|mx)'       => RPS::File::Sale::FORMAT_DOWNLOAD,
    'last.fm - (interactive|radio)'                 => RPS::File::Sale::FORMAT_STREAM,
    'slacker - (basic|plus|premium) radio service'  => RPS::File::Sale::FORMAT_STREAM,
    'zune - monthly zune pass 15 plus 10'           => RPS::File::Sale::FORMAT_STREAM,
    'amazon cloud us'         => RPS::File::Sale::FORMAT_DOWNLOAD,
    'medianet digital'        => RPS::File::Sale::FORMAT_STREAM,
    'amazonmp3'               => RPS::File::Sale::FORMAT_DOWNLOAD,
    'emusic (ca|us)'          => RPS::File::Sale::FORMAT_DOWNLOAD,
);

#public methods

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

    my $lines = $args{lines};
    my $version = $args{file}->VersionNum();
    my $fileName = $args{file}->OrigFileName();
    my @sheets = @{ $args{sheets} };

    return undef unless ($lines);

    my $linenum = 1;
    
    my $offsets = $field_map{$version};
    my %errors = ();
     
    foreach my $line(@$lines)
    {       
        my $countryName = lc $line->[ $offsets->{country} ];
        if ($countryName eq 'country of sale')  # skip header
        {
            $linenum++;
            next;
        }

        my $serviceName = $line->[ $offsets->{service} ];
        my $serviceID;
        
        if($serviceName){
            $serviceID = $self->getServiceID( $serviceName ) || $RPS::Import::ServiceMap::SERVICE_ALIASES{ lc $serviceName };
        }
        
        my $album  = $line->[ $offsets->{album} ];
        my $track  = $line->[ $offsets->{track} ];
        

        next if ($countryName =~ m/^$/ && $album =~ m/^$/ && $track =~ m/^$/); # blank lines at eof

        my $countryCode;
        if ( $countryName )
        {
            my $countryObj = Common::Country->Get( $countryName );
            $countryCode = $countryObj->alpha2() if( $countryObj );

            if(!$countryCode || '' eq $countryCode)
            {
                $self->errstr("Unknown country '$countryName' in line:".$linenum);
                return undef;
            }
        }
        else
        {
            $self->errstr("Missing country in line:".$linenum);
            return undef;
        }

        if(!$countryName || '' eq $countryName) {
            $self->errstr("Missing country in line:".$linenum);
            return undef;
        }

        my ($dateBegin, $dateEnd) = $self->_getDates($line->[ $offsets->{year} ], 
        $line->[ $offsets->{month} ]);     
        
        my $artist = $line->[ $offsets->{artist} ];
               
        my $catalog_number = $line->[ $offsets->{catalog_number} ];
        
        my $upc    = Common::Util::normalize_upc($line->[ $offsets->{upc} ]);
        my $isrc   = Common::Util::normalize_isrc($line->[ $offsets->{isrc} ]);
        my ($units)       = $line->[ $offsets->{units} ];
        my $revenue = $line->[ $offsets->{revenue} ];
        
        my $product_type;
        my $format_type = $serviceName ? $self->_getFormatType( $serviceName ) : undef;

        if( $isrc )
        {
            $product_type = RPS::File::Sale::TYPE_TRACK;
        }
        else
        {
            $product_type = RPS::File::Sale::TYPE_ALBUM;
            if( $track && '' ne $track )
            {
                $album = $track; # Use track name as album name (FB17250)
                undef $track;
            }
        }
        
        my $price = 0;
        
        $price = $revenue / $units if($units != 0);
        
        if ($units =~ /\d+/ && ($track || $album) && defined $price && $artist) 
        {
            if( $price < 0 && $units > 0 ) # returns
            {
                $price = abs($price);
                $units *= -1;
            }

            if( !$format_type && !$serviceName )
            {
                # From Case 1967
                # If blank & product = track & PPU < .50 = DTeth.  If Blank + product = track + PPU > .51 = D.  
                # If blank & product = album & PPU < 3 = DTeth.  If Blank + product = album + PPU > 3.01 = D.  
                my $ppu = $price / $units;  # recall, price is _net_ revenue
                if( $product_type eq RPS::File::Sale::TYPE_TRACK )
                {
                    $format_type = ( abs($ppu) <= 0.50 ) ? RPS::File::Sale::FORMAT_TETHERED : RPS::File::Sale::FORMAT_DOWNLOAD;
                }
                elsif( $product_type eq RPS::File::Sale::TYPE_ALBUM )
                {
                    $format_type = ( abs($ppu) <= 3 ) ? RPS::File::Sale::FORMAT_TETHERED : RPS::File::Sale::FORMAT_DOWNLOAD;
                }

            }

            unless ($countryCode or exists $errors{$countryName}) {
                $self->errstr('unknown country:'.$countryName . " line:".$linenum);
                print STDERR "country: '$countryName' line: $linenum\n";
                $errors{$countryName} = 1;
            }
            unless ($dateBegin && $dateEnd) {
                $self->errstr("couldn't get dates");
                print STDERR 'y,m: ', $line->[ $offsets->{year} ], ',', $line->[ $offsets->{month} ], "\n";
                return undef;
            }
            
            if($serviceName){
            
                unless ($serviceID) {
                    unless ($errors{$serviceName}) {
                        $self->errstr('Unknown service:'.$serviceName);
                        print STDERR "Unknown service: '$serviceName'\n";
                        $errors{$serviceName} = 1;
                    }
                }
            }
            my $sale = RPS::Import::SaleRec->new();

            $sale->serviceID($serviceID) if ($serviceName);
            $sale->dateBegin($dateBegin);
            $sale->dateEnd($dateEnd);
            $sale->upc($upc);
            $sale->isrc($isrc) if( $product_type eq RPS::File::Sale::TYPE_TRACK );
            $sale->artistName($artist);
            $sale->albumName($album);
            $sale->trackName($track) if( $product_type eq RPS::File::Sale::TYPE_TRACK );
            $sale->units($units);
            $sale->price($price);
            $sale->productType($product_type);
            $sale->formatType($format_type);
            $sale->lineNum($linenum);
            $sale->countryCode($countryCode);
            $sale->clientProductID($catalog_number);

            #$args{dumper}($sale);  ## for cmd-line testing
            $self->_insertSale(sale => $sale);
        }
            $linenum++;
        
        }
        
        
    

    return $linenum;
}



#
# Private methods
#

sub _getFormatType {
    my $self = shift;
    my $serviceName = shift;
    my $_format;

    # New and improved format type rules (see Case 1967):
    #
    # If service name ends in 
    #   streams = DS
    #   downloads = D
    #   basic = Dteth
    #   plays = DS
    #   MediaNet Digital - albums = D
    #   Mix and Burn = D
    #   Napster - ads = DS
    #   Napster - OTA = D
    #   Navio / gBox = D
    #   Passalong = D
    #   Pure Tracks = D
    #   Ruckus Network - university = DS
    #   SecuryCast Download = D
    #   Slacker - basic = DS
    #   Slacker - premium = DS
    #   T-Online = D
    #   Verizon = D
    #   Spring = D
    #   Sprint = D
    #   Rogers Wireless - subscriptions = DTeth
    #   Napster - download = D
    #   Rogers Wireless - subscriptions = D
    #   Virginmega.fr = D

    # If blank & product = track & PPU < .50 = DTeth.  If Blank + product = track + PPU > .51 = D.  
    # If blank & product = album & PPU < 3 = DTeth.  If Blank + product = album + PPU > 3.01 = D.  

    if( $serviceName =~ /streams$/i ) # = DS
    {
        $_format = RPS::File::Sale::FORMAT_STREAM;
    }
    elsif( $serviceName =~ /downloads$/i ) # = D
    {
        $_format = RPS::File::Sale::FORMAT_DOWNLOAD;
    }
    elsif( $serviceName =~ /basic$/i ) # = Dteth
    {
        $_format = RPS::File::Sale::FORMAT_TETHERED;
    }
    elsif( $serviceName =~ /plays$/i ) # = DS
    {
        $_format = RPS::File::Sale::FORMAT_STREAM;
    }
    elsif( $serviceName =~ /MediaNet Digital - albums$/i ) # = D
    {
        $_format = RPS::File::Sale::FORMAT_DOWNLOAD;
    }
    elsif( $serviceName =~ /Mix and Burn$/i ) # = D
    {
        $_format = RPS::File::Sale::FORMAT_DOWNLOAD;
    }
    elsif( $serviceName =~ /Napster - ads$/i ) # = DS
    {
        $_format = RPS::File::Sale::FORMAT_STREAM;
    }
    elsif( $serviceName =~ /Napster - OTA$/i ) # = D
    {
        $_format = RPS::File::Sale::FORMAT_DOWNLOAD;
    }
    elsif( $serviceName =~ /Navio \/ gBox$/i ) # = D
    {
        $_format = RPS::File::Sale::FORMAT_DOWNLOAD;
    }
    elsif( $serviceName =~ /Passalong$/i ) # = D
    {
        $_format = RPS::File::Sale::FORMAT_DOWNLOAD;
    }
    elsif( $serviceName =~ /Pure Tracks$/i ) # = D
    {
        $_format = RPS::File::Sale::FORMAT_DOWNLOAD;
    }
    elsif( $serviceName =~ /Ruckus Network - university$/i ) # = DS
    {
        $_format = RPS::File::Sale::FORMAT_STREAM;
    }
    elsif( $serviceName =~ /SecuryCast Download$/i ) # = D
    {
        $_format = RPS::File::Sale::FORMAT_DOWNLOAD;
    }
    elsif( $serviceName =~ /Slacker - basic$/i ) # = DS
    {
        $_format = RPS::File::Sale::FORMAT_STREAM;
    }
    elsif( $serviceName =~ /Slacker - premium$/i ) # = DS
    {
        $_format = RPS::File::Sale::FORMAT_STREAM;
    }
    elsif( $serviceName =~ /T-Online$/i ) # = D
    {
        $_format = RPS::File::Sale::FORMAT_DOWNLOAD;
    }
    elsif( $serviceName =~ /Verizon$/i ) # = D
    {
        $_format = RPS::File::Sale::FORMAT_DOWNLOAD;
    }
    elsif( $serviceName =~ /Spring$/i ) # = D
    {
        $_format = RPS::File::Sale::FORMAT_DOWNLOAD;
    }
    elsif( $serviceName =~ /Sprint/i ) # = D
    {
        $_format = RPS::File::Sale::FORMAT_DOWNLOAD;
    }
    elsif( $serviceName =~ /Rogers Wireless - subscriptions/i ) # = DTeth
    {
        $_format = RPS::File::Sale::FORMAT_TETHERED;
    }
    elsif( $serviceName =~ /Napster - download/i ) # = D
    {
        $_format = RPS::File::Sale::FORMAT_DOWNLOAD;
    }
    elsif( $serviceName =~ /Rogers Wireless - subscriptions/i ) # = D
    {
        $_format = RPS::File::Sale::FORMAT_DOWNLOAD;
    }
    elsif( $serviceName =~ /virginmega.fr/i ) # = D
    {
        $_format = RPS::File::Sale::FORMAT_DOWNLOAD;
    }

    # Old-style format lookup (FB17031).
    #
#    foreach my $s (keys %gServiceFormatMap)
#    {
#        if( $serviceName =~ /$s/i )
#        {
#            $_format = $gServiceFormatMap{$s};
#            last;
#        }
#    }

    return $_format;
}

sub _getDates
{
    my $self  = shift;
    my $year  = shift;
    my $month = shift;

    my ($dateBegin, $dateEnd);
    
    if(!$year || !$month){
        return undef;
    }
    
    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_num;
     
    if((lc $month) =~ /(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/)
    {
        my $month_abbr = $1;
          
        $month_num = $months{$month_abbr};

        if(!$month_num){
            return undef;
        }

        $dateBegin = sprintf("%04d-%02d-%02d", $year, $month_num, 1);
        $dateEnd   = sprintf("%04d-%02d-%02d", $year, $month_num, Days_in_Month($year, $month_num));
    }
    elsif( $month =~ /q(\d)/i )
    {
        my $qtr = $1;

        if ($qtr == 1) {
            $dateBegin = $year."-01-01";
            $dateEnd = $year."-03-".Days_in_Month($year, 3);
        } elsif ($qtr == 2) {
            $dateBegin = $year."-04-01";
            $dateEnd = $year."-06-".Days_in_Month($year, 6);
        } elsif ($qtr == 3) {
            $dateBegin = $year."-07-01";
            $dateEnd = $year."-09-".Days_in_Month($year, 9);
        } elsif ($qtr == 4) {
            $dateBegin = $year."-10-01";
            $dateEnd = $year."-12-".Days_in_Month($year, 12);
        }

    }
     
    return ($dateBegin, $dateEnd);
}

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