package RPS::Import::KochDigital;

use strict;
use warnings;

use Date::Calc qw(Days_in_Month);
use Math::BigFloat;

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

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 base 'RPS::Import::Importer';

my %indexes = map { lc $_ => -1 } (
    'Album ID / Item #',
    'Album / Track Artist',
    'Album / Track Title',
    'Digital Provider',
    'Disc',
    'Dollars',
    'Format',
    'Units',
    'UPC / ISRC #',
);
# Insert aliases to the above in here:
my %aliases = map lc, (
    #'Foo Bar'  => 'Original Name',
    'Album  / Track Title' => 'Album / Track Title',
		'service_product_id' => 'Album ID / Item #',
    'artist'   => 'Album / Track Artist',
    'format'   => 'Format',
    'prodcode' => 'UPC / ISRC #',
    'service'  => 'Digital Provider',
    'title'    => 'Album / Track Title',
    'units'    => 'Units',
    'price'    => 'Dollars',
);

my %format_map = (
    'track ***' =>
        [ RPS::File::Sale::TYPE_TRACK, RPS::File::Sale::FORMAT_DOWNLOAD ],
    'track download' =>
        [ RPS::File::Sale::TYPE_TRACK, RPS::File::Sale::FORMAT_DOWNLOAD ],
    'track teth download' =>
        [ RPS::File::Sale::TYPE_TRACK, RPS::File::Sale::FORMAT_TETHERED ],
    'track stream' =>
        [ RPS::File::Sale::TYPE_TRACK, RPS::File::Sale::FORMAT_STREAM ],
    'track ringtone' =>
        [ RPS::File::Sale::TYPE_TRACK, RPS::File::Sale::FORMAT_RINGTONE ],
    'track background' =>
        [ RPS::File::Sale::TYPE_TRACK, RPS::File::Sale::FORMAT_BACKGROUNDMUSIC ],                
    'album download' =>
        [ RPS::File::Sale::TYPE_ALBUM, RPS::File::Sale::FORMAT_DOWNLOAD ],
    'track non drm upgrade track' =>
        [ RPS::File::Sale::TYPE_TRACK, RPS::File::Sale::FORMAT_DOWNLOADUPGRADE ],
    'album high quality song' =>
        [ RPS::File::Sale::TYPE_ALBUM, RPS::File::Sale::FORMAT_DOWNLOADPREMIUM ],
    'track high quality song' =>
        [ RPS::File::Sale::TYPE_TRACK, RPS::File::Sale::FORMAT_DOWNLOADPREMIUM ],
    'album high quality playlist/album' =>
        [ RPS::File::Sale::TYPE_ALBUM, RPS::File::Sale::FORMAT_DOWNLOADPREMIUM ],
    'album non drm upgrade album' =>
        [ RPS::File::Sale::TYPE_ALBUM, RPS::File::Sale::FORMAT_DOWNLOADUPGRADE ],
    'track song' =>
        [ RPS::File::Sale::TYPE_TRACK, RPS::File::Sale::FORMAT_DOWNLOAD ],
    'track download-subscription' =>
        [ RPS::File::Sale::TYPE_TRACK, RPS::File::Sale::FORMAT_VPD ],
    'track burn' =>
        [ RPS::File::Sale::TYPE_TRACK, RPS::File::Sale::FORMAT_DOWNLOAD ],
    'album download-subscription' =>
        [ RPS::File::Sale::TYPE_ALBUM, RPS::File::Sale::FORMAT_VPD ],
    'album playlist upgrade' =>
        [ RPS::File::Sale::TYPE_ALBUM, RPS::File::Sale::FORMAT_DOWNLOADUPGRADE ],
    'track video teth downl' =>
        [ RPS::File::Sale::TYPE_TRACK, RPS::File::Sale::FORMAT_TETHERED ],
    'track audio ad support/stream' =>
        [ RPS::File::Sale::TYPE_TRACK, RPS::File::Sale::FORMAT_STREAM ],
);

