#---------------------------------------------------------------
# Copyright (C) 2009 RoyaltyShare, Inc.      All Rights Reserved
#---------------------------------------------------------------
package Support::DataImport::ImportTemplate;

use strict;
use warnings;
use Carp;

use Data::Dumper;
use File::Path qw[make_path];
use File::Copy;
use File::Basename;

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

use base 'Common::XMLObject';

use constant kImportDir => '/app/shared/imports';

use lib '/app/tools/support/lib';
use Support::DB::Item::DataImport;
use Support::DataImport::RPSDataImport;
use Support::DataImport::DataImport;
use Support::DataImport::Job::RunImport;

Log->init();
#Log->setLogLevel('info');

sub _init {
    my ( $self, %args ) = @_;

    my $userID        = $args{userID};
    my $supportRoleID = $args{supportRoleID};

    my $filePath      = $args{filePath};

    my $clientID      = $args{clientID};
    my $caseno        = $args{caseno};
    my $action        = $args{action};
    my $importID      = $args{importID};  # used if action = 'add_new'

    my $serviceID     = $args{serviceID};
    my $versionNum    = $args{versionNum};

    $self->SUPER::_init(%args);

    my $files;

    $self->{Items} = [];

    my $basedir = kImportDir;

    my $importType    = $serviceID;
    my $importVersion = $versionNum;

    # The 'action' parameter controls what happens here:
    #
    #   'upload_new' - We're uploading a file for a new case, so we must create the
    #     case import home directory, then create the timestamped staging directory
    #     from which to run the import.
    #
    #   'add_new' - Upload a file to an existing case.  The import home directory
    #     is already exists, so we're just adding the timestamped staging directory.
    #

    my $client = Common::DB::Item::Client->Lookup( client_id => $clientID );
    my $cname  = $client->client_name_clean;

    my $typeString = Support::DataImport::RPSDataImport->GetTypeString( $importType );
    $typeString    = Common::Util::clean_name($typeString);

    my $homedir    = Common::Util::clean_name( $caseno ) . '_' . $cname . '_' . $typeString;

    my $timestamp  = POSIX::strftime( "%Y%m%d_%H%M", localtime time);
    my $stageDir   = join('/', $basedir, $homedir, $timestamp );


    #------------------------------------------------------------------------
    # If this is a new case, create the import home directory
    #------------------------------------------------------------------------
    my $parentID;
    if ( $action eq 'upload_new' ) {

        my $homepath = join( '/', $basedir, $homedir );
        if ( ! -e $homepath ) {
            make_path($homepath) or die("Unable to create home dir '$homepath'" . $! );

            my %dargs = (
                client_id   => $clientID,
                path        => $homepath,
                case_id     => $caseno,
                service_id  => $importType,
                version_num => $importVersion,
            );

            my $file = Support::DB::Item::DataImport->Create( %dargs );
            $file->save;
            $parentID = $file->import_id;
            Log->debug("  Created new DataImport import_id $parentID : ". Dumper(\%dargs) );

        } else {
            # Shouldn't happen (if you get here then validate case isn't working...)
            Log->warn("ImportTemplate: home directory '$homepath' exists");
            $self->{errstr} = "ImportTemplate: home directory '$homepath' exists\n";
            return $self;
        }
    } elsif( $action eq 'add_new' ) {
        $parentID = $importID; # use the importID passed in

        # Make sure we're adding the same type of file
        #
        my $parent = Support::DB::Item::DataImport->Lookup( import_id => $parentID );
        if ( $parent->service_id != $serviceID ) {
            Log->warn("ImportTemplate: serviceID $serviceID != parent serviceID ". $parent->service_id);
            $self->{errstr} = "Template type mismatch\n";
            return $self;
        }

        # Check for an import in progress
        #
        my $coll = Support::DB::Item::DataImport->GetChildren( $importID );
        my $inprogress;
        while( $coll->hasNext() ) {
            my $di = $coll->next();
            my $fcoll = Support::DB::Item::DataImportFile->GetByImportID( import_id => $di->import_id );
            while( $fcoll->hasNext() ) {
                my $df = $fcoll->next();
                if ( $df->file_type == Support::DB::Item::DataImportFile::kFileTypeTemplate &&
                     $df->status == Support::DB::Item::DataImportFile::kFileStatusUnprocessed ) {
                    $inprogress = 1;
                }
            }
        }

        if ( $inprogress ) {
            Log->warn("ImportTemplate: import in progress");
            $self->{errstr} = "Import already in progress\n";
            return $self;
        }
    }

    Log->info("DataImport/ImportTemplate: ### action($action): Processing import staging directory: $stageDir");

    #------------------------------------------------------------------------
    # Create a new datafile node for the staging directory containing the 
    # template being uploaded
    #------------------------------------------------------------------------
    my $importObj;
    my $newImportID;
    if ( ! -e $stageDir ) {
        make_path($stageDir) or die("Unable to create staging dir '$stageDir'" . $! );

        my %dargs = (
            client_id   => $clientID,
            parent_id   => $parentID,
            path        => $stageDir,
            case_id     => $caseno,
            service_id  => $importType,
            version_num => $importVersion,
        );

        $importObj = Support::DB::Item::DataImport->Create( %dargs );
        $importObj->save;
        $newImportID = $importObj->import_id;
        Log->debug("DataImport/ImportTemplate: Created new child DataImport import_id $newImportID : ". Dumper(\%dargs) );

    } else {
        # If the staging directory exists, then an attempt was made to import a file
        # within 60 seconds (the directory names are timestamped to the nearest minute).
        $self->{errstr} = "Import directory '$stageDir' exists\n";
        return $self;
    }

    #------------------------------------------------------------------------
    # Now that the staging directory is setup, copy the template file into it
    # and setup the import-related files.
    #------------------------------------------------------------------------

    my $fileName = basename $filePath;

    # Copy the temp uploaded file to the staging directory
    my $srcFile    = '/app/shared/data_import/' . $clientID . '/' . $filePath;
    my $targetFile = $stageDir . '/' . $fileName;

    copy( $filePath, $targetFile ) or die "Copy failed: $!";

    # Setup DataImportFile object
    my %dargs = (
        file_name   => "$fileName",
        import_id   => $newImportID,
        file_type   => Support::DB::Item::DataImportFile::kFileTypeTemplate,
        status      => Support::DB::Item::DataImportFile::kFileStatusUnprocessed,
        service_id  => $importType,
        version_num => $importVersion,
    );

    my $file = Support::DB::Item::DataImportFile->Create( %dargs );
    $file->save;
    my $fileID = $file->file_id;
    Log->debug("DataImport/ImportTemplate: Created new DataImportFile $fileID : ". Dumper(\%dargs) );

    # At this point, we have a staging directory (DataImport) containing the
    # template (DataImportFile).  Let's copy the import-related support files
    # into the same directory.  We'll use rps_dataimport.pl to copy the files
    # for us.
    #
    #   rps_dataimport.pl -c clientID -i importID
    #
    # By specifying the importID, we don't need to specify the template name or
    # importer type since that information can be looked up via the importID.
    #
    # The generated 'makefile' will pass the importID to the wrapper script that
    # gets called during 'make test' or 'make import'.
    # E.g., "run_import.pl -c clientID -f filename -i importID"
    # The template will be imported using the wrapper, and once complete, the
    # results will be recorded in the database using the post_import.pl script.
    #

    if ($fileName) {

        my $_fileName = $fileName;
        $_fileName =~ s/ /\\ /g;
        $_fileName =~ s/-/\\-/g;
        $_fileName =~ s/\(/\\(/g;
        $_fileName =~ s/\)/\\)/g;
        my $cmd = "/app/tools/rps/bin/misc/rps_dataimport.pl -c $clientID -f $_fileName -i $newImportID";

        Log->debug("ImportTemplate: stageDir($stageDir) calling rps_dataimport.pl cmd = $cmd");

        chdir($stageDir);

        my $report = `$cmd`; # generate import files

        $self->{_importDir} = $stageDir;

        # create a job to run the import
        Log->info("DataImport/ImportTemplate: Starting import job");
        my $job = $self->_createImportJob();
    }
    return $self;

} # _init

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

    # Create a job for the import
    #    
    my $clientID  = Common::RSApp::GetClientID();
    my $importDir = $self->{_importDir};

    my $jobArgs = Support::DataImport::Job::RunImport->new(
        importDir => $self->{_importDir},
        clientID  => $clientID,
    );   
    my $job = $jobArgs->enqueue();
    return $job;
}

1;
