package RPS::Import::Thumbplay::v1;

use strict;

use lib '/app/tools/rps/lib';
use RPS::DB::Item::Client;

use lib '/app/tools/common/lib';
use Common::Country;
use Common::Consts;
use Common::Assert;
use Common::Log;
use Data::Dumper;

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

use lib '/app/tools/rps/lib';
use RPS::Import::SaleRec;
use RPS::DB::Item::MediaType;
use RPS::File::Sale;

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

sub _fieldMap {
    {

        #-----------------------------------------------------------------
        # Note: the sales file has a blank first column, so in terms of
        # setting up the _fieldMap, we list the column numbers minus one
        # (e.g., the column numbers are zeroed at column B).
        #
        # The actual column information is added as a comment to make
        # it easier to identify the source columns. -ES
        #-----------------------------------------------------------------
        # Summary-related columns
        salesType             => 0,    # B - Sales Type
        salesProduct          => 1,    # C - Product
        salesUnits            => 2,    # D - Units
        salesRevenue          => 9,    # K - Sales Revenue
        salesStreamingRevenue => 8,    # J (Merged column)

        # Detail-related columns
        dateBegin   => 8,              # J - Period Start Date
        dateEnd     => 9,              # K - Period End Date
        productType => 5,              # G - Product
        formatType  => 1,              # C - Sales Channel
        artistName  => 6,              # H - Artist
        isrc        => 2,              # D - External Meta Data
        upc         => 4,              # E - UPC
        trackName   => 7,              # I - Title
        units       => 10,             # K - Units
    };
}

#--------------------------------------------------------------------
# productSummaryMap - maps product types found in the summary section
# to the product type in the detail section.
# Note: the following products are assumed to be tracks.
#--------------------------------------------------------------------
my %productSummaryMap = (
    'full track (tier ii)' => 'ms2 download',
    'streaming'            => 'ms2 stream',
);

#---------------------------------------------------------------
# salesChannelMap - Maps the sales channel to an RPS format type
#---------------------------------------------------------------
my %salesChannelMap = (
    'ms2 download' => RPS::File::Sale::FORMAT_DOWNLOAD,
    'ms2 stream'   => RPS::File::Sale::FORMAT_STREAM,
);

