package RPS::Import::ADA;

use strict;

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

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

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

my %field_map = (
    1 => {
        date_row          => 2,
        date_col          => 0,
        upc               => { 0 => 3, },
        product_code_type => { 0 => 4, },
        product_code      => { 0 => 5, },
        artist            => { 0 => 6, },
        track             => { 0 => 7, },
        units             => { 0 => 9, },
        price             => { 0 => 11, },
    },

    2 => {
        date_row          => 1,
        date_col          => 0,
        label             => 0,
        format_type       => 2,
        product_code_type => {
            digital => 6,
            wmi     => 8,
            streams => 6,
        },
        serviceName => 3,
        upc         => {
            digital => 4,
            streams => 4,
        },
        country_code => {
            wmi => 4,
        },
        product_code => {
            digital => 5,
            wmi     => 7,
            streams => 5,
        },
        artist => {
            digital => 7,
            wmi     => 5,
            streams => 7,
        },
        track => {
            digital => 8,
            wmi     => 6,
            streams => 8,
        },
        units => {
            digital => 11,
            wmi     => 11,
            streams => 10,
        },
        price => {
            digital => 13,
            wmi     => 13,
            streams => 12,
        },
    },

    3 => {
        date_row          => 1,
        date_col          => 0,
        service_name      => 0,
        format_type       => 2,
        product_code      => { 0 => 9, },
        product_code_type => { 0 => 10, },
        country_code      => { 0 => 4, },
        artist            => { 0 => 5, },
        track             => { 0 => 6, },
        units             => { 0 => 13, },
        price             => { 0 => 15, },
    },
    4 => {
        date_row          => 1,
        date_col          => 0,
        service_name      => 3,
        format_type       => 2,
        label             => 0,
        product_code_type => { 0 => 6, },
        upc               => { 0 => 4, },
        product_code      => { 0 => 5, },
        artist            => { 0 => 7, },
        track             => { 0 => 8, },
        units             => { 0 => 10, },
        price             => { 0 => 12, },
    },
    5 => {
        date_row          => 2,
        date_col          => 0,
        service_name      => 0,
        format_type       => 2,
        label             => 0,
        product_code_type => { 0 => 8, },
        product_code      => { 0 => 7, },
        country_code      => { 0 => 4, },
        artist            => { 0 => 5, },
        track             => { 0 => 6, },
        units             => { 0 => 11, },
        price             => { 0 => 13, },
    },

    # v6 is similar to v2, just a new tab (tab #1 'wireless')
    6 => {
        date_row          => 1,
        date_col          => 0,
        label             => 0,
        format_type       => 2,
        product_code_type => {
            digital  => 6,
            wireless => 6,
            wmi      => 8,
            streams  => 6,
        },
        serviceName => 3,
        upc         => {
            digital  => 4,
            wireless => 4,
            streams  => 4,
        },
        country_code => {
            wmi => 4,
        },
        product_code => {
            digital  => 5,
            wireless => 5,
            wmi      => 7,
            streams  => 5,
        },
        artist => {
            digital  => 7,
            wireless => 7,
            wmi      => 5,
            streams  => 7,
        },
        track => {
            digital  => 8,
            wireless => 8,
            wmi      => 6,
            streams  => 8,
        },
        units => {
            digital  => 11,
            wireless => 11,
            wmi      => 11,
            streams  => 10,
        },
        price => {
            digital  => 13,
            wireless => 13,
            wmi      => 13,
            streams  => 12,
        },
    },

    # v16 is similar to v6, with an extra column on the WMI tab; the other tabs
    # are identical.
    16 => {
        date_row          => 1,
        date_col          => 0,
        label             => 0,
        format_type       => 2,
        product_code_type => {
            digital  => 6,
            wireless => 6,
            wmi      => 9,
            streams  => 6,
        },
        serviceName => 3,
        upc         => {    # FIRST REL UPC
            digital  => 4,
            wireless => 4,
            streams  => 4,
            wmi      => 7,
        },
        isrc => {           # Product Identifier
            digital  => 5,
            wireless => 5,
            streams  => 5,
            wmi      => 8,
        },
        country_code => {
            wmi => 4,
        },
        product_code => {    # Product Identifier
            digital  => 5,
            wireless => 5,
            wmi      => 8,
            streams  => 5,
        },
        artist => {
            digital  => 7,
            wireless => 7,
            wmi      => 5,
            streams  => 7,
        },
        track => {
            digital  => 8,
            wireless => 8,
            wmi      => 6,
            streams  => 8,
        },
        units => {
            digital  => 11,
            wireless => 11,
            wmi      => 12,    # was column 11 in v6
            streams  => 10,
        },
        price => {
            digital  => 13,
            wireless => 13,
            wmi      => 13,
            streams  => 12,
        },
    },
);

#
# Private methods
#

