package RPS::Import::ADA::v12;

use strict;


use lib '/app/tools/common/lib';
use Common::Util qw(normalize_date normalize_upc);
use Date::Calc qw(Days_in_Month Decode_Month);
use Data::Dumper;

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

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

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

# non-standard _fieldMap; need to override _importLines
sub _fieldMap {
    {
        'domestic' => {
            label           => 28, # AC 
            serviceName     => 2,  # C
            dateBegin       => 3,  # D
            dateEnd         => 4,  # E
            productType     => 17, # R
            formatType      => 41, # AP
            artistName      => 7,  # H
            upc             => 20, # U
            albumName       => 22, # W
            isrc            => 18, # S
            trackName       => 9,  # J
            units           => 10, # K  
            price           => 15, # P
            mediaType       => 17, # R
            mediaCode       => 41, # AP
            streamFlag      => 44, # AS                                 
        },
        'international' => {
            label           => 0,  # A 
            serviceName     => 5,  # F
            countryCode     => 7,  # H

            productType     => 9,  # J
            formatType      => 9,  # J           
            mediaType       => 9,  # J

            artistName      => 1,  # B

            albumName       => 2,  # C
            trackName       => 2,  # C

            isrc            => 3,  # D
            upc             => 3,  # D

            units           => 11, # L
            price           => 12, # M
        },        
    }
}


my %mediaCodeMap = (
   'DRMUPGR' => {
      format_type  => RPS::File::Sale::FORMAT_DOWNLOADUPGRADE,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
   },
   'DUALDIST' => {
      format_type  => RPS::File::Sale::FORMAT_DUALDOWNLOAD,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
   },
   'PERMDWNL' => {
      format_type  => RPS::File::Sale::FORMAT_DOWNLOAD,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
   },
   'PERMVDLD' => {
      format_type  => RPS::File::Sale::FORMAT_DOWNLOAD,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeVideo,
   },   
   'SUBAICLD' => {
      format_type  => RPS::File::Sale::FORMAT_STREAM,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
   },
   'SUBASONE' => {
      format_type  => RPS::File::Sale::FORMAT_STREAM,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
   },
   'SUBASPPE' => {
      format_type  => RPS::File::Sale::FORMAT_STREAM,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeVideo,
   },
   'SUBVICLD' => {
      format_type  => RPS::File::Sale::FORMAT_STREAM,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeVideo,
   },
   'SUBVSONE' => {
      format_type  => RPS::File::Sale::FORMAT_STREAM,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeVideo,
   },
   'SUBVSPPE' => {
      format_type  => RPS::File::Sale::FORMAT_STREAM,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeVideo,
   },
   'UGMV' => {
      format_type  => RPS::File::Sale::FORMAT_STREAM,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeVideo,
   },
   'UGRWRMST' => {
      format_type  => RPS::File::Sale::FORMAT_RINGTONE,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
   },
   'UGV' => {
      format_type  => RPS::File::Sale::FORMAT_STREAM,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeVideo,
   },   
   'WRMST' => {
      format_type  => RPS::File::Sale::FORMAT_RINGTONE,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
   },
   'WRRNGBK' => {
      format_type  => RPS::File::Sale::FORMAT_RINGTONE,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
   },
   'WRSTREAM' => {
      format_type  => RPS::File::Sale::FORMAT_STREAM,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
   },         
);


# International delivery format mappings
#
my %deliveryFormatMap = (
   'EMASTERTONE' => {
      format_type  => RPS::File::Sale::FORMAT_RINGTONE,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
      product_type => RPS::File::Sale::TYPE_TRACK,
   },         
   'EMDALBUM' => {
      format_type  => RPS::File::Sale::FORMAT_DOWNLOAD,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
      product_type => RPS::File::Sale::TYPE_ALBUM,
   },         
   'EMDALBUMSTREAMING' => {
      format_type  => RPS::File::Sale::FORMAT_STREAM,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
      product_type => RPS::File::Sale::TYPE_ALBUM,
   },         
   'EMDTRACK' => {
      format_type  => RPS::File::Sale::FORMAT_DOWNLOAD,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
      product_type => RPS::File::Sale::TYPE_TRACK,
   },         
   'EMDTRACKSTREAMING' => {
      format_type  => RPS::File::Sale::FORMAT_STREAM,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
      product_type => RPS::File::Sale::TYPE_TRACK,
   },         
   'ERINGBACK' => {
      format_type  => RPS::File::Sale::FORMAT_RINGTONE,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
      product_type => RPS::File::Sale::TYPE_TRACK,
   },         
   'EVD' => {
      format_type  => RPS::File::Sale::FORMAT_DOWNLOAD,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeVideo,
      product_type => RPS::File::Sale::TYPE_TRACK,
   },         
   'EVDSTREAMING' => {
      format_type  => RPS::File::Sale::FORMAT_STREAM,
      media_type   => RPS::DB::Item::MediaType::kMediaTypeVideo,
      product_type => RPS::File::Sale::TYPE_TRACK,
   },         
);