#
# This map is no longer used.  Calling the function getServiceID instead.
my %service_map = map lc, (
    AltNet         => Client::Service::DSP_ALTNET,
    BuyMusic       => Client::Service::DSP_BUYMUSIC,
    eMusic         => Client::Service::DSP_EMUSIC,
    iTunes         => Client::Service::DSP_ITUNES,
    'Liquid Audio' => Client::Service::DSP_LIQUIDAUDIO,
    MusicMatch     => Client::Service::DSP_MUSICMATCH,
    MusicNet       => Client::Service::DSP_MEDIANET,
    MusicNow       => Client::Service::DSP_MUSICNOW,
    Napster        => Client::Service::DSP_NAPSTER,
    Real           => Client::Service::DSP_REAL,
    "musicgiant"   => Client::Service::DSP_MUSICGIANTS,
    "hdtracks"     => Client::Service::DSP_HDTRACKS,
);

my %format_errors;

#public methods

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

	  my $fileObj = $args{file};
    my $fileName = $fileObj->OrigFileName;
    ##my $fileName = $args{OrigFileName}; ## for cmd-line testing
    

    my $lines = $args{lines};

    my $linenum = 1;
    my $headerFound = 0;  
    
    my $fileDate;  
    
    while (my $line = shift @$lines) {
        my @elements = map { Common::Util::trimspaces($_) } @$line;
        my $elementnum = 0;
        for my $element (@elements) {
            my $e = lc $element;
            
            # We can also find the date through regex,
            # but it seems to make the import run a lot slower.
            #if ($e =~ m/^fiscal period:/) 
           	if (($linenum == 5) && ($elementnum == 2)) 
        		{
        			$fileDate = $e;
        		}
            
            if ( exists $aliases{$e} ) {
                $e = $aliases{$e};
            }
            if ( exists $indexes{$e} ) {
                $indexes{$e} = $elementnum;
                ++$headerFound;
            }
        }
        
        continue { $elementnum ++; }
    }
    continue 
    {
        $linenum++;

        if ($headerFound) {
            my $keyCount = scalar keys %indexes;
            if ( $headerFound != $keyCount ) {
                warn "Not all headers found, $headerFound != $keyCount:\n",
                     "Not found: ",
                     join(', ', grep { $indexes{$_} < 0 } keys %indexes);
            }

            last;
        }
    }


    #
    # First we'll check for the date in the file name
	  my ($dateBegin, $dateEnd) = $self->_getDatesFromFileName($fileName);
	
		#
		# If there's no date in the file name, we'll look in the file
    unless (defined $dateBegin && defined $dateEnd) {
			($dateBegin, $dateEnd) = $self->_getDatesFromFile($fileDate);
    }
    
    #
    # If there's no date in the file name or file, then game over, man.
    unless (defined $dateBegin && defined $dateEnd) {
        print STDERR "Couldn't get dates from: ". $fileName . "\n";
        $self->errstr("couldn't get dates from: ". $fileName);
        return undef;
    }


    foreach my $line (@$lines)
    {
        my $artist   = $line->[ $indexes{ $aliases{artist}   } ];
        my $format   = $line->[ $indexes{ $aliases{format}   } ];
        my $price    = $line->[ $indexes{ $aliases{price}    } ];
        my $prodcode = $line->[ $indexes{ $aliases{prodcode} } ];
        my $serviceName  = $line->[ $indexes{ $aliases{service}  } ];
        my $title    = $line->[ $indexes{ $aliases{title}    } ];
        my $units    = $line->[ $indexes{ $aliases{units}    } ];
        my $serviceProductID    = $line->[ $indexes{ $aliases{service_product_id}    } ];

        unless ($artist && $serviceName && $title && $units) {
            next;
        }

        my $prodtype = $format_map{ lc $format };
        
        if (!$prodtype && !$format_errors{$format}) {
            $self->errstr("Unknown format '$format'");
            print STDERR "Uknown format: '$format\n'";
            $format_errors{$format} = 1;
            next;
            #return;
        }
        elsif(!$prodtype){
            next;
        }
        
        ($prodtype, $format)  = @{ $prodtype };
        

	
	my $service = $self->_get_service_id($serviceName);
	
	unless($service){
	    #print STDERR "Using service map: X".lc($serviceName)."X\n";
	    $service = $service_map{lc $serviceName};
	}
	
        #$service = $service_map{ lc $service };
        unless ($service) {
            $self->errstr("Unknown service '$serviceName'");
            return;
        }


        # Figure out if this is whole album info, or just single track info:
        my ($album, $upc);
        my ($track, $trackNum, $isrc);
        if ( $prodtype eq RPS::File::Sale::TYPE_TRACK ) {
            ($trackNum, $track)
                = $title =~ /^\s*Track:?\s*(\d+)\s*[:-]\s*(.*)/;
            $isrc = $prodcode;
        }
        elsif ( $prodtype eq RPS::File::Sale::TYPE_ALBUM ) {
            $album = $title;
            $upc   = $prodcode;
        }
        else {
            $self->errstr("Unknown product type '$prodtype'");
            return;
        }


        if ( 0 != $units )
        {
            $price = Math::BigFloat->new($price);
        }
        else
        {
            $price = 0;
        }

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

        $sale->albumName($album) if ($album);
        $sale->artistName($artist);
        # averagePrice channel clientProductID
        # configuration conversionRate countryCode
        # currencyCode
        $sale->dateBegin($dateBegin);
        $sale->dateEnd($dateEnd);
        $sale->formatType($format);
        # free importStatus
        $sale->isrc($isrc) if ($isrc);
        # labelName
        $sale->lineNum($linenum);
        # outlet payoutType
        $sale->price($price / $units);
        # priceLevel priceType
        $sale->productType($prodtype);
        # retail returns returnsRevenue
        # sales salesRevenue
        $sale->serviceID($service);
        # serviceProductID totalRevenue
        $sale->trackName($track) if ($track);
        $sale->trackNum($trackNum) if ($trackNum);
        $sale->units($units);
        $sale->upc($upc) if ($upc);
        $sale->serviceProductID($serviceProductID);
        # wholesaleRate
        
        if ($serviceName =~ /Canada/)
        {
        	$sale->countryCode('CA');
      	}
      	else{
      	        $sale->countryCode('US');
      	}

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

    return $linenum;
}

