package GTx::APE::FlushController;

use strict;
use warnings;
use Carp;

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

{
    my %_attributes = (
		       arrayingEntity => undef,
		       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} }
    }

    
    #################################################################
    ## Constructor method for this object. Returns a new
    ## FlushController object.
    #################################################################
    sub new {
	my ($proto,%args) = @_;
	
	my $class = ref($proto) || $proto;
	my $self  = bless {}, $class;
	
	%args = $self->_init(%args);
	
	my @leftover = keys %args;
	
	confess "Error: the following arguments are unknown - @leftover\n" if @leftover;
	
	return $self;
    }


    #################################################################
    ## 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};
	    }
	}

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

	return %args;
    }

    
    #################################################################
    ## Method to flush the arrayed data to STDOUT. 
    #################################################################
    sub flush {
	my $self = shift;
	eval { 
	    my $entity    = ${$object{ $self }->{arrayingEntity}};
	    my $user      = ${$object{ $self }->{userObj}};
	    my $sessionId = $entity->getSessionId();
	    my $atomicProcessCount = 0;
	    print STDOUT "Flushing as user: ", $user->getEmail(), 
	    " Team: ", $user->getWorkingTeam()->getTeamName(),
	    " RoleId: ", $user->getWorkingTeam()->getWorkingRole()->getRoleId(),
	    " RoleType: ", $user->getWorkingTeam()->getWorkingRole()->getRoleType(), "\n";
	    print STDOUT "Creating a '", $entity->getOutDescription(), "' (",$entity->getOutPrefix(), ") entity - " .
		"sessionId: $sessionId ....\n";
	    #print STDOUT "**** ArrayingEntity has nothing to rearray ****\n", return if !$entity->hasArrayingData();
	    foreach my $atomicProcess (@{$entity->getAtomicProcessList()}) {
		#print "**** AtomicProcess has nothing to array ****\n", next if !$atomicProcess->hasArrayingData();
		my $aph = $atomicProcess->getArrayPatternHash();
		my $arrayPatternCount = 0;
		foreach my $inMapId (keys(%{$aph})) {
		    foreach my $arrayPattern (sort{$a->getOutMapId() <=> $b->getOutMapId()} @{$aph->{$inMapId}}) {
			my $inRow    = $arrayPattern->getInRow();
			my $inCol    = $arrayPattern->getInColumn();
			my $outRow   = $arrayPattern->getOutRow();
			my $outCol   = $arrayPattern->getOutColumn();
			my $outMapId = $arrayPattern->getOutMapId();
			foreach my $outData (@{$arrayPattern->getOutData()}) {
			    print STDOUT "\tInDataId: ", $atomicProcess->getInDataId() . 
				" -> In '$inRow$inCol' to Out '$outRow$outCol' with data '@$outData'\n";
			}
			$arrayPatternCount++;
		    }
		}
		$atomicProcessCount++;
		print STDOUT "\tArrayPattern count: $arrayPatternCount\n";
	    }
	    print STDOUT "AtomicProcess count: $atomicProcessCount\n";
	};
	if($@) { croak $@; }
    }

 
    #################################################################
    ## Method offered to subclasses. Further functionality to come.
    #################################################################
    sub beginTransaction    {}
    sub rollbackTransaction {}
    sub commitTransaction   {}


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

1;