#------------------------------------------------------------------------
# revenueMap - Maps the product type in the summary section to a sales
# channel in the detail section.
#
# For example for the product 'full track (tier ii)' in the summary
# section, we'd map the product type to 'ms2 download' (via the
# productSummaryMap, above), and store the associated revenue as:
#
# revenueMap{ 'ms2 download' }{ 'track' } => {
#    revenue => $revenue,
#    units => $units,
#    unit_price => $revenue/$units
# }
#------------------------------------------------------------------------
my %revenueMap;

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

    assert( defined $args{sheets} );
    assert( defined $version );

    my $offsets     = $self->_fieldMap;
    my $sheet_names = $args{sheet_names};
    my $sheets      = $args{sheets};
    my $linenum     = 1;

    for ( my $sheetIndex = 0 ; $sheetIndex < scalar @{ $args{sheets} } ; $sheetIndex++ ) {
        my $sheet = $sheets->[$sheetIndex];

        #--------------------------------------------------------------------
        # All data is assumed to be on the first sheet.
        #
        # We'll look for the summary section first.  Once it is found, we'll
        # set 'foundSummaryHeader' and process the summary data until we
        # encounter the detail section.  At that point, we'll set the
        # 'foundDetailHeader' flag and the subsequent sales data will be read
        # in.  We'll set the price information for each sale based on the
        # unit price information derived from the summary section.
        #--------------------------------------------------------------------
        next if ( $sheetIndex > 0 );

        my $foundSummaryHeader = 0;
        my $foundDetailHeader  = 0;

        for ( my $lineIndex = 0 ; $lineIndex < scalar @$sheet ; $lineIndex++ ) {
            $linenum = $lineIndex + 1;
            my $line = $sheet->[$lineIndex];

            if ( !$foundSummaryHeader ) {
                if ( 'Sales Type' eq $line->[ $offsets->{format_type} ] ) {
                    $foundSummaryHeader = 1;
                }
                next;
            }

            if ($foundSummaryHeader) {

                if ( !$foundDetailHeader ) {

                    #-------------------------
                    # Process the summary data
                    #-------------------------

                    #==================================================================
                    # NOTE: The revenue column for Subscription/(Streaming) is slightly
                    # different than for Subscription/(anything_but_streaming) or
                    # A La Carte/(anything).  This is due to the merged cell for the
                    # 'Proportionate Share' data with Subscription/Streaming.
                    #==================================================================
                    my $salesType    = $line->[ $offsets->{salesType} ];
                    my $salesProduct = $line->[ $offsets->{salesProduct} ];
                    my $salesUnits   = $line->[ $offsets->{salesUnits} ];

                    my $salesRevenue          = $line->[ $offsets->{salesRevenue} ];
                    my $salesStreamingRevenue = $line->[ $offsets->{salesStreamingRevenue} ];

                    if ( 'Row number' eq $line->[ $offsets->{format_type} ] ) {
                        $foundDetailHeader = 1;
                        next;    # keep looking for detail section...
                    } elsif ( $salesType && ( $salesType ne 'Sales Type' ) && $salesProduct && $salesUnits ) {

                        #---------------------------------------------------------
                        # Store the units/revenue data for the given sales_type &
                        # product combination.
                        #
                        # Per the template, the initial version of the importer
                        # will only accept 'Full Track (Tier II)' and 'Streaming'
                        # as valid sales types, and those are only valid for track
                        # sales.
                        #---------------------------------------------------------
                        my $mappedProduct = $productSummaryMap{ lc $salesProduct };

                        if ($mappedProduct) {
                            my $_revenue = $salesRevenue;
                            $_revenue = $salesStreamingRevenue if ( $salesProduct =~ m/^streaming$/i );
                            my $_unitPrice = $_revenue / $salesUnits;

                            $revenueMap{$mappedProduct}{track} = {
                                units      => $salesUnits,
                                revenue    => $_revenue,
                                unit_price => $_unitPrice
                            };
                        } else {
                            print STDERR "Unknown sales product '$salesProduct' detected\n";    # XXX
                            $self->errstr("Line $linenum: unknown sales product");
                            return undef;
                        }
                    }

                } else {

                    #------------------------
                    # Process the detail data
                    #------------------------

                    my ( $dateBegin, $dateEnd ) = $self->_getDates(
                        date_begin => $line->[ $offsets->{dateBegin} ],
                        date_end   => $line->[ $offsets->{dateEnd} ]
                    );

                    my $artist       = $line->[ $offsets->{artistName} ];
                    my $units        = $line->[ $offsets->{units} ];
                    my $formatType   = $line->[ $offsets->{formatType} ];
                    my $_productType = $line->[ $offsets->{productType} ];

                    my $productFormat = $salesChannelMap{ lc $formatType };
                    if ( !$productFormat ) {
                        print STDERR "ERROR: line $linenum: Unable to map sales channel '$formatType'\n";
                        $self->errstr("Line $linenum: unknown sales channel");
                        return undef;
                    }

                    my $unitPrice;
                    my $upc;
                    my $isrc;
                    my $albumTitle;
                    my $trackTitle;
                    my $productType;
                    my $_title = $line->[ $offsets->{trackName} ];

                    if ( lc $_productType eq 'track' ) {
                        $trackTitle  = $_title;
                        $isrc        = $line->[ $offsets->{isrc} ];
                        $productType = RPS::File::Sale::TYPE_TRACK;

                        if ( exists $revenueMap{$formatType}{track} ) {
                            $unitPrice = $revenueMap{$formatType}{track}->{unit_price};
                        } else {
                            print STDERR "ERROR: line $linenum: Unable to determine unit price for track format($formatType)\n";
                            $self->errstr("Line $linenum: unable to determine unit price");
                            return undef;
                        }
                    } elsif ( lc $_productType eq 'album' ) {
                        $albumTitle  = $_title;
                        $upc         = $line->[ $offsets->{upc} ];
                        $productType = RPS::File::Sale::TYPE_ALBUM;
                        if ( exists $revenueMap{$formatType}{album} ) {
                            $unitPrice = $revenueMap{$formatType}{album}->{unit_price};
                        } else {
                            print STDERR "ERROR: line $linenum: Unable to determine net price for album format($formatType)\n";
                            $self->errstr("Line $linenum: unable to determine unit price");
                            return undef;
                        }
                    } else {
                        print STDERR "ERROR: line $linenum: Unknown product type '$_productType'\n";
                        $self->errstr("Line $linenum: unknown product type");
                        return undef;
                    }

                    my $mediaType = RPS::DB::Item::MediaType::kMediaTypeAudio;

                    if ( ( $units || $artist ) && $unitPrice && ( '' ne $albumTitle || '' ne $trackTitle ) ) {

                        my $sale = RPS::Import::SaleRec->new();
                        $sale->mediaType($mediaType);
                        $sale->productType($productType);
                        $sale->formatType($productFormat);
                        $sale->dateBegin($dateBegin);
                        $sale->dateEnd($dateEnd);
                        $sale->trackName($trackTitle) if ($trackTitle);
                        $sale->albumName($albumTitle) if ($albumTitle);
                        $sale->artistName($artist);
                        $sale->upc($upc)   if ($upc);
                        $sale->isrc($isrc) if ($isrc);
                        $sale->units($units);
                        $sale->price($unitPrice);
                        $sale->countryCode('US');
                        $sale->currencyCode('USD');
                        $sale->lineNum($linenum);

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

        }
    }

    return $linenum;
}

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