package APE::FlushControllerFactory::ConcreteFlushController::DefaultExoApeFlushController;

use base 'APE::FlushControllerFactory::ConcreteFlushController::DefaultFlushController';

$APE::FlushControllerFactory::ConcreteFlushController::DefaultExoApeFlushController::VERSION = '0.1';

use strict;
use warnings;
use SqlEngine2;
use Class::Throwable;
use Carp;

use constant TRUE  => 1;
use constant FALSE => 0;

{
    my %_attributes = (userObj     => undef,
		       programName => undef);

    my %object;

    ## Autoloader wannabe. Inserts the sub calls that I want to be
    ## accessible into the symbol table.
    foreach my $attName (keys(%_attributes)) {
	no strict 'refs';
	*{__PACKAGE__ . "::get\u$attName"} = sub { $object{ $_[0] }->{$attName} }
    }


    #################################################################
    ## Initialise the objects private attributes. The argument is
    ## deleted as it is found, initialised and set.
    #################################################################
    sub _init {
	my ($self,%args) = @_;
	foreach my $attName (keys(%args)) {
	    if(exists($_attributes{$attName})) {
		$object{ $self }->{$attName} = delete $args{$attName};
	    }
	}


	## ExoApe concrete flush controllers require the calling
	## program name.
	croak "Error: attribute 'programName' is required"
	    unless $object{ $self }->{programName};

	## Strip the program name down to just the name.
	$object{ $self }->{programName} =~ s!.*/([^/]+)$!$1!;

	## ExoApe concrete flush controllers require a User object
	## containing the details of the user (login, team, role id,
	## barcode and line printer etc).
	croak "Error: attribute 'userObj' is required"
	    unless $object{ $self }->{userObj};


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


    #################################################################
    ## Method to populate the snp.exo_process table. This table holds
    ## data corresponding to an APE flush so that the parentage of a
    ## created entity can be traced, including the tract that it was
    ## created in.
    #################################################################
    sub populateExoProcess {
	my ($self,%arguments) = @_;
	warn "*** MAKING NEW ENTRY TO EXO_PROCESS ***\n";
	my %args = ();

	## Supplying an input or output entity overrides the id and prefix
	## arguments if the argument is a proper entity - otherwise the prefix
	## and id are left to fend for themselves in the next block.
	foreach(qw/input output/) {
	    my $key = "-".$_."Entity";
	    warn "*** Checking inputEntity and outputEntity arguments using key: $key ***\n";
	    if(exists($arguments{$key}) && $arguments{$key} =~ /^(\w\w)(\d+)/) {
		throw Class::Throwable::Simple("ERROR: pattern match failed on $key: $arguments{$key} -> '$1' '$2'")
		    unless $1 && $2;
		$arguments{"-".$_."Prefix"} = $1;
		$arguments{"-".$_."Id"}     = $2;
		delete $arguments{$key};
		warn "*** Split '$key' to '".$arguments{"-".$_."Id"}."' -> '".
		    $arguments{"-".$_."Prefix"}."' ***\n";
	    }
	}

	## Verify the passed arguments.
	foreach(qw/-sqlEngine -dbh -processId -inputId -inputPrefix -outputId -outputPrefix/) {
	    throw Class::Throwable::Simple("ERROR: argument '$_' is missing")
		unless $arguments{$_};
	    $args{$_} = delete $arguments{$_};
	    warn "$_ = $args{$_}\n";
	}

	## An unknown option has been passed - oops!
	croak "ERROR: unknown option '",join(",",keys %arguments),"'\n"
	    if keys %arguments;

	## Get the next id and make the insert into the exo_process table.
	my $nextExoProcessId = $self->_getNextExoProcessId($args{-sqlEngine},$args{-dbh});
	warn "Using id_exo_process: $nextExoProcessId\n";
	$args{-sqlEngine}->do
	  ('ExoSeq::insert_exo_process',
	   [$nextExoProcessId,$args{-processId},$args{-inputId},
	    $args{-inputPrefix},$args{-outputId},$args{-outputPrefix}],
	   $args{-dbh});
    }


    #################################################################
    ## Method to get the next primary key id from the sequence used
    ## on the exo_process table.
    #################################################################
    sub _getNextExoProcessId {
	my ($self,$sqlEngine,$dbh) = @_;
	my $nextExoProcessId = 
	    eval { $sqlEngine->getRow('ExoSeq::next_exo_process',
				      [],$dbh); };
	croak $@ if $@;
	return $nextExoProcessId;
    }

       
    #################################################################
    ## Method to destory this object.
    #################################################################
    sub DESTROY { 
	my $self = shift;
	delete $object{ $self };
    }
}

1;