sub _importLines {
    my $self        = shift;
    my %args        = @_;
    my $fileObj     = $args{file};
    my $version     = $args{file}->VersionNum();
    my $fileName    = $args{file}->OrigFileName();
    my $offsets     = $field_map{$version};
    my $sheet_count = 0;
    my ( $linenum, $serviceID );

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

    my $sheet_names = $args{sheet_names};

    # Some tabs don't have the date, so we'll declare this out here so that it can persist.
    #
    my ( $dateBegin, $dateEnd );

    foreach my $sheet ( @{ $args{sheets} } ) {
        my $sheet_name = lc( $sheet_names->[$sheet_count] );

        # Version 1 is the only one to have multiple tabs that are not named according
        # to the convention used in versions 2 and 6.  The columns are all the same, so we
        # can just use the same offsets for all of the tabs.
        # !!! Actually, versions 3-5 do not have consistent sheet names.  Since they only have one sheet,
        # !!! let's do the same thing for those.
        if ( $version == 1 || $version == 3 || $version == 4 || $version == 5 ) {
            $sheet_name = 0;
        }

        #
        # Extract the date from row 2 of each sheet (see FB13053).
        # If the date isn't found, examine the individual lines (below).
        #
        my ( $tabDateBegin, $tabDateEnd ) = $self->_getDates( $sheet->[ $offsets->{date_row} ][ $offsets->{date_col} ] );

        if ($tabDateBegin) {
            $dateBegin = $tabDateBegin;
            $dateEnd   = $tabDateEnd;
        }

        $linenum = 1;
        foreach my $line ( @{$sheet} ) {
            my $upc;
            my $isrc;

            if ( defined $offsets->{serviceName} && ( 'DSP Name' eq $line->[ $offsets->{serviceName} ] ) ) {
                $linenum++;
                next;
            }

            if ( !$dateBegin ) {
                ( $dateBegin, $dateEnd ) = $self->_getDates( $line->[ $offsets->{date_col} ] );
            }

            my $format_type  = RPS::File::Sale::FORMAT_DOWNLOAD;
            my $product_type = RPS::File::Sale::TYPE_TRACK;
            my $mediaType    = RPS::DB::Item::MediaType::kMediaTypeAudio;

            my $artist = $line->[ $offsets->{artist}->{$sheet_name} ];

            my $product_code = $line->[ $offsets->{product_code}->{$sheet_name} ] if ( defined $offsets->{product_code}->{$sheet_name} );
            my $product_code_type = $line->[ $offsets->{product_code_type}->{$sheet_name} ]
              if ( defined $offsets->{product_code_type}->{$sheet_name} );

            # Find the UPC and ISRC.  Depending on the importer version, this can be:
            #
            #    a) From a combination field (product_code) that requires another
            #       field (product_code_type) to determine if the combo field contains
            #       an ISRC or UPC, or
            #    b) From separate UPC and ISRC fields.
            #
            if ( defined $offsets->{upc}->{$sheet_name} ) {
                $upc = $line->[ $offsets->{upc}->{$sheet_name} ];
            } else {
                $upc = $product_code if ( lc($product_code_type) eq 'upc' );
            }

            if ( defined $offsets->{isrc}->{$sheet_name} ) {
                $isrc = $line->[ $offsets->{isrc}->{$sheet_name} ];
            } else {
                $isrc = $product_code if ( lc($product_code_type) eq 'isrc' );
            }

            my $track = $line->[ $offsets->{track}->{$sheet_name} ];
            my $units = $line->[ $offsets->{units}->{$sheet_name} ];
            my $price = $line->[ $offsets->{price}->{$sheet_name} ];
            my $label = $line->[ $offsets->{label} ] if ( defined $offsets->{label} );
            if ( $units != 0 ) {
                $price /= ( $units * -1 ) if ( $units < 0 );
                $price /= $units if ( $units > 0 );
                $price *= -1 if ( $price < 0 );
            }
            $format_type = RPS::File::Sale::FORMAT_STREAM
              if ( $sheet_name =~ /stream/i || $line->[ $offsets->{format_type} ] =~ /stream/i );

            if ( $line->[ $offsets->{format_type} ] =~ /evd/i ) {
                if ( $sheet_name =~ /stream/i ) {
                    $format_type = RPS::File::Sale::FORMAT_STREAM;    # was FORMAT_VIDEOSTREAM (FB1324)
                } else {
                    $format_type = RPS::File::Sale::FORMAT_DOWNLOAD;    # was FORMAT_VIDEO (FB1324)
                }
                $mediaType = RPS::DB::Item::MediaType::kMediaTypeVideo;
            }

            if ( $line->[ $offsets->{format_type} ] =~ /evdstreaming/i ) {
                $format_type = RPS::File::Sale::FORMAT_VIDEOSTREAM;         # was FORMAT_VIDEOSTREAM (FB1324)
                $mediaType   = RPS::DB::Item::MediaType::kMediaTypeVideo;
            }

            $format_type  = RPS::File::Sale::FORMAT_RINGTONE if ( $line->[ $offsets->{format_type} ] =~ /tone/i );
            $format_type  = RPS::File::Sale::FORMAT_RINGTONE if ( $line->[ $offsets->{format_type} ] =~ /wallpaper/i );
            $format_type  = RPS::File::Sale::FORMAT_RINGTONE if ( $line->[ $offsets->{format_type} ] =~ /mastertone/i );
            $format_type  = RPS::File::Sale::FORMAT_RINGTONE if ( $line->[ $offsets->{format_type} ] =~ /ringback/i );
            $product_type = RPS::File::Sale::TYPE_ALBUM      if ( $line->[ $offsets->{format_type} ] =~ /album/i );

            $isrc = "" if ( $product_type eq RPS::File::Sale::TYPE_ALBUM );

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

            if ( $units && $product_type && $price && $artist && $artist ne "Artist" && $track && $track ne "Title" ) {

                #                print STDERR "units: $units\n";
                unless ( $dateBegin && $dateEnd ) {
                    $self->errstr( "Couldn't get dates from: " . $sheet->[ $offsets->{date_row} ][ $offsets->{date_col} ] );
                    print STDERR "Couldn't get dates from: " . $sheet->[ $offsets->{date_row} ][ $offsets->{date_col} ] . "\n";
                    return undef;
                }
                if ( defined $offsets->{serviceName} ) {
                    unless ($serviceID) {

                        my $sn = $sheet_count + 1;
                        if ( $serviceName =~ /[[:^ascii:]]/ ) {
                            $serviceID = Client::Service::DSP_ADA;

                            #$self->errstr("Sheet $sn, line $linenum: Service name contains incompatible characters");
                        } else {
                            $self->errstr( "Sheet $sn, line $linenum: Couldn't find service ID for: " . $serviceName );
                            return undef;
                        }

                        #return undef;
                    }
                }
                my $sale = RPS::Import::SaleRec->new();

                $sale->productType($product_type);
                $sale->formatType($format_type);
                $sale->dateBegin($dateBegin);
                $sale->dateEnd($dateEnd);
                $sale->labelName($label) if ( defined $offsets->{label} && $label ne "" );
                if ( $product_type eq RPS::File::Sale::TYPE_ALBUM ) {
                    $sale->albumName($track);
                } else {
                    $sale->trackName($track);
                    $sale->isrc( Common::Util::normalize_isrc($isrc) ) if ( $isrc ne "" );
                }
                $sale->upc( Common::Util::normalize_upc($upc) ) if ( $upc ne "" );
                $sale->serviceID($serviceID) if ( defined $offsets->{serviceName} );
                $sale->artistName($artist);
                $sale->units($units);
                $sale->price($price);

                my $countryCode;
                if ( defined $offsets->{country_code}->{$sheet_name} && $line->[ $offsets->{country_code}->{$sheet_name} ] ne "" ) {
                    $countryCode = $line->[ $offsets->{country_code}->{$sheet_name} ];
                } else {
                    $countryCode = 'US';
                }
                $sale->countryCode($countryCode);

                $sale->mediaType($mediaType);
                $sale->lineNum($linenum);

                $self->_insertSale( sale => $sale );
            }

     #else { print STDERR "skip s:".$sheet_names->[$sheet_count]." l:".$linenum." a:".$artist." t:".$track." u:".$units." p:".$price."\n"; }
            $linenum++;
        }
        $sheet_count++;
    }

    return $linenum;
}

