#
# $Id: LemurGetJobs.pm,v 1.21 2006/05/19 09:06:49 mdf Exp $

package LemurGetJobs;

require Exporter;

use     strict;
use     WrapDBI;
use     File::Basename;
use     FileHandle;
use     Carp;

#use     Data::Dumper;


##########################################
# CONSTANTS
# i use emacs - leave space after '\' char
##########################################

*LemurGetJobs::NUM_ROWS    = \20;
*LemurGetJobs::BITMAP_DIR  = \ "$ENV{'BADGER'}/lib/finch/bitmaps";

##########################################
# GLOBALS
##########################################

my $instanceCount = 0;
my $debug         = 0;
print STERR "testing";
################################################################################
# create Make Work window.
################################################################################

sub new {
    my ($type, $parentWindow, $dbUser, $session_id, $pathogen_mode) = @_;
    my (@dummy);
    my ($table);

    my $realUserName = getpwuid($<);

    my $self = {
	dbUser       => $dbUser,
	session_id   => $session_id,
	realUserName => "$realUserName",
        pathogen_mode => $pathogen_mode,
    };

    bless($self, $type);

    # INSTANCE COUNT STUFF. DESTROY decrements $instanceCount.
    # Don't think this is needed anymore...

    ++$instanceCount;

    if( $instanceCount > 1 ) {
	warn "\nThere is already a Select Job window active\n";
	return undef;
    }

    my (@localtime) = localtime;

    $self->{date} =  $localtime[3]."/".
	             ($localtime[4] + 1)."/".
	             ($localtime[5] + 1900);

    $self->setupHashTables();
    $self->createWindow($parentWindow);
    $self->getData();

    return $self;
}

sub createWindow {
    my ($self, $parentWindow) = @_;

    $self->{mw} = $parentWindow->Toplevel();
    my $mw      = $self->{mw};

    $mw->protocol('WM_DELETE_WINDOW' => sub { 
	$self->hide();
    });

    $mw->title('Select Jobs');
#    $mw->Label(width   => 40)->pack;
    $mw->Label(font    => '*-times-bold-r-normal--*-180-*-*-p-*-*-*',
	       text    => "Select jobs to do",
	       height  => 1,
	       -bg          => 'white',
	       -relief      => 'groove',
	       -borderwidth => '3',
	       )->pack(-side => 'top');
    $mw->Label(width   => 40)->pack;

    # mf : masterFrame , which contains;
    #   tf : Table Frame 
    #   upDownFrame
    
    my $mf = $mw->Frame(-relief => 'raised',);
    my $tf = $mf->Frame(-relief => 'raised',);

    $self->createTableFrame($tf);

    $tf->pack(-side => 'right');


    my ($upButton, $downButton, $makeWorkButton);
    my $upDownFrame = $mf->Frame();

    # Make an 'up-button';
    $mw->Bitmap('up',
		-file     => "$LemurGetJobs::BITMAP_DIR/uarrw.xbm",
		-maskfile => "$LemurGetJobs::BITMAP_DIR/uarrw.xbm"
	       );

    $upButton = $upDownFrame->Button(-image   => 'up',
				     -command => sub { $self->pressedUp; }); 
    $upButton->pack(-side => 'top');

    # Make an 'down-button';
    $mw->Bitmap('down',
		-file     => "$LemurGetJobs::BITMAP_DIR/darrw.xbm",
	       	-maskfile => "$LemurGetJobs::BITMAP_DIR/darrw.xbm"
		);
    
    $downButton = $upDownFrame->Button(-image   => 'down',
			               -command => sub { $self->pressedDown; });
    $downButton->pack(-side => 'bottom');

    $upDownFrame->pack(-side => 'left');
    $mf->pack(-side => 'top');

    # Generate buttons

    my $buttonFrame; 
    my $workToggButt;
    my $cancelButton;
    my $dummyLabel;

    $buttonFrame    = $mw->Frame(-relief => 'raised',);

    $makeWorkButton = $buttonFrame->Button(-text    => 'Print Jobs',
					   -width   => 12,
					   -command => sub{
					       $self->pressedMakeWork;
					   });

    my $label1  = $buttonFrame->Label(-width    => 5,
                                      );

    my $cancelJob = $buttonFrame->Button(-text    => 'Cancel Jobs',
                                         -width   => 12,
                                         -command => sub{
                                             $self->pressedCancelJobs();
                                         });

    my $pageNum = 
	$buttonFrame->Label(-text     => 'Page 1',
			    -textvariable => \$self->{pageNumLabel},
			    -width    => 30,
			    );



    $workToggButt =
	$buttonFrame->Checkbutton(-text     => 'Show Jobs already printed',
				  -width    => 30,
				  -variable =>
				      \$self->{showAllJobs},
				  -command => sub{
				      LemurUtils->setWait([$mw]);
				      $self->getData( $self->{showAllJobs} );
				      LemurUtils->unSetWait([$mw]);
				  },
				  );

    $cancelButton   = $buttonFrame->Button(-text    => 'Done',
					   -width   => 12,
					   -command => sub {
					       $self->hide();
					   });

    $makeWorkButton->grid (-row => 1, -column => 1);
    $label1->grid         (-row => 1, -column => 2);
    $cancelJob->grid      (-row => 1, -column => 3);
    $pageNum->grid        (-row => 1, -column => 4);
    $workToggButt->grid   (-row => 1, -column => 5);
    $cancelButton->grid   (-row => 1, -column => 6);

    $buttonFrame->pack(-side => 'bottom');
}

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

    $self->{mw}->deiconify();
}

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

    $self->{cancel_job_window}->goAway() if defined($self->{cancel_job_window});
    delete $self->{cancel_job_window};

    $self->{mw}->withdraw();
}