sub _importLines
{
    my $self = shift;
    my %args = @_;
    my $fileObj = $args{file};
    my $version = $args{file}->VersionNum();
    my $fileName = $args{file}->OrigFileName();

    my $offsets = $self->_fieldMap;

    my $sheet_count = 0;
    my ($linenum,$serviceID);

    return undef unless (defined $args{sheets} && defined $version);

    my $sheet_names = $args{sheet_names};

    my $currencyCode = 'USD';

    foreach my $sheet(@{ $args{sheets} })
    {

        my $sheetName = $sheet_names->[$sheet_count];

        my $sheetIndex = $self->_normalizeSheetName( lc $sheetName );

        if ( ! exists $offsets->{ $sheetIndex } )
        {
            print STDERR "ADABase: Illegal sheet '$sheetName'\n";
            $self->errstr("Sheet '$sheetName' is not valid");
            return undef;
        }

        my $data = $offsets->{$sheetIndex};
        
        my ($gDateBegin, $gDateEnd);
        if (! defined $data->{dateBegin} )
        {                
            ($gDateBegin, $gDateEnd) = $self->_getDatesFromFileName($fileName); 
        }
        
        $linenum = 1;
        foreach my $line(@{ $sheet })
        {

            my $sn = $sheet_count + 1; # sheet number (1-based)
            my $lineInfo = "Sheet $sn, line $linenum";

            my $serviceName = $line->[$data->{serviceName}];

            # Skipping header
            #
            if ( !$serviceName ||
                ( $serviceName && '' eq $serviceName ) ||            
                ( $serviceName && ('vendor' eq lc($serviceName)) ) ||
                ( $serviceName && ('provider' eq lc($serviceName) ) ))
            {
                $linenum++;
                next;
            }
          
            my $countryCode;
            if ( defined $data->{countryCode} )
            {
                $countryCode = $line->[$data->{countryCode}];     
            }
            else
            {
                $countryCode = 'US';   
            }
          
          

            my $productType;
            my $formatType;
            my $mediaType;

            if ( defined $data->{mediaCode} )
            {
                # Domestic Sales
                #
                my $mediaCode       = $line->[$data->{mediaCode}];
                if ( $mediaCode )
                {
                    $formatType  = $mediaCodeMap{ uc $mediaCode }->{ format_type };
                    $mediaType   = $mediaCodeMap{ uc $mediaCode }->{ media_type };
    
                    if ( !$formatType && !$mediaType )
                    {
                        $self->errstr("$lineInfo: Unknown media code '$mediaCode'");
                        return undef;
                    }
                }
                else
                {
                    $self->errstr("$lineInfo: Media Code not found");
                    return undef;
                }            
            

                my $_productType  = uc $line->[$data->{productType}];

                if( $_productType eq 'D' || $_productType eq 'P' || $_productType eq 'T' || $_productType eq 'S' )
                {
                    $productType = RPS::File::Sale::TYPE_TRACK;
                }
                elsif( $_productType eq 'A' )
                {
                    $productType = RPS::File::Sale::TYPE_ALBUM;
                }
                else
                {
                    $self->errstr("$lineInfo: Unknown product type '$_productType'");
                    return undef;
                }

            }
            else
            {
                # International Sales
                #
                my $deliveryFormat = $line->[$data->{productType}];

                $formatType  = $deliveryFormatMap{ uc $deliveryFormat }->{ format_type };
                $mediaType   = $deliveryFormatMap{ uc $deliveryFormat }->{ media_type };
                $productType = $deliveryFormatMap{ uc $deliveryFormat }->{ product_type };

                if( !$productType )
                {
                    $self->errstr("$lineInfo: Unknown product type '$deliveryFormat'");
                    return undef;
                }

            }
            
            my $trackName;
            my $albumName;
            my $isrc;
            my $upc;
            
            if( $productType eq RPS::File::Sale::TYPE_TRACK )
            {
                $isrc        = $line->[$data->{isrc}] if (defined $data->{isrc});  
                $trackName   = $line->[$data->{trackName}];
                
                # On the domestic sheet, album name is always included.
                #
                if ($sheetIndex eq 'domestic')
                {
                    $albumName = $line->[$data->{albumName}];
                }
            }
            elsif( $productType eq RPS::File::Sale::TYPE_ALBUM )
            {
                $albumName = $line->[$data->{albumName}];
                $upc       = $line->[$data->{upc}] if (defined $data->{upc});   
            }

            my $artistName      = $line->[$data->{artistName}];            
            my $units           = $line->[$data->{units}];       
            my $price           = $line->[$data->{price}];
            my $label           = $line->[$data->{label}]; 
            
            my ($dateBegin, $dateEnd);
            if ( defined $data->{dateBegin} )
            {
                my $saleDateBegin = _normalizeDate($line->[$data->{dateBegin}]);
                ($dateBegin, $dateEnd) = $self->_getDates(date_begin => $saleDateBegin);     
            }
            else
            {
                ($dateBegin, $dateEnd) = ($gDateBegin, $gDateEnd); 
            }             

            if ( $units && $units < 0 && $price && $price > 0 )
            {
                $self->errstr("$lineInfo: Negative units with revenue");
                return undef;
            }

            if ( !$units && $price && $price < 0 )
            {                
                # We're just going to skip this line if it has negative revenue and no units.
                $linenum++;
                next;
            }

            if( $units!=0 )
            {
                $price  /= ($units*-1) if($units<0);
                $price  /= $units if($units>0);
                if ($price < 0)
                {
                    if ($units > 0)
                    {
                        $units *= -1;
                    }
                    $price  *= -1;
                }
            }

            if(defined $data->{serviceName})
            {
                $serviceID = $self->getServiceID(lc ($serviceName)) || $RPS::Import::ServiceMap::SERVICE_ALIASES{ lc $serviceName };
                
                if (!$serviceID)
                {
                    # Trying to get the Korean names to match up...
                    my $serviceNameCopy = $serviceName;
                    $serviceNameCopy =~ s/(.|\n)/sprintf("%02lx", ord $1)/eg;  
                    $serviceID = $RPS::Import::ServiceMap::SERVICE_ALIASES{ lc $serviceNameCopy }; 
                }
            }

            if ($productType && $artistName && lc($artistName) ne "artist" && ($albumName || $trackName))
            {
                if(defined $data->{serviceName}) {
                    unless ($serviceID) {

                        if ( $serviceName =~ /[[:^ascii:]]/ ) {
                            # Case 15436 - defaulting service names with incompatible characters to ADA
                            $serviceID = Client::Service::DSP_ADA;
                        } else {
                            $self->errstr("$lineInfo: Couldn't find service ID for: ".$serviceName);
                            return undef;
                        }                  
                    }
                }

                my $sale = RPS::Import::SaleRec->new();

                $sale->productType($productType);
                $sale->formatType($formatType);
                $sale->dateBegin($dateBegin);
                $sale->dateEnd($dateEnd);
                $sale->labelName($label) if(defined $data->{label} && $label ne "");
                $sale->albumName($albumName);
                $sale->trackName($trackName);
                $sale->isrc(Common::Util::normalize_isrc($isrc)) if( $isrc );
                $sale->upc(Common::Util::normalize_upc($upc)) if( $upc );
                $sale->serviceID($serviceID) if( $serviceName );
                $sale->artistName($artistName);
                $sale->units($units);
                $sale->price($price);         
                $sale->countryCode($countryCode);                            
                $sale->currencyCode($currencyCode);                                      
                $sale->mediaType($mediaType);
                $sale->lineNum($linenum);
                
                my $free = $price == 0 ? 1 : 0;
                $sale->free($free);

                $self->_insertSale(sale => $sale);
            }
            else { print STDERR "skip s: $sheetIndex l:".$linenum." a:".$artistName." t:".$albumName." u:".$units." p:".$price."\n"; }
            $linenum++;
        }
        $sheet_count++;
    }

    return $linenum;
}

