package RPS::Import::MusicNet;

use strict;

use Date::Calc qw(Days_in_Month Decode_Month);

use lib '/app/tools/common/lib';
use Common::Util;
use Common::CurrencyFormat;
use Common::RSApp;

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

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

my %field_map = (
    1 => {
        'vendorid' => 0,
        'track'    => 1,
        'upc'      => 2,
        'album'    => 3,
        'artist'   => 4,
        'isrc'     => 5,
        'units'    => 6,
        'prodtype' => 7,
        'label'    => 8,
        'tracknum' => 9,
        'clientid' => 11,
        'retailer' => 12,
        'category' => 13,
    },
    2 => {
        'vendorid' => 0,
        'track'    => 1,
        'album'    => 3,
        'artist'   => 4,
        'upc'      => 5,
        'isrc'     => 6,
        'units'    => 7,
        'prodtype' => 8,
        'label'    => 9,
        'tracknum' => 12,
    },
    3 => {
        'vendorid' => 0,
        'track'    => 1,
        'album'    => 3,
        'artist'   => 4,
        'upc'      => 5,
        'isrc'     => 6,
        'units'    => 7,
        'prodtype' => 8,
        'label'    => 9,
        'tracknum' => 13,
    },
    4 => {
        'vendorid' => 0,
        'track'    => 1,
        'album'    => 3,
        'artist'   => 4,
        'upc'      => 5,
        'isrc'     => 6,
        'units'    => 7,
        'prodtype' => 8,
        'label'    => 9,
        'tracknum' => 13,
    },
    5 => {
        'vendorid' => 0,
        'track'    => 1,
        'upc'      => 2,
        'album'    => 3,
        'artist'   => 4,
        'isrc'     => 5,
        'units'    => 6,
        'prodtype' => 7,
        'label'    => 8,
        'tracknum' => 9,
        'clientid' => 11,
        'retailer' => 12,
        'category' => 13,
        'country'  => 15,
        'currency' => 16,
    },
    6 => {
        'vendorid' => 0,
        'track'    => 1,
        'album'    => 3,
        'artist'   => 4,
        'upc'      => 5,
        'isrc'     => 6,
        'units'    => 7,
        'prodtype' => 8,
        'label'    => 9,
        'tracknum' => 12,
        'country'  => 14,
        'currency' => 15,
    },
    7 => {
        'vendorid' => 0,
        'track'    => 1,
        'upc'      => 2,
        'album'    => 3,
        'artist'   => 4,
        'isrc'     => 5,
        'units'    => 6,
        'prodtype' => 7,
        'label'    => 8,
        'tracknum' => 9,
        'clientid' => 11,
        'retailer' => 12,
        'category' => 13,
        'country'  => 15,
        'currency' => 16,
        'price'    => 17,
    },
);

my %currency_map = (
    US => 'USD',
    CA => 'USD',
    GB => 'GBP',
    DE => 'GBP',
    FR => 'GBP',
);

my %service_map = (
    "DigitalMedia 2.0"        => Client::Service::DSP_DIGITAL_MEDIA_2_0,
    "DigitalMedia Canada 2.0" => Client::Service::DSP_DIGITAL_MEDIA_2_0,
    "DigitalMedia GB 2.0"     => Client::Service::DSP_DIGITAL_MEDIA_2_0,
    "MOG Australia"           => Client::Service::DSP_MOG,
    "DMGB"                    => Client::Service::DSP_DMGB,
);

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