#
# this pulls out of the DB all Jobs that need doing. It can be called many
# times by the 'Show Jobs already printed'. If called via this button, it 
# passes in extra arg, $getJobsPrinted to say which STATUS's to get.
#

sub getData {
    my ($self, $getJobsPrinted) = @_;
    my ($dbh, $ref_rows);

    $self->clearEverything();

    # Get SIL_REQUEST's that are new.

    my $refClonesLigated;
    my $jobsWanted;
    my $species_wanted;

    unless( $getJobsPrinted ) {
	$jobsWanted = 
	    "and    srs.STATUS    = 1";
    }
    else {
	$jobsWanted =
	    "and    (    srs.STATUS    = 1
                     OR srs.STATUS    = 2)";
    }

    if( $self->{pathogen_mode} ){
       # $species_wanted = "and    c.SPECIESNAME NOT IN ('Human', 'Mouse', 'Zebrafish', 'Dog')";
       $species_wanted = "and tpr.teamname in (21,23,24,25)";
    }
    else {
        #$species_wanted = "and    c.SPECIESNAME IN ('Human', 'Mouse', 'Zebrafish', 'Dog')";
	$species_wanted = "and tpr.teamname  in (44,46,47,48,60)";
    }

    eval {
	$dbh = WrapDBI->connect($self->{dbUser}, {RaiseError => 1});
	expire("Could not connect to database") if !defined $dbh;
	$dbh->{AutoCommit} = 0;

	$ref_rows = $dbh->fetch_all("
            select sr.ID_REQUEST, p.FORENAME, p.SURNAME, std.DESCRIPTION,
                   sds.CLONENAME,
                   c.SPECIESNAME, cd.Description
            from   SIL_REQUEST      sr, SILREQUEST_STATUS srs,
                   SILTYPEDICT      std,
                   SIL_DNASOURCE    sds,
                   CLONE            c,
                   TEAM_PERSON_ROLE tpr,
                   PERSON           p,
                   CHROMOSOMEDICT   cd
            where  srs.ID_REQUEST  = sr.ID_REQUEST
            $jobsWanted
            and    srs.ISCURRENT   = 1
            and    sr.SIL_TYPE     = std.ID_DICT
            and    sds.ID_SOURCE   = sr.ID_SOURCE
            and    sds.CLONENAME   = c.CLONENAME
            $species_wanted
            and    sr.REQUESTED_BY = tpr.ID_ROLE
            and    tpr.ID_PERSON   = p.ID_PERSON
            and    c.CHROMOSOME    = cd.ID_DICT (+)
            order by sr.ID_REQUEST
            ");
    };

    LemurUtils->showError($self->{mw},"$@\n") if ($@);

    $dbh->disconnect if $dbh;

    # For each Job Request, store its details

    my ($id_request, $requested_by, $SIL_type,
        $cloneName,
	$speciesName, $chromosome);
    my ($i);

    my $x = 0;
    my $row;

    foreach $row (@$ref_rows) {

	$id_request    = $row->[0];
	$requested_by  = $row->[1]." ".$row->[2];
        $SIL_type      = $row->[3];
	$cloneName     = $row->[4];
	$speciesName   = $row->[5];
	$chromosome    = $row->[6];

	push( @{$self->{dataStore}->[$x]} , "$id_request"     );   # 0
	push( @{$self->{dataStore}->[$x]} , $SIL_type         );   # 1
	push( @{$self->{dataStore}->[$x]} , $cloneName        );   # 2
	push( @{$self->{dataStore}->[$x]} , $speciesName      );   # 3
	push( @{$self->{dataStore}->[$x]} , $requested_by     );   # 4
	push( @{$self->{dataStore}->[$x]} , $chromosome       );   # 5

        # 10 is the person assigned to the job
        # 15 is marked for deletion

#	print "id_request   == ", $self->{dataStore}->[$x]->[0], "\n";
#	print "requested_by == ", $self->{dataStore}->[$x]->[1], "\n";
#	print "SIL_type     == ", $self->{dataStore}->[$x]->[2], "\n";
#	print "cloneName    == ", $self->{dataStore}->[$x]->[3], "\n";
#	print "speciesName  == ", $self->{dataStore}->[$x]->[4], "\n";
#	print "chromosome   == ", $self->{dataStore}->[$x]->[5], "\n\n";

	$x++;
    }

    $dbh->disconnect if $dbh;

    ##################################################
    # now sort the dataStore. Squash all DNA Prep Nums
    # into one row of text, so only 1 clone per line
    ##################################################

    my $numRecs;

    unless( defined($self->{dataStore}) ) {
	warn "no records found\n";
    }

    # set Page X of Y and draw draw the screen
    my $numPages = 0;

    if( $self->{dataStore} && @{$self->{dataStore}} ){
        $numPages     = scalar(@{$self->{dataStore}}) / $LemurGetJobs::NUM_ROWS;
        $numPages     =~ s/(\.\d+)$//;
        ++$numPages if $1;
    }

    $self->{numberOfPages} = $numPages;
    $self->{pageNum}       = 1;
    $self->{pageNumLabel}  = "Page $self->{pageNum} of $self->{numberOfPages}";

    $self->redrawScreen();
}

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

    $self->{pageNum}++;
    $self->{pageNumLabel}  = "Page $self->{pageNum} of $self->{numberOfPages}";
}

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

    $self->{pageNum}--;
    $self->{pageNumLabel}  = "Page $self->{pageNum} of $self->{numberOfPages}";
}

################################################################################
# connects to DB and handles any errors. Calls various subroutines to setup
# hash tables with data from dictionaries.
################################################################################

