#---------------------------------------------------------------
# ____                   _ _         ____  _
#|  _ \ ___  _   _  __ _| | |_ _   _/ ___|| |__   __ _ _ __ ___
#| |_) / _ \| | | |/ _` | | __| | | \___ \| '_ \ / _` | '__/ _ \
#|  _ < (_) | |_| | (_| | | |_| |_| |___) | | | | (_| | | |  __/
#|_| \_\___/ \__, |\__,_|_|\__|\__, |____/|_| |_|\__,_|_|  \___|
#            |___/             |___/
#
# Copyright (C) 2009 RoyaltyShare, Inc.      All Rights Reserved
#---------------------------------------------------------------
package Support::GenreMap::Importer;

use strict;
use Data::Dumper;

use lib '/app/tools/common/lib';
use Common::XMLObject;
use Common::Assert;
use Common::Log;

use lib '/app/tools/distribution/lib';
use Distribution::DB::Item::GenreServiceMap;

use lib '/app/tools/support/lib';
use Support::GenreMap::Translator;

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

use base 'Common::XMLObject';

sub Import {
    my ( $class, %args ) = @_;

    my $filename = $args{filename};
    assert($filename);

    # Instantiate a translator object.
    #
    my $translator = Support::GenreMap::Translator->new( filename => $filename );

    # Did something go wrong parsing the header?
    #
    if ( $translator->error() ) {
        my %errorHash;
        $errorHash{ErrorMessage} = $translator->error();

        # !!! These might be better served with an accessor method.
        #
        $errorHash{MissingHeader} = $translator->{_version}{_missingHeaders} if $translator->{_version}{_missingHeaders};
        $errorHash{UnknownHeader} = $translator->{_version}{_unknownHeaders} if $translator->{_version}{_unknownHeaders};
        return \%errorHash;
    }

    # Now we parse the rest of the file.
    # For now, we will require that the RS_GENRE_IDs we read already
    # exist, and that their RS GENRE NAME matches what we already have.
    # This is the only real sanity check we can do.
    #
    my @errors;
    my @lines = $translator->getAll();
    my %newMap;
    foreach my $line (@lines) {
        my $rsGenreID   = $line->genre_id;
        my $rsGenreName = $line->rs_genre_name;

        # Trim spaces from the ends of the name
        #
        $rsGenreName =~ s/^\s+//;
        $rsGenreName =~ s/\s+$//;
        Common::Log::Debug("genre id: $rsGenreID   genre name: $rsGenreName");

        if ( !$rsGenreID ) {
            push @errors,
              {
                Message => "Missing Genre ID",
                Line    => $line->line(),
              };

            next;
        }

        # This _is_ a valid genre, right?
        #
        my $genreItem = RPS::DB::Item::Genre->Lookup( genre_id => $rsGenreID );
        if ( !$genreItem ) {
            push @errors,
              {
                Message => "Unknown Genre ID",
                Line    => $line->line(),
              };
        } elsif ( $genreItem->genre_name() ne $rsGenreName ) {
            push @errors,
              {
                Message => "Genre Name \"$rsGenreName\" does not match expected name: \"" . $genreItem->genre_name . "\"",
                Line    => $line->line(),
              };
        } else {

            # Looks valid. Save the mappings in our temp hash.
            #
            foreach my $serviceID ( $line->getColumnNames() ) {
                next if $serviceID eq 'genre_id';
                next if $serviceID eq 'rs_genre_name';

                my $value = $line->$serviceID;
                if ( defined $value ) {
                    $newMap{$serviceID}{$rsGenreID} = $value;
                }
            }
        }
    }

    if ( scalar @errors ) {
        my %errorHash;
        $errorHash{ErrorMessage} = 'Invalid Data';
        $errorHash{DataError}    = \@errors;

        return \%errorHash;
    }

    # If we've gotten this far, we win!
    # Write out the table.
    # !!! So, we need to _replace_ data, but I don't want to just truncate the
    # whole table.  We might not have specified all services.
    # I believe I will drop entries for each _service_ that we see.
    #
    Common::Log::Debug( "NEWMAP: " . Dumper( \%newMap ) );
    foreach my $serviceID ( keys %newMap ) {

        # Drop their entries.
        #
        Distribution::DB::Item::GenreServiceMap->DeleteByServiceID($serviceID);

        # Enter in the new values.
        #
        my $serviceMap = $newMap{$serviceID};
        foreach my $genreID ( keys %$serviceMap ) {
            my $genreName   = $serviceMap->{$genreID};
            my $newMapEntry = Distribution::DB::Item::GenreServiceMap->Create(
                genre_id   => $genreID,
                service_id => $serviceID,
                genre_name => $genreName,
            );
            $newMapEntry->save();
        }
    }

    return;
}

1;