sub _normalizeSheetName {
    my $self = shift;
    my $sname = shift;
    my $name;

    $name = $sname;
    if ( $sname =~ /domestic digital/i )
    {
        $name = "domestic";
    }
    elsif ( $sname =~ /int\'l digital/i )
    {
        $name = "international";
    }    

    return $name;
}

sub _normalizeDate {
    my($dt) = @_;
    my $date = $dt;
    if ( $dt =~ m/^\d{5}$/ ) {
        $date = Spreadsheet::ParseExcel::Utility::ExcelFmt( "yyyy-mm-dd", $dt );
    }
    return $date;
}

sub _getDatesFromFileName
{
    my $self = shift;
    my $date = shift;

    my ($dateBegin, $dateEnd, $month, $year);

    if( $date =~ m/(january|february|march|april|may|june|july|august|september|october|november|december)_(\d{4})\./i )
    {
        $month = Decode_Month($1);
        $year  = $2;

#print STDERR "DEBUG: _getDatesFromFileName: fmonth($1) month($month) year($year)\n";
        $dateBegin = sprintf("%04d-%02d-%02d", $year, $month, 1);
        $dateEnd   = sprintf("%04d-%02d-%02d", $year, $month, Days_in_Month($year, $month));
    }
    elsif ($date =~ m/(\w*)\s*(\d{4})\./) {

        $month = Decode_Month($1);
        $year  = $2;

        $dateBegin = sprintf("%04d-%02d-%02d", $year, $month, 1);
        $dateEnd   = sprintf("%04d-%02d-%02d", $year, $month, Days_in_Month($year, $month));
    }
    else {
        return undef;
    }

    return ($dateBegin, $dateEnd);
}


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