sub setupHashTables {

    my ($self) = @_;
    my ($dbh);

    eval {
	$dbh = WrapDBI->connect($self->{dbUser}, {RaiseError => 1});
	expire("Could not connect to database") if !defined $dbh;
	$dbh->{AutoCommit} = 0;

	$self->getSubcloners($dbh);

    };

    if ($@) {
	if ($DBI::err) {
	    $self->expire("$DBI::errstr: $@ Occured in setupHashtables()");
	} else {
	    $self->expire("$@: Occured in setupHashtables()");
	}
    }

    $dbh->disconnect if $dbh;
}

################################################################################
# setup $self->{operatorHash}
################################################################################

sub getSubcloners {

    my ($self, $dbh) = @_;
    my ($arrayOfArrays, $arrayRef);
    my %operatorHash;

    $arrayOfArrays = $dbh->fetch_all(
         "select PERSON.ID_PERSON, PERSON.FORENAME, PERSON.SURNAME, PERSON.EMAIL
          from   PERSON, TEAM_PERSON_ROLE
          where  TEAM_PERSON_ROLE.ROLETYPE  = 'Subcloning' 
          and    TEAM_PERSON_ROLE.ID_PERSON = PERSON.ID_PERSON "); 
 
    foreach $arrayRef (@$arrayOfArrays) {
	my $fullName = (@$arrayRef[1]." ".@$arrayRef[2]);

	$operatorHash{$fullName}          = @$arrayRef[0];
	$self->{email_id_of}->{$fullName} = @$arrayRef[3];
    }

    $operatorHash{'<nobody>'} = ''; # if user selected someone, then changed 
                                    # there mind.

    $self->{operatorHash} = \%operatorHash;
}
################################################################################
# 
# When trying to set the BrowseEntry widget to 
#     -variable => \$self->{dataStore}->[$x]->[10]
# it did not work correctly. This maybe due to an old Tk version. I have now
# given up on trying to make it work!
################################################################################

sub createTableFrame {

    my ($self, $tf) = @_;
    my $widgets     = $self->{widgets};
    my ($x, $y);

    # x and y are the wrong way round here - y is on x axis....


    for($x = 0; $x <= $LemurGetJobs::NUM_ROWS; $x++) {

	# create 5 label widgets
	my $width = 16;

	for($y = 0; $y < 6; $y++) {
	     if(    $y == 0 ) { $width = 10; }
             elsif( $y == 2 ) { $width = 15;  }
             elsif( $y == 3 ) { $width = 10; }
	     elsif( $y == 4 ) { $width = 26; }
	     else { $width = 16; }

	    $self->{widgets}->[$x][$y] = $tf->Label(-relief => 'sunken',
						    -width  => $width,
						    -bg     => 'lightblue');
	    $self->{widgets}->[$x][$y]->grid(-row => $x+1, -column => $y);
	}

	# Entry gadget - who will do the ligations for this DNA Prep.
        # Make sure create label for column heading only.

	if( $x == 0 ) {
	    $self->{widgets}->[$x][$y] = $tf->Label(-text   => "Make Work",
						    -relief => 'sunken',
						    -width  => 20,
						    -bg     => 'lightblue');
	}
	else {
	    # weirdness here with '-variable => \$assignTo[$x]'. 
	    # See above comment
	    $self->{widgets}->[$x][$y] =
		$tf->BrowseEntry(-width    => 18,
				 -relief   => 'sunken',
				 -state    => 'readonly',
				 -variable => \$self->{assignTo}->[$x],
				 -choices  => 
				     [ sort keys %{$self->{operatorHash}} ],
				 -browsecmd => $self->subby("$x"),
				 );
	}

        $self->{widgets}->[$x][$y]->grid(-row    => $x + 1, 
					 -column => $y);
    }

    # put in column headings

    $self->{widgets}->[0][0]->configure(text => "Request",
					bg   => 'grey');
    $self->{widgets}->[0][1]->configure(text => "Description",
					bg   => 'grey');
    $self->{widgets}->[0][2]->configure(text => "Clone",
					bg   => 'grey');
    $self->{widgets}->[0][3]->configure(text => "Species",
					bg   => 'grey');
    $self->{widgets}->[0][4]->configure(text => "Submitter",
					bg   => 'grey');
    $self->{widgets}->[0][5]->configure(text => "Chromo",
					bg   => 'grey');
    $self->{widgets}->[0][6]->configure(text => "Assign to:",
					bg   => 'grey');
}

#
# Used to clear $self->{assignTo}->[$x] to '' when <nobody> is selected on
# BrowseEntry widget.
#

sub subby {
    my $self = shift;
    my $x    = shift;

    return sub {
	if( $self->{assignTo}->[$x] eq '<nobody>' ) {
	    $self->{assignTo}->[$x] = '';
	}
    }
}
    
################################################################################
#  blow away old stuff - could be re-displaying data
################################################################################

sub clearEverything {

    my ($self) = @_;

    delete $self->{dataStore};
    $self->{cursor} = 0;

    if( exists($self->{cancel_job_window}) ){
        $self->{cancel_job_window}->goAway(); # Cancel Job object
        delete $self->{cancel_job_window};
    }

    foreach my $i ( 1..$LemurGetJobs::NUM_ROWS ) {
	$self->{widgets}->[$i][0]->configure(text => "");
	$self->{widgets}->[$i][1]->configure(text => "");
	$self->{widgets}->[$i][2]->configure(text => "");
	$self->{widgets}->[$i][3]->configure(text => "");
	$self->{widgets}->[$i][4]->configure(text => "");
	$self->{widgets}->[$i][5]->configure(text => "");
	
	$self->{widgets}->[$i][6]->configure(-state => 'disabled');

	$self->{widgets}->[$i][0]->configure(fg => 'black');
	$self->{widgets}->[$i][1]->configure(fg => 'black');
	$self->{widgets}->[$i][2]->configure(fg => 'black');
	$self->{widgets}->[$i][3]->configure(fg => 'black');
	$self->{widgets}->[$i][4]->configure(fg => 'black');
	$self->{widgets}->[$i][5]->configure(fg => 'black');

	$self->{assignTo}->[$i] = '';
    }
}

################################################################################
# show the last $NUM_ROWS of data above the current 'position'
################################################################################

sub pressedUp {

#    print "\nUp was pressed - cursor == $self->{cursor}\n";
    my ($self)     = @_;
    my $cursorToBe;
    my $lastIndex  = $#{$self->{dataStore}};
    my $widgets    = $self->{widgets};

    if( $self->{cursor} <= 1 ) { 
	return; 
    }

    $self->decPageNum();

    # Save the data entered before scrolling up

    my $i = 1;
    my $x;

    foreach $x ($self->{cursor} ..
                $self->{cursor} + $LemurGetJobs::NUM_ROWS - 1) {
	last if( ! defined($self->{dataStore}->[$x]) );

	$self->{dataStore}->[$x]->[10] = $self->{assignTo}->[$i];
	$i++;
    }

    # if NUM_ROWS == 1, this won't work.
    if( ($self->{cursor} - $LemurGetJobs::NUM_ROWS) <= 1 )  {
	$self->{cursor} = 0;
    }
    else {
	$self->{cursor} = $self->{cursor} - $LemurGetJobs::NUM_ROWS;
    }

    $self->redrawScreen();
}

################################################################################
# show the next $NUM_ROWS of data below the current position
################################################################################

sub pressedDown {

#    print "\nDown was pressed. cursor == $self->{cursor}\n";
    my ($self)    = @_;
    my $lastIndex = $#{$self->{dataStore}};
    my $i         = 1;  # starts at one 'cos BrowseEntry widget starts there.
    my $x         = 0;
    my $widgets   = $self->{widgets};

    if( ($self->{cursor} + $LemurGetJobs::NUM_ROWS) < ($lastIndex + 1)) {

	# Save operator names to $self->{dataStore}
    
	foreach $x ($self->{cursor} .. 
                    $self->{cursor} + $LemurGetJobs::NUM_ROWS - 1) {

	    $self->{dataStore}->[$x]->[10] = $self->{assignTo}->[$i];
	    $i++;
	}

	$self->{cursor} += $LemurGetJobs::NUM_ROWS;
#	print "Updated cursor == $self->{cursor} , last index == $lastIndex\n";
    }
    else {
#	print "can't go down - cursor at self->{$cursor}\n";
	return;
    }

    $self->incPageNum();

    $self->redrawScreen();
}

# redisplay the the data from cursor to cursor + NUM_ROWS
# loop for each member in the dataStore.
#
sub redrawScreen {
    my ($self)  = @_;
    my $widgets = $self->{widgets};
    my $i       = 0;
    my $x;

    foreach $x ($self->{cursor} .. 
                ($self->{cursor} + $LemurGetJobs::NUM_ROWS - 1)) {

	++$i;

	if( ! defined($self->{dataStore}->[$x]) ) {
	    $widgets->[$i][0]->configure(text => "");
	    $widgets->[$i][1]->configure(text => "");
	    $widgets->[$i][2]->configure(text => "");
	    $widgets->[$i][3]->configure(text => "");
	    $widgets->[$i][4]->configure(text => "");
	    $widgets->[$i][5]->configure(text => "");
	    $widgets->[$i][6]->configure(-state => 'disabled');
	    $self->{assignTo}->[$i] = "";

	    next;
	}

	$widgets->[$i][0]->configure(text => "$self->{dataStore}->[$x]->[0]");
	$widgets->[$i][1]->configure(text => "$self->{dataStore}->[$x]->[1]");
	$widgets->[$i][2]->configure(text => "$self->{dataStore}->[$x]->[2]");
	$widgets->[$i][3]->configure(text => "$self->{dataStore}->[$x]->[3]");
	$widgets->[$i][4]->configure(text => "$self->{dataStore}->[$x]->[4]");
	$widgets->[$i][5]->configure(text => "$self->{dataStore}->[$x]->[5]");

        # marked for deletion?
	if( $self->{dataStore}->[$x]->[15] == 1 ) {
	    $widgets->[$i][0]->configure(fg => 'red');
	    $widgets->[$i][1]->configure(fg => 'red');
	    $widgets->[$i][2]->configure(fg => 'red');
	    $widgets->[$i][3]->configure(fg => 'red');
	    $widgets->[$i][4]->configure(fg => 'red');
	    $widgets->[$i][5]->configure(fg => 'red');
	}
	else {
	    $widgets->[$i][0]->configure(fg => 'black');
	    $widgets->[$i][1]->configure(fg => 'black');
	    $widgets->[$i][2]->configure(fg => 'black');
	    $widgets->[$i][3]->configure(fg => 'black');
	    $widgets->[$i][4]->configure(fg => 'black');
	    $widgets->[$i][5]->configure(fg => 'black');
	}

	$self->{assignTo}->[$i] = $self->{dataStore}->[$x]->[10];
	$widgets->[$i][6]->configure(-state => 'normal');
    }
}

################################################################################
# Connect to DB - wrapper for calling &printWorkSheets()
################################################################################

sub pressedMakeWork {

    my ($self) = @_;
    my $dbh;
    # connect to DB and pass $dbh into printWorkSheets

    eval {
	$dbh = WrapDBI->connect($self->{dbUser}, {RaiseError => 1});
	expire("Could not connect to database") if !defined $dbh;
	$dbh->{AutoCommit} = 0;

	$self->printWorkSheets($dbh);
    };

    if ($@) {
	LemurUtils->showError($self->{mw},"$@\n");
	$dbh->rollback if $dbh;
    }
    else {
	$dbh->disconnect if $dbh;
    }
}

################################################################################
# work down the 'Assign To' column and look for a persons name not in the hash
# %alreadyAssigned. If not, look for more occurances and push details of each
# clone/prep number onto @workForPerson.
#
# When the end of the list is found it writes everything stored in 
# @workForPerson to the printer via genscript (to get landscape mode).
#
# It repeats the whole process for the next person.
################################################################################

sub printWorkSheets {

    my ($self, $dbh)   = @_;

    my %alreadyAssigned;
    my $firstIndex     = 0;
    my $printer        = $ENV{'PRINTER'};
    my $workSheetCount = 1;
    my $totalJobCount  = 0;
    my $jobsPerPage    = 2; # 3 is good but not be enough space for restriction


    LemurUtils->setWait([$self->{mw}]);

    # Save operator names to $self->{dataStore}
    
    my ($x, $i);
    $i = 1;

    foreach $x ($self->{cursor} .. 
		$self->{cursor} + $LemurGetJobs::NUM_ROWS - 1) {
	$self->{dataStore}->[$x]->[10] = $self->{assignTo}->[$i];
	$i++;
    }

    if( $printer eq '' ) {
        $printer = "d324bw"; # one nearest Matt Jones.
	warn "Using default printer 'd324bw' \n";
    }
    else {
	warn "Using printer '$printer'\n";
    }

    # get clones to fragment. If a person has been assigned to a clone, collect
    # all the others he has been assigned.

    foreach my $jobArray (@{$self->{dataStore}}) {

	my $person = $jobArray->[10];
	my @workForPerson;

	my $id_request;           # These variables are used in the
	my $requested_by;         # report generated off the Generate Work
	my $SIL_type;             # Sheets button
	my $cloneName;
	my $speciesName;
	my $chromosome;
	my @frags;
	my ($PCRproductSize,
	    $PCRforwardPrimer,
	    $PCRreversePrimer,
	    $PCRKinase,
	    $PCRpurify);

	# if person not already been assigned work already, get all work for 
	# other clones that his name is against.

	my $first = 0;

	if( ($alreadyAssigned{$person} == 0) && ($person ne '') ) {
	    my $rowArray;

	    for(my $x = $firstIndex;
		$x < scalar(@{$self->{dataStore}});
		++$x  ) {

		$rowArray = @{$self->{dataStore}}->[$x];

		if( $person eq @$rowArray->[10] ) {
		    push @workForPerson, $rowArray;
		}
	    }

	    $alreadyAssigned{$person} = 1;
	}

	# print a report for this person if he has work assigned.

	select(WORKSHEET);

	++$firstIndex;

	unless( scalar(@workForPerson) > 0 ) {
	    next;
	}

	open(WORKSHEET,
		 "| genscript  -P$printer -b 'Work for: $person\n".
		 "      Date assigned: $self->{date}'");
#	     "| more");

#	warn "\n\nWork for: $person\n";

	my $width     = 20;
	my $jobCount  = 0;

	$totalJobCount += scalar(@workForPerson);

	foreach my $work ( @workForPerson ) {

	    my ($consensus_file, $gap_coord, $enzyme_name);

	    $id_request   = $work->[0];
	    $SIL_type     = $work->[1];
	    $cloneName    = $work->[2];
	    $speciesName  = $work->[3];
	    $requested_by = $work->[4];
	    $chromosome   = $work->[5];

	    my ($comment, $gap_size, $preferred_vector) = $dbh->fetch_row("
                select REMARK, GAP_SIZE_KB, PREFERRED_VECTOR
                from   SIL_REQUEST
                where  ID_REQUEST = $id_request");

	    if( defined($preferred_vector) ){
		my ($vector_name, $enzyme) = $dbh->fetch_row("
                    select v.VECTORNAME, ve.ENZYMENAME
                    from   VECTORSITE v, VECTORSITE_ENZYME ve
                    where  v.ID_VECTORSITE = ve.ID_VECTORSITE
                    and    v.ID_VECTORSITE = $preferred_vector"); 

		$preferred_vector = "$vector_name ($enzyme)";
	    }

	    # linefeed needed?

	    if( $jobCount < $jobsPerPage ) {
		++$jobCount;
	    }
	    else {
		printf WORKSHEET "\f" ;
		$jobCount = 1;
		++$workSheetCount;
	    }

	    if( $jobCount != 1 ) {
		printf "\n";
		printf "----------------------------------------".
		        "---------------------------------------".
			"--------\n\n" ;
	    }

	    ($PCRforwardPrimer,
	     $PCRreversePrimer,
	     $PCRproductSize,
	     $PCRpurify,
	     $PCRKinase) = $self->getPCRInfo($dbh, $id_request);

	    my @array2 = $dbh->fetch_row("
                    select CONSENSUS_FILE, GAP_COORDINATE, ENZYMENAME
                    from   SIL_RESTRICTION
                    where  ID_REQUEST = $id_request");

	    if( defined(@array2) ) {
		$consensus_file = $array2[0];
		$gap_coord      = $array2[1];
		$enzyme_name    = $array2[2];
	    }

	    my $arrayOfArrays3 = $dbh->fetch_all("
                select FROM_BP, TO_BP
                from   SIL_INSERTSIZE
                where  ID_REQUEST = $id_request");

	    my $fragCount = 0;

	    foreach my $row (@{$arrayOfArrays3}) {
		$frags[$fragCount][0] = $row->[0];
		$frags[$fragCount][1] = $row->[1];

		++$fragCount;
	    }

	    # get Subclone stuff: plate num, row, col, vector/enzyme

	    my ($plateName, $row, $col, $vectorName, $enzymeName) = @{ [] };

	    my @array4 = $dbh->fetch_row("
                select  sds.PLATENAME,
                        rcm.MAPROW, rcm.MAPCOL,
                        vs.VECTORNAME,
                        vse.ENZYMENAME
                 from   SIL_REQUEST sr, SIL_DNASOURCE sds,
                        ROWCOL_MAP rcm, VECTORSITE vs, VECTORSITE_ENZYME vse
                 where  sr.ID_REQUEST     = $id_request
		 and    sr.ID_SOURCE      = sds.ID_SOURCE
                 and    sds.ID_MAP        = rcm.ID_MAP
                 and    sds.ID_VECTORSITE = vs.ID_VECTORSITE
                 and    vs.ID_VECTORSITE  = vse.ID_VECTORSITE");

	    $plateName  = $array4[0];
	    $row        = $array4[1];
	    $col        = $array4[2];
	    $vectorName = $array4[3];
	    $enzymeName = $array4[4];

	    printf "\n\n";
	    printf "Request   : %-${width}d \n", $id_request   ;
	    printf "Job Type  : %-${width}s \n", $SIL_type     ;
	    printf "Submitter : %-${width}s \n", $requested_by ;
	    printf "Clone     : %-${width}s \n", $cloneName    ;
	    printf "Species   : %-${width}s \n", $speciesName  ;
	    printf "Chromosome: %-${width}s \n", $chromosome   ;
	    printf "\n", ;

	    if(   defined($PCRforwardPrimer)
	       && (   $SIL_type ne 'Genome Walk'
		   && $SIL_type ne 'Oligo Screening' )) {

		printf "PCR:\n", ;
		printf "     Est. Product Size: $PCRproductSize\n",;
		printf "     Forward Primer   : $PCRforwardPrimer\n",;
		printf "     Reverse Primer   : $PCRreversePrimer\n",
WORKSHEET->autoflush(1); # bizarre bug - above line not output in correct order
		printf "     Kinase           : $PCRKinase\n", ;
		printf "     Purify from Gel  : $PCRpurify\n", ;
		printf "\n";
	    }

	    if( defined $gap_size){
		printf "Gap Size  : $gap_size\n\n", ;
	    }

	    if( defined $preferred_vector ){
		printf "Preferred Vector: $preferred_vector\n", ;
		printf "\n", ;
	    }


	    if( defined($PCRforwardPrimer) && $SIL_type eq 'Genome Walk' ){
		printf "Genome Walk:\n", ;
		printf "     Outer Primer: $PCRforwardPrimer \n",;
		printf "     Inner Primer: $PCRreversePrimer\n", ;
		printf "\n", ;
	    }

		
	    if( defined($PCRforwardPrimer) && $SIL_type eq 'Oligo Screening' ){
		printf "Oligo Screening:\n", ;
		printf "     Forward Primer: $PCRforwardPrimer\n";
		printf "     Reverse Primer: $PCRreversePrimer\n",;
		printf "\n", ;
	    }

	    if( $SIL_type eq 'Restriction' ) {
		printf "Restriction:\n", ;
		printf "     Consensus file  : $consensus_file\n", ;
		printf "     Gap Coord       : $gap_coord\n", ;
		printf "     Suggested Enzyme: $enzyme_name\n", ;
		printf "\n", ;
	    }

	    if( defined($plateName) ) {
		printf "Sub Clone\n";
		printf "     Plate Name          : $plateName\n" ;
		printf "     Row                 : $row\n" ;
		printf "     Col                 : $col\n" ;
		printf "     Vector Name         : $vectorName\n" ;
		printf "     Vector cut by Enzyme: $enzymeName\n" ;
		printf "\n", ;
	    }

	    if( $SIL_type eq 'Oligo Screening' ) {
		if( scalar(@frags) > 0 ){
		    printf "Screen for size: $frags[0][0] To $frags[0][1] bp";
		}
		else {
		    printf "Error: do not know size to screen for\n";
		}
	    }
	    elsif( scalar(@frags) > 0 ){
		printf"Desired Fragment Sizes:\n";

		for ( 0..$#frags) {
		    printf "     Fragment ".($_ + 1)."  From $frags[$_][0]".
			                             "  To $frags[$_][1] bp\n";
		}
	    }

	    printf "\n";
	    printf "Finishers comment: \n";
	    printf "     $comment \n";

	    $self->createSILStatus($dbh, $id_request, $person);
	}

	close(WORKSHEET);
    }


    my $remainder += $totalJobCount % $jobsPerPage;
    my $numPages   = ($totalJobCount - $remainder) / $jobsPerPage;
    ++$numPages if $remainder > 0;

    LemurUtils->unSetWait([$self->{mw}]);

    warn "Printing complete\n";
    LemurUtils->showInfo($self->{mw},
			 "Printing complete. Please collect $numPages ".
			 "work sheet(s) from the printer");
}

sub getPCRInfo {
    my ($self, $dbh, $id_request) = @_;
    my @array;

    my $arrayOfArrays1 = $dbh->fetch_all("
		    select FWD_PRIMER, REV_PRIMER, EST_PRODUCT_SIZE_KB,
		           GEL_PURIFY, WITH_KINASE
	            from   SIL_PCR
		    where  ID_REQUEST = $id_request");

    my $arrayRefPCR = $arrayOfArrays1->[0];

    if( defined($arrayRefPCR) ) {

	my $PCRpurify = $arrayRefPCR->[3];
	my $PCRKinase = $arrayRefPCR->[4];

	if( $PCRpurify == 0 ){
	    $PCRpurify = 'No';
	} else {
	    $PCRpurify = 'Yes';
	}

	if( $PCRKinase == 0 ){
	    $PCRKinase = 'No';
	} else {
	    $PCRKinase = 'Yes';
	}

	push @array, $arrayRefPCR->[0];
	push @array, $arrayRefPCR->[1];
	push @array, $arrayRefPCR->[2];
	push @array, $PCRpurify;
	push @array, $PCRKinase;

	return @array;
    }
    else {
	return;
    }
}

#
# mark request as being assign to a subcloner ($person)
# checks if this has already been done today....
#

sub createSILStatus {
    my ($self, $dbh, $id_request, $fullName) = @_;

    my $email_id = $self->{email_id_of}->{$fullName};

    my $count = $dbh->fetch_scalar("
                select count(*)
                from   SILREQUEST_STATUS
                where  ID_REQUEST = $id_request
                and    STATUS     = 2
                and    STATUSDATE = to_date('$self->{date}', 'dd/mm/yyyy')");

    if( $count > 0 ) {
	$dbh->do("
                update SILREQUEST_STATUS
                set    OPERATOR   = '$email_id'
                where  ID_REQUEST = $id_request
                and    STATUS     = 2
                and    STATUSDATE = to_date('$self->{date}', 'dd/mm/yyyy')");

    }
    else {

	$dbh->do("
                update SILREQUEST_STATUS
                set    ISCURRENT  = 0
                where  ID_REQUEST = $id_request");

	$dbh->do("
                insert into SILREQUEST_STATUS
                       (ID_REQUEST,
                        STATUS,
                        STATUSDATE,
                        ISCURRENT,
                        SESSIONID,
                        PROGRAM,
                        OPERATOR)
                values ($id_request,
                        2,
                        to_date('$self->{date}', 'dd/mm/yyyy'),
                        1,
                        $self->{session_id},
                        'LemurGetJobs',
                        '$email_id')");
    }
}

sub expire {

    my ($self, $errorMsg, $dbh) = @_;

    $dbh->disconnect if $dbh; 
    warn "ERROR: $errorMsg\n";

    Mail::sendMail( -to      => 'bug',
                    -subject => "Lemur: Error in GetJobs.", 
                    -message => $errorMsg);

    die "\n";
}

sub pressedCancelJobs {
    my ($self) = @_;
    my @temp   = $self->getJobs();

    $self->{cancel_job_window} = CancelJobs->new($self, $self->{mw}, @temp);
}

sub getJobs {
    my ($self) = @_;
    my @temp;

    foreach ( @{$self->{dataStore}} ){
        push @temp, $_->[0];
    }

    return @temp;
}

# called by CancelJobs object
# in dataStore, [0] = job id, [15] = mark for delete flag
sub markForCancel {
    my ($self, $job_num) = @_;

    foreach my $data ( @{$self->{dataStore}} ){
        if( $data->[0] == $job_num ){
            $data->[15] = 1;
            last;
        }
    }

    $self->redrawScreen();
}

# called by CanelJOb object
sub unCancelEverything {
    my ($self) = @_;

    foreach my $data ( @{$self->{dataStore}} ){
        $data->[15] = 0;
    }

    $self->redrawScreen();
}

# called by CancelJob object
sub cancelJobs {
    my ($self) = @_;

    warn "cancelJobs called\n";

    LemurUtils->setWait([$self->{mw}]);

    foreach my $data ( @{$self->{dataStore}} ){
        if( $data->[15] == 1 ){
            my $job_num = $data->[0];
            my $dbh;

            eval {
                $dbh = WrapDBI->connect($self->{dbUser}, {RaiseError => 1});
                expire("Could not connect to database") if !defined $dbh;
                $dbh->{AutoCommit} = 0;

                $dbh->do(qq[
                            update SILREQUEST_STATUS
                            set    ISCURRENT  = 0
                            where  ID_REQUEST = $job_num
                            ]);

                $dbh->do(qq[
                            insert into SILREQUEST_STATUS
                            values ($job_num,
                                    4,
                                    SYSDATE,
                                    1,
                                    $self->{session_id},
                                    'LemurGetJobs',
                                    '$self->{realUserName}')
                            ]);
            };

            if( $@ ){
                LemurUtils->showError($self->{mw},
                                      "Error accessing DB:\n$@");
                warn "$@\n" if $debug;
            }
            else {
                $dbh->commit; # COMMIT
            }
            $dbh->disconnect if $dbh;
        }
    }

    $self->getData( $self->{showAllJobs} );
    LemurUtils->unSetWait([$self->{mw}]);
}


DESTROY {
    my $self = shift;
    warn "Wrong type passed to LemurGetJobs->DESTROY '$self'" unless ref $self;
    --$instanceCount;
    delete($self->{cancel_job_window});
}

###############################################################################
# this is a simple object that conssists of a basic window where you enter a 
# job number to delete. It makes calls back into the above object to highlight
# jobs in red - marked for deletion. When Done is pressed the user is asked if
# they want ti cancel jobs x, y, z.
################################################################################
package CancelJobs;

my $debug = 0;

sub new {
    my ($type, $parent_self, $parent_window, @job_numbers) = @_;

    my $self = {
        parent_self   => $parent_self,
        parent_window => $parent_window,
        job_numbers   => \@job_numbers, # used for validating user input
    };
    bless($self, $type);

    $self->createWindow();

    return $self;
}

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

    $self->{mw} = $self->{parent_window}->Toplevel();
    my $mw      = $self->{mw};
    $mw->title('Cancel Job');

    my $b =
        $mw->Button(-font        => '*-times-bold-r-normal--*-180-*-*-p-*-*-*',
                    -text        => 'Cancel Jobs',
                    -height      => 1,
                    -bg          => 'white',
                    -relief      => 'groove',
                    -borderwidth => '3',
                    )->pack(-side => 'top');

    $b->bindtags(['DebugButton',$b->toplevel,'all']);
    $b->bind('DebugButton', '<Control-Button-2>', sub{ 
        warn "\$debug was $debug, setting to 1\n";
        $debug = 1;
    });

    my $job_num = $mw->Entry(-width        => 17,
                             -relief       => 'sunken',
                             -bg           => 'lemonchiffon2',
                             -textvariable => \$self->{job_num},
                             )->pack;

    $job_num->bind("<KeyPress-Return>", sub { $self->nextPressed; } );

    my $frame = $mw->Frame->pack;
    $frame->Button(-text    => 'Next',
                   -width   => 6,
                   -command => sub { $self->nextPressed; },
                   )->pack(-side => 'left');
    $frame->Button(-text    => 'Done',
                   -width   => 6,
                   -command => sub{ $self->donePressed(); },
                   )->pack(-side => 'right');
}

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

    $self->{job_num} =~ s/^\s+//; # remove leading & trailing whitespace
    $self->{job_num} =~ s/\s+$//;
    

    return if $self->{job_num} eq '';

    if( $self->{job_num} !~ /^\d+$/ ){
        LemurUtils->showError($self->{mw},
                              "Please enter a valid number with no spaces");
        return;
    }

    # if it's already in the list, don't do nothing
    my $answer = grep /^$self->{job_num}$/, @{$self->{marked_jobs}};
    return if $answer > 0;

    # if it gets here its a valid number, see if it is a valid job
    $answer = grep /^$self->{job_num}$/, @{$self->{job_numbers}};

    if( $answer == 0 ){
        # user may have updated parent window with more jobs since this object
        # was created. Check.
        my @temp = $self->{parent_self}->getJobs();

        $answer = grep /^$self->{job_num}$/, @temp;

        if( $answer == 1 ){
            @{$self->{job_numbers}} = @temp;
        }
        else {
            LemurUtils->showError($self->{mw},
                                  "That was not a valid Job Number. ".
                                  "Try Again!");
            return;
        }
    }

    push @{$self->{marked_jobs}}, $self->{job_num};
    $self->{parent_self}->markForCancel($self->{job_num});
}

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

    my $answer = LemurUtils->yesNo($self->{mw},
                                   "Do you want to delete Jobs\n".
                                   join(', ', @{$self->{marked_jobs}}).
                                   " ?");

    if( $answer eq 'Yes' ){
        $self->{mw}->destroy;
        delete $self->{mw};

        $self->{parent_self}->cancelJobs;
        delete $self->{marked_jobs};
    }
    else {
        $self->{mw}->destroy;
        delete $self->{mw};

        delete $self->{marked_jobs};
        $self->{parent_self}->unCancelEverything();
    }
}

sub goAway {
    my $self = shift;
    $self->{mw}->withdraw() if $self->{mw};
}

sub DESTROY {
    my $self = shift;
    warn "Wrong type passed to CancelJobs->DESTROY '$self'" unless ref $self;

    $self->{mw}->destroy if $self->{mw};
}

# End of Module #
1;


#
# $Log: LemurGetJobs.pm,v $
# Revision 1.21  2006/05/19  09:06:49  mdf
# *** empty log message ***
#
# Revision 1.20  2006/05/12  09:45:54  mdf
# *** empty log message ***
#
# Revision 1.19  2006/05/12  09:44:56  mdf
# changed the pathogen lookup to be team rather than species specific
#
# Revision 1.18  2001/10/02  12:40:47  holroyd
# Added 'Dog' to the list of species to fetch/disregard in the SQL.
#
# Revision 1.17  2001/06/08  16:06:44  pjm
# added ", 'Zebrafish'" to SQL so this species does not go into pathogen lemur
#
# Revision 1.16  2000/08/22  14:55:06  pjm
# in pathogen mode it now ignores Mouse as well as Human.
# In "Human Mode" it shows human & Mouse jobs
#
# Revision 1.15  2000/07/20  08:49:51  pjm
# narrowed a few columns to fit on lower res screens.
#
# Revision 1.14  2000/07/14  13:36:01  pjm
# took out 2 blocks of redunant code: one to "squash" the preps together - this
# was left over code from GetDNApreps and the second was code to draw the
# screen - replaced by redrawScreen
#
# Displays chromo for each clone/job now.
#
# Revision 1.13  2000/03/29  14:53:45  pjm
# added '(+)' to main sql so pathogens that don't have a chromo will still
# work.
#
# Revision 1.12  2000/03/06  17:34:49  pjm
# added line "and    c.SPECIESNAME  = 'Human'" if in non pathogen mode.
#
# Revision 1.11  1999/09/01  10:40:53  pjm
# tried to call goAway() on non-existant CancelJob object. Added check.
#
# Revision 1.10  1999/08/31 12:38:16  pjm
# Added Cancel Job button - new package/object at bottom of file called
# CancelJob. When click on 'show jobs already printed' this will remove the
# Cancel Job window.
#
# Revision 1.9  1999/08/10 16:02:14  pjm
# took out \n from subject.
#
# Revision 1.8  1999/07/27 12:41:46  pjm
# mail was going to pjm and not bug. now goes to bug.
#
# Revision 1.7  1999/07/26 16:52:21  pjm
# optimised column widths. Request num col shrunk, submitter and Assign To
# made wider.
#
#