#public methods

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

    my $retval   = undef;
    my $lines    = $args{lines};
    my $fileObj  = $args{file};
    my $fileName = $fileObj->OrigFileName;
    my $version  = $fileObj->VersionNum;

    return undef unless ( $lines && $fileName && $version );

    my $offsets = $field_map{$version};

    ## category only applies to version 1, so everything using it
    ## will only be applied if category field is present in file
    my $loggableCategory = '^(NORMAL|TRIAL)$';

    my ( $countryCode, $dateBegin, $dateEnd );
    if ( $version == 1 && $fileName =~ m/^(GB|US|CA)?.*(20\d\d-\d\d-01)_(20\d\d-\d\d-\d\d)/ ) {
        ( $countryCode, $dateBegin, $dateEnd ) = ( $1, $2, $3 );
    } elsif ( $fileName =~ m/BPMediaNet(\w{3})(\d{2})(Tracks|Albums|Streams)/ ) {
        my $year  = $2 + 2000;
        my $month = Decode_Month($1);
        $dateBegin = $year . "-" . $month . "-1";
        $dateEnd = $year . "-" . $month . "-" . Days_in_Month( $year, $month );
    } elsif ( $fileName =~ m/(\d\d)(\d\d)(\d{4})_(\d\d)(\d\d)(\d{4})/ ) {
        $dateBegin = $3 . "-" . $1 . "-" . $2;
        $dateEnd   = $6 . "-" . $4 . "-" . $5;
    } elsif ( $fileName =~ m/(20\d\d-\d\d-01)[ |_](20\d\d-\d\d-\d\d)/ ) {
        $dateBegin = $1;
        $dateEnd   = $2;
    } elsif ( $fileName =~ m/(\w+) (20\d\d) PD\.(xls|csv|txt)/i ) {
        my $year  = $2;
        my $month = Decode_Month($1);
        $dateBegin = $year . "-" . sprintf( "%02d", $month ) . "-01";
        $dateEnd = $year . "-" . sprintf( "%02d", $month ) . "-" . Days_in_Month( $year, $month );
        $countryCode = "US";
    } elsif ( $fileName =~ m/(20\d\d) (\w+) (\w+)\.(xls|csv|txt)/i ) {
        my $year  = $1;
        my $month = Decode_Month($2);
        $dateBegin = $year . "-" . sprintf( "%02d", $month ) . "-01";
        $dateEnd = $year . "-" . sprintf( "%02d", $month ) . "-" . Days_in_Month( $year, $month );
        $countryCode = "US";
    } elsif ( $fileName =~ m/(20\d\d) (\w+)\.(xls|csv|txt)/i ) {
        my $year  = $1;
        my $month = Decode_Month($2);
        $dateBegin = $year . "-" . sprintf( "%02d", $month ) . "-01";
        $dateEnd = $year . "-" . sprintf( "%02d", $month ) . "-" . Days_in_Month( $year, $month );
        $countryCode = "US";
    }

    unless ( $dateBegin && $dateEnd ) {
        $self->errstr("couldn't get dates");
        print STDERR "filename: $fileName\n";
        return undef;
    }

    my $currencyCode;
    my %errors  = ();
    my $linenum = 1;

    foreach my $line (@$lines) {
        if ( $linenum == 1 ) {
            $linenum++;
            next;
        }

        unless ($line->[ $offsets->{'units'} ] && ($line->[ $offsets->{'album'}] || $line->[ $offsets->{'track'} ])) {
            print STDERR "Skipping line: $linenum\n";
            next;
        }

        my ($prodtype, $format, $mediatype);

        if (
            $line->[ $offsets->{'prodtype'} ] =~ /streams/i
            &&
            ## only check if category present in this version
            ( !( defined $offsets->{'category'} ) || $line->[ $offsets->{'category'} ] =~ m/$loggableCategory/i )
          ) {
            $prodtype = RPS::File::Sale::TYPE_TRACK;
            $format   = RPS::File::Sale::FORMAT_STREAM;
        }
        if (
            $line->[ $offsets->{'prodtype'} ] =~ m/^Play ?Counts$/i
            &&
            ## only check if category present in this version
            ( !( defined $offsets->{'category'} ) || $line->[ $offsets->{'category'} ] =~ m/$loggableCategory/i )
          ) {
            $prodtype = RPS::File::Sale::TYPE_TRACK;
            $format   = RPS::File::Sale::FORMAT_TETHERED;
        }
        if (
            $line->[ $offsets->{'prodtype'} ] =~ /Device Play Counts/i
            &&
            ## only check if category present in this version
            ( !( defined $offsets->{'category'} ) || $line->[ $offsets->{'category'} ] =~ m/$loggableCategory/i )
          ) {
            $prodtype = RPS::File::Sale::TYPE_TRACK;
            $format   = RPS::File::Sale::FORMAT_TETHERED;
        } elsif ( $line->[ $offsets->{'prodtype'} ] =~ m/^Permanent Albums$/i ) {
            $prodtype = RPS::File::Sale::TYPE_ALBUM;
            $format   = RPS::File::Sale::FORMAT_DOWNLOAD;
        } elsif ( $line->[ $offsets->{'prodtype'} ] =~ /Permanent MP3 Albums/i ) {
            $prodtype = RPS::File::Sale::TYPE_ALBUM;
            $format   = RPS::File::Sale::FORMAT_DOWNLOAD;
            $mediatype = RPS::DB::Item::MediaType::kMediaTypeAudio;
        } elsif ( $line->[ $offsets->{'prodtype'} ] =~ /Permanent MP3 A la Carte Tracks/i ) {
            $prodtype = RPS::File::Sale::TYPE_TRACK;
            $format   = RPS::File::Sale::FORMAT_DOWNLOAD;
            $mediatype = RPS::DB::Item::MediaType::kMediaTypeAudio;
        } elsif ( $line->[ $offsets->{'prodtype'} ] =~ m/^Permanent A ?la Carte Tracks$/i ) {
            $prodtype = RPS::File::Sale::TYPE_TRACK;
            $format   = RPS::File::Sale::FORMAT_DOWNLOAD;
        } elsif ( $line->[ $offsets->{'prodtype'} ] =~ /^Permanent AAC\+ A la Carte Tracks$/i ) {
            $prodtype = RPS::File::Sale::TYPE_TRACK;
            $format   = RPS::File::Sale::FORMAT_DOWNLOAD;
            $mediatype = RPS::DB::Item::MediaType::kMediaTypeAudio;
        } elsif ( $line->[ $offsets->{'prodtype'} ] =~ m/^Permanent Album Tracks$/i ) {
            $prodtype = RPS::File::Sale::TYPE_TRACK;
            $format   = RPS::File::Sale::FORMAT_DOWNLOAD;
        } elsif ( $line->[ $offsets->{'prodtype'} ] =~ m/^Permanent Downloads$/i ) {
            $prodtype = RPS::File::Sale::TYPE_TRACK;
            $format   = RPS::File::Sale::FORMAT_DOWNLOAD;
        } elsif ( $line->[ $offsets->{'prodtype'} ] =~ m/^Permanent Subscription Token Tracks$/i ) {
            $prodtype = RPS::File::Sale::TYPE_TRACK;
            $format   = RPS::File::Sale::FORMAT_DOWNLOAD;
        } elsif ( $line->[ $offsets->{'prodtype'} ] =~ /^Permanent AAC\+ Albums$/i ) {
            $prodtype = RPS::File::Sale::TYPE_ALBUM;
            $format   = RPS::File::Sale::FORMAT_DOWNLOAD;
            $mediatype = RPS::DB::Item::MediaType::kMediaTypeAudio;
        } else {
            die "Unknown Product Type: '" . $line->[ $offsets->{'prodtype'} ] . "', Line: $linenum";
        }

        my $vendorID   = $line->[ $offsets->{'vendorid'} ];
        my $clientID   = ( $offsets->{'clientid'} ) ? $line->[ $offsets->{'clientid'} ] : undef;
        my $upc        = Common::Util::normalize_upc( $line->[ $offsets->{'upc'} ] );
        my $isrc       = Common::Util::normalize_isrc( $line->[ $offsets->{'isrc'} ] );
        my $artist     = $line->[ $offsets->{'artist'} ];
        my $album      = $line->[ $offsets->{'album'} ];
        my $track      = $line->[ $offsets->{'track'} ];
        my $label      = $line->[ $offsets->{'label'} ];
        my ($tracknum) = $line->[ $offsets->{'tracknum'} ] =~ m/^(\d+)$/;
        my ($units)    = $line->[ $offsets->{'units'} ] =~ m/^(-?\d+)$/;

        my $price = ( $offsets->{'price'} ) ? $line->[ $offsets->{'price'} ] : undef;

        if ( defined $offsets->{country} ) {
            $countryCode = $line->[ $offsets->{'country'} ];

            if ( $version == 8 ) {
                $currencyCode = 'USD';
            } else {
                if ( $countryCode eq "" ) {
                    $currencyCode = Common::Client::Current()->Locale()->currencyFormat()->currencyCode();
                } else {
                    my $currencyFormat = Common::CurrencyFormat->new( countryCode => $countryCode );
                    $currencyCode = $currencyFormat->currencyCode();
                }
            }
        }

        my $free = 0;
        ## only check category if version 1
        $free = 1
          if (  ( defined $offsets->{'category'} )
            and $line->[ $offsets->{'category'} ] =~ m/^TRIAL$/i
            and ( $format eq RPS::File::Sale::FORMAT_STREAM or $format eq RPS::File::Sale::FORMAT_TETHERED ) );

        #$free = 1 if(defined $offsets->{'category'} && $line->[$offsets->{'category'}] =~ /trial/i);

        if ( $prodtype && $units && ( $artist || $album || $track ) ) {
            unless ( $currencyCode ne "" && $countryCode ne "" ) {
                $self->errstr( "Could not find country/currency: " . $countryCode . " line:" . $linenum );
                print STDERR "Could not find country/currency: " . $countryCode . " line:" . $linenum . "\n";
                return undef;
            }

            my $serviceID;
            if ( defined $offsets->{retailer} ) {
                my $serviceName = $line->[ $offsets->{retailer} ];
                $serviceName =~ s/\s+(US|CANADA|CA|UK|FR|DE)$//i;

                $serviceID = $self->_get_service_id($serviceName);

                if ( !$serviceID ) {
                    $serviceID = $service_map{$serviceName};
                }

                unless ($serviceID) {
                    unless ( $errors{$serviceName} ) {
                        die "unknown service '$serviceName', line:$linenum";
                    }
                }
            }

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

            $sale->serviceID($serviceID) if $serviceID;
            $sale->productType($prodtype);
            $sale->formatType($format);
            $sale->dateBegin($dateBegin);
            $sale->dateEnd($dateEnd);
            $sale->serviceProductID($vendorID);
            $sale->clientProductID($clientID);
            $sale->upc($upc);
            $sale->isrc($isrc);
            $sale->artistName($artist);
            $sale->albumName($album);
            $sale->trackName($track);
            $sale->labelName($label);
            $sale->trackNum($tracknum);
            $sale->units($units);
            $sale->currencyCode($currencyCode);
            $sale->countryCode($countryCode);
            $sale->lineNum($linenum);
            $sale->free($free);
            $sale->price($price);
            $sale->mediaType($mediatype);

            $self->_insertSale( sale => $sale );
        }    #else { print STDERR "skip l: $linenum p: $prodtype u: $units r: $artist a: $album t: $track\n" . join(",",@$line) . "\n"; }
        $linenum++;
    }

    return $linenum;
}

#
# Private methods
#

sub _get_service_id {
    my $self        = shift;
    my $serviceName = lc shift;

    # minor adjustments to help the decorated service name match ours
    $serviceName =~ s/mtvn/mtv_networks/;

    return $self->getServiceID($serviceName) || $RPS::Import::ServiceMap::SERVICE_ALIASES{ lc $serviceName };
}

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