#---------------------------------------------------------------
# ____                   _ _         ____  _
#|  _ \ ___  _   _  __ _| | |_ _   _/ ___|| |__   __ _ _ __ ___
#| |_) / _ \| | | |/ _` | | __| | | \___ \| '_ \ / _` | '__/ _ \
#|  _ < (_) | |_| | (_| | | |_| |_| |___) | | | | (_| | | |  __/
#|_| \_\___/ \__, |\__,_|_|\__|\__, |____/|_| |_|\__,_|_|  \___|
#            |___/             |___/
#
# Copyright (C) 2012 RoyaltyShare, Inc.   All Rights Reserved
#---------------------------------------------------------------

package RPS::ArtistRoyalty::Fast::Final;

use strict;
use Data::Dumper;
use File::Path;

use lib '/app/tools/common/lib';
use lib '/app/tools/rps/lib';
use lib '/app/tools/raptor/lib';
use Common::RSApp;
use Common::RSDB;
use Common::Assert;
use Common::Log;

use IO::File;

use Common::Log;

# We'll maintain some hashes to store derived class global data.
# The class package will be the hash key.
#
my %gFD;
my %gCurrentID;

sub Init {
    my ( $class, $outputDirectory ) = @_;
    assert( $outputDirectory, "ERROR - missing outputDirectory" );

    assert( !$gFD{$class}, "ERROR - Class is already initialized" );

    $gFD{$class} = $class->WriteFD($outputDirectory);

    # Figure out the current max statement id, and store
    # that as our current id. We'll increment this every time we
    # instiate a new line object.
    #
    $gCurrentID{$class} = $class->GetCurrentMaxID();
}

# !!! I have to re-write this.
# !!! using MAX() will not work if the rows at the 'end' of the table have been deleted.

sub GetCurrentMaxID {
    my ($class) = @_;

    my $dbo       = Common::RSApp::GetClientDB();
    my $tableName = $class->FileName();

    # First refresh the table metadata
    my $sql       = "ANALYZE NO_WRITE_TO_BINLOG TABLE " . $tableName;
    my $sth       = $dbo->DoCmd($sql);

    # Now try to retrieve the auto-increment value
    $sql          = "SHOW TABLE STATUS LIKE '" . $tableName . "'";
    $sth          = $dbo->DoCmd($sql);
    my $hr        = $sth->fetchrow_hashref();
    my $id        = $hr->{'Auto_increment'};
    assert($id);
    return ( $id - 1 );
}

sub id {
    my ($self) = @_;

    my $class = ref($self);
    return $class->_CurrentID();
}

sub _CurrentID {
    my ($class) = @_;
    return $gCurrentID{$class};
}

sub _IncrementID {
    my ($class) = @_;
    $gCurrentID{$class}++;
}

sub WriteFD {
    my ( $class, $dataPath ) = @_;

    my $filename = "$dataPath/" . $class->FileName();
    my $fd       = IO::File->new("> $filename")
      || die "ERROR: Unable to open $filename: $!";

    binmode( $fd, ':utf8' );
    return $fd;
}

sub BlankItem {
    my ($class) = @_;

    my $f = $class->Fields();

    my @array;
    foreach (@$f) {
        push @array, 0;
    }
    return \@array;
}

# !!! Need to pass the client_id as a parameter, so we can get the correct database name.
sub Commit {
    my ( $class, $dataPath ) = @_;

    # !!! I'm getting a "can't stat ..." error from mysqlimport.
    # !!! I am going with the theory that the file needs to be closed before we can do this.
    #
    # !!! Well, closing the file is a good idea.  But I think the actual issue is that I need to still use
    # !!! the --local flag, otherwise it tries to find the file on the database server's filesystem...
    if ( $gFD{$class} ) {
        my $fd = $gFD{$class};
        close($fd);
        delete $gFD{$class};
    }

    my $filename = "$dataPath/" . $class->FileName();

    my $clientID = Common::RSApp::GetClientID();

    my $f       = $class->Fields();
    my $fields  = join( ',', @$f );
    my @command = (
        'mysqlimport',                                               '--local',
        '--fields-optionally-enclosed-by=\"',                        "--columns=$fields",
        "--user=" . $Common::RSDB::CLIENT_DB{$clientID}->{username}, "--password=" . $Common::RSDB::CLIENT_DB{$clientID}->{password},
        "--host=" . $Common::RSDB::CLIENT_DB{$clientID}->{server},   $Common::RSDB::CLIENT_DB{$clientID}->{db_name},
        $filename,
    );
    Log->warn( "COMMAND: " . join( ' ', @command ) );

    # Catch the bloody error code!
    #
    my $status = system(@command);
    die "ERROR EXECUTING " . join( ' ', @command ) . " : ($?) $!" unless 0 == $status;
}

# Here's the one remotely clever bit:  We'll write out our state when the line object goes out of scope.
#
sub DESTROY {
    my ($self) = @_;
    my $class  = ref($self);
    my $fd     = $gFD{$class};
    $self->_output($fd) if $fd;
}

sub _output {
    my ( $self, $fd ) = @_;
    print $fd join( "\t", @$self ) . "\n";
}

1;