#
# Private methods
#

my %month_map = (
    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 = '(?:' . join('|', sort keys %month_map) . ')';
my $YY    = qr/[0-9]{2}/;

sub _getDatesFromFileName {
	my $self  = shift;
	my $fname = shift;
    return unless ( $fname =~ m/^BN($MONTH)($YY)digital/ );

    my $month = $month_map{$1};
    my $year  = 2000 + $2;

    my $month_end = Days_in_Month( $year, $month );

    my $format    = '%4d-%02d-%02d';
    my $beginDate = sprintf( $format, $year, $month, 1 );
    my $endDate   = sprintf( $format, $year, $month, $month_end );

    return ($beginDate, $endDate);
}

sub _getDatesFromFile {
	
		# This is what get's passed in:
		# fiscal period: 200804 thru: 200806
		
		my $self  = shift;
		my $date = shift;
	  return unless ( $date =~ m/^fiscal period: (\d{6}) thru: (\d{6})$/ );
	
		my $beginYear = substr($1,0,4);
	  my $beginMonth = substr($1,4,2);
	
		my $endYear = substr($2,0,4);
	  my $endMonth = substr($2,4,2);
	
	  my $endMonthEnd = Days_in_Month( $endYear, $endMonth );
	
	  my $format    = '%4d-%02d-%02d';
	  my $beginDate = sprintf( $format, $beginYear, $beginMonth, 1 );
	  my $endDate   = sprintf( $format, $endYear, $endMonth, $endMonthEnd );
	
	  return ($beginDate, $endDate);
}

sub _get_service_id
{
    my $self = shift;
    my $serviceName = lc shift;
    
    # minor adjustments to help the service name match ours
    $serviceName =~ s/ canada//;   
    $serviceName =~ s/ us//;
    $serviceName =~ s/ uk//;
    $serviceName =~ s/Mix and Burn/mix_burn/i; 

    return $self->getServiceID($serviceName);
}

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