package PS::MOPS::DC::Test::Instance;

## @class PS::MOPS::DC::Test::Instance
#
# @par DESCRIPTION
# A Test Instance contains a PS-MOPS Instance (see PS::MOPS::DC::Instance).
#
# @par ATTRIBUTES
# _NAME - String corresponding to the name of the PS-MOPS Instance.
# _PSMOPS_INSTANCE - Scalar reference to PS-MOPS Instance.
# _FIELD_NAMES_TYPES
# _DB - Database object linked to the Test Instance.
# _DELETE_ON_FINISH - Remove the PS-MOPS Instance at exit.

use strict;
use warnings;
our $VERSION = sprintf "%d", q$Revision: $ =~ /(\d+)/g;

use Env;
use PS::MOPS::DC::Build;
use PS::MOPS::DC::Instance;
use PS::MOPS::Test::Utility qw(getFormattedTime);
use PS::MOPS::DC::Test::Instance::Database;
use Params::Validate;

my $_init=sub{};
my $_buildInstance=sub{};
my $_removeInstance=sub{};

# Constructor.
# No arguments.
sub new {
    my ($class,%arg)=@_;
    my $self={};

    $self->{_NAME}=undef;
    $self->{_PSMOPS_INSTANCE}=undef;
    $self->{_FIELD_NAMES_TYPES}=undef; # Array of hashes containing field names and types from database.
    $self->{_DB}=undef;
    $self->{_DELETE_ON_FINISH}=undef;

    if(defined($arg{test_instance_name})){
        $self->{TEST_INSTANCE_NAME}=$arg{test_instance_name}; # Set the name of the test instance.
    }
    else {
        $self->{TEST_INSTANCE_NAME}=undef;
    }
    print "delete on finish = $arg{delete_on_finish}\n";
    if(defined($arg{delete_on_finish})){
        $self->{_DELETE_ON_FINISH}=$arg{delete_on_finish};
    }
    else {
        $self->{_DELETE_ON_FINISH}=0;
    }
    bless($self,$class);
    $self->$_init();
    return $self;
}

# Intialize member variables.
# Create PSMOPS Test instance.
$_init=sub
{
    my($self)=shift;

    # Generate unique name for test instance.
    my $test_db_name;
    if(defined($self->{TEST_INSTANCE_NAME})){
        $test_db_name=$self->{TEST_INSTANCE_NAME};
    }
    else {
        $test_db_name="psmops_test_";
        $test_db_name.=$ENV{USER} . "_";
        $test_db_name.=getFormattedTime();
    }
    # @todo Validate Test Instance name.

    my $inst=PS::MOPS::DC::Instance->new(DBNAME=>$test_db_name);
    $self->{_PSMOPS_INSTANCE}=$inst;

    $self->{_NAME}=$test_db_name;
    $self->$_buildInstance();

    # Make a new database object
    $self->{_DB}=PS::MOPS::DC::Test::Instance::Database->new(psmops_instance=>$self->{_PSMOPS_INSTANCE},
                                                             name=>$test_db_name );

};

# Destructor.
#
# Remove PSMOPS Test instance.
sub DESTROY {
    my ($self) = shift;
    $self->$_removeInstance();
}

# TO DO:
# Check for existence of database prior to calling modcb_build(). We want
# to fail if the MOPS DB instance already exists.
#
# Setting the name in build indicates which directory under MOPS_HOME/var
# to use. We build an empty instance for now.
$_buildInstance = sub {
    my ($self) = shift;
    my $res = modcb_build(name=>$self->{_NAME},
                          model=>'',
                          noprompt=>1 # Don't prompt to drop database.
                          );
};

# Return current PSMOPS instance.
sub getPSMOPSInstance {
    my($self)=shift;
    return $self->{_PSMOPS_INSTANCE};
}

# Return database name in PSMOPS instance.
sub getName {
    my($self)=shift;
    return $self->{_NAME};
}

# Return reference to the database associated with the Test Instance.
sub getDB {
    my($self)=shift;
    return $self->{_DB};
}

# For compatibility with PS::MOPS::DC::Instance.
sub dbh {
    my ($self)=shift;
    return $self->{_DB}->{_PSMOPS_INSTANCE}->dbh();
}

# For compatibility with PS::MOPS::DC::Instance.
sub pushAutocommit {
    # set AutoCommit flag as specified; preserving current setting so we
    # can restore to previous.
    my $self = shift;
    my ($new_ac) = validate_pos(@_, 1);
    my $dbh = $self->dbh;
    push @{$self->{_AC_STACK}}, $dbh->{AutoCommit};
    $dbh->{AutoCommit} = $new_ac;
}

# Remove an instance.
$_removeInstance=sub
{
    print "[_removeInstance()]\n";
    my ($self)=shift;
    if($self->{_DELETE_ON_FINISH}==1){
        my $res=modcb_remove(name=>$self->{_NAME});
        if(!$res){ print STDERR "\nRemove failed: " . Dumper($res); }
        else { print STDERR "\nPSMOPS instance $self->{_NAME} removed.\n"; }
    }
};

1;