sub _getDates {
    my $self = shift;
    my $date = shift;
    my ( $month, $year, $dateBegin, $dateEnd );
    if ( $date =~ /through (\w*) (\d{4})/ ) {
        $year = $2;
    } elsif ( $date =~ /(\w*) (\d{4})$/ ) {
        $year = $2;
    } elsif ( $date =~ /^(\w*) (\d{4})/ ) {
        $year = $2;
    }
    $month = "01" if ( $date =~ /jan/i );
    $month = "02" if ( $date =~ /feb/i );
    $month = "03" if ( $date =~ /mar/i );
    $month = "04" if ( $date =~ /apr/i );
    $month = "05" if ( $date =~ /may/i );
    $month = "06" if ( $date =~ /jun/i );
    $month = "07" if ( $date =~ /jul/i );
    $month = "08" if ( $date =~ /aug/i );
    $month = "09" if ( $date =~ /sep/i );
    $month = "10" if ( $date =~ /oct/i );
    $month = "11" if ( $date =~ /nov/i );
    $month = "12" if ( $date =~ /dec/i );

    if ( $month ne "" && $year ne "" ) {
        $dateBegin = $year . "-" . $month . "-01";
        $dateEnd = $year . "-" . $month . "-" . Days_in_Month( $year, $month );
        return ( $dateBegin, $dateEnd );
    }
    return undef;
}

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