# This software has been created by Genome Research Limited (GRL). 
# GRL hereby grants permission to use, copy, modify and distribute 
# this software and its documentation for non-commercial purposes 
# without fee at the user's own risk on the basis set out below.
# GRL neither undertakes nor accepts any duty whether contractual or 
# otherwise in connection with the software, its use or the use of 
# any derivative, and makes no representations or warranties, express
# or implied, concerning the software, its suitability, fitness for
# a particular purpose or non-infringement.
# In no event shall the authors of the software or GRL be responsible 
# or liable for any loss or damage whatsoever arising in any way 
# directly or indirectly out of the use of this software or its 
# derivatives, even if advised of the possibility of such damage.
# Our software can be freely distributed under the conditions set out 
# above, and must contain this copyright notice.

# Author: Jennifer Liddle (js10)
#
# $Id: SIBarcode.pm,v 1.4 2004/12/08 14:35:05 js10 Exp $
#
# $Log: SIBarcode.pm,v $
# Revision 1.4  2004/12/08 14:35:05  js10
# Fixed minor bug relating to 'Override'
#
# Revision 1.3  2004/12/08 10:48:03  js10
# Added a minimal POD
#
# Revision 1.2  2004/12/07 16:16:33  js10
# Just a little tidying
#
# Revision 1.1  2004/11/26 17:19:08  holroyd
# moved files within badger CVS,
#  from libs/*
#  to PSG/lib/*
#
# Revision 1.3  2004/11/04 09:33:21  js10
# Tweaked label type 7 (epigenomics) slightly
#
# Revision 1.2  2004/10/15 08:29:29  holroyd
# Added Storage Area label routine for type 1 labels.
#
# Revision 1.1.1.1  2004/10/06 14:12:41  js10
# Initial import
#
# Revision 1.9  2004/09/08 08:30:30  js10
# Removed the aritrary limit of 11 characters for a project name
#
# Revision 1.8  2004/08/19 14:28:57  js10
# Stop over-writing Currentlabel->{Barcode} to allow reprint to work
#
# Revision 1.7  2004/08/19 14:12:47  js10
# Twiddled the settings to make the type 7 barcodes fit slightly better
#
# Revision 1.6  2004/08/04 10:07:05  js10
# Added findDefaultPrinter() method
#
# Revision 1.5  2004/08/02 11:17:32  js10
# Added 'ViewPrinters' to Barcode3 for backwards compatibility
#
# Revision 1.4  2004/07/27 15:53:06  js10
# Tidied a little
#
# Revision 1.3  2004/07/13 16:25:05  js10
# first attempt at loading plates - not yet tested
#
# Revision 1.2  2004/07/08 13:14:32  js10
# Allow -Override option to getPrinters, and allow no paramaters to get all printers
#
# Revision 1.1.1.1  2004/06/09 10:24:18  js10
# Initial work-in-progress version
#
#

use warnings;
use strict;

package Barcode;
use Carp;
use Checkbarcode2;
use SqlEngine2;
use ViewPrinters;

use vars qw($AUTOLOAD);

my $ESC = chr(27);
my $LF	= chr(10);
my $NULL = chr(0);


{
	my %attrs = ( Printer => '',
	              Type => '',
	              Quantity => 1,
	              Barcode => '',
	              Name => '',
	              Project => '',
	              Owner => '',
	              Suffix => '',
	              User => '',
	              Date => '',
	              FHDL => '',
	              HeaderLabel => 1,
	              FooterLabel => 0,
	              Override => 0,
	              Desc => '',
	              Quiet => 0,
	              Label => [],
	              NoOracle => 0 );

	sub _standardKeys {
		return keys %attrs;
	}

	sub _default {
		my ($self, $a) = @_;
		return $attrs{$a};
	}

	sub _exists {
		my ($self, $a) = @_;
		return defined $attrs{$a};
	}
}

sub dump
{
	my $self = shift;
	foreach my $a ($self->_standardKeys()) {
		print "$a:\t$self->{$a}\n";
	}
}

#
# Create and Initialise a new Barcode object
#
sub new
{
	my ($pkg, %attr) = @_;

	my $setup = bless {}, $pkg;

	foreach my $a ($setup->_standardKeys()) {
		if (defined $attr{-$a}) { $setup->{$a} = $attr{-$a}; }
		else                    { $setup->{$a} = $setup->_default($a); }
	}

	# reformat Quantity
	$setup->{Quantity} = sprintf("%04d", $setup->{Quantity});

	# open the oracle connection, if required
	if (!$setup->{NoOracle}) {
		$setup->{se} = new SqlEngine2();
		$setup->{dbh} = SqlEngine2::getDbh('reports');
	}

	# set a default date
	if (!$setup->{Date}) {
		my ($d, $m, $y) = (localtime)[3,4,5];
		$y = $y + 1900;
		$m = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")[$m];
		$setup->{Date} = uc("$d-$m-$y");
	}

	# set a default user
	if (!$setup->{User}) {
		$setup->{User} = `whoami`;
		chomp $setup->{User};
	}

	return $setup;
}

#
# All of the get() and set() accessor functions (almost) are handled by AUTOLOAD
#
sub AUTOLOAD 
{
	no strict 'refs';
	my ($self, $v) = @_;

	return if $AUTOLOAD =~ /::DESTROY$/;
	if ($AUTOLOAD =~ /.*::([A-Z]\w+)/ && $self->_exists($1)) {
		my $attrname = $1;
		*{$AUTOLOAD} = sub { $_[0]->{$attrname} = $_[1] if $_[1];
		                     return $_[0]->{$attrname};
		                   };
		$self->{$1} = $v if $v;
		return $self->{$1};
	}
	confess "no such method: $AUTOLOAD\n";
}

#
# Quantity is a special case
#
sub Quantity {
    my ($pkg,$q) = @_;
    $q = '0000'.$q;
    $q ? $pkg->{"Quantity"} = substr($q,length($q)-4,4) : return $pkg->{"Quantity"};
}

#
# Provided for backwards compatibility
#
sub Override_labeltype { 
    my ($pkg,$p) = @_;
	$pkg->Override($p);
}

#
# This will insert a blank label
#
sub Break {
	my ($pkg) = @_;
	$pkg->{Barcode}	= 'BREAK';
	$pkg->Labellist();
}

#
# Print a header label
#
sub PrintJobHeaderLabel 
{
	my ($pkg, $type) 	= @_;
	my $FHDL = $pkg->{FHDL};
	my $PrintTime = localtime();

	return if !$pkg->{HeaderLabel};

	$_ = $type;
	SWITCH: {

		$_ == 6  && do { 
			print $FHDL $ESC,"PC001;0100,0035,1,1,G,00,B",$LF,$NULL;
			print $FHDL $ESC,"PC002;0100,0065,1,1,G,00,B",$LF,$NULL;
			print $FHDL $ESC,"C",$LF,$NULL;
			print $FHDL $ESC,"RC001;Printed By $pkg->{\"User\"}",$LF,$NULL;
			print $FHDL $ESC,"RC002;$PrintTime",$LF,$NULL;
			print $FHDL $ESC,"XS;I,0001,0002C5201",$LF,$NULL;
			print $FHDL $ESC,"C",$LF,$NULL;

			last SWITCH; 
		};
      

		$_ == 1  && do { 
			print $FHDL $ESC,"PC001;0020,0035,1,1,G,00,B",$LF,$NULL;
			print $FHDL $ESC,"PC002;0020,0065,1,1,G,00,B",$LF,$NULL;
			print $FHDL $ESC,"C",$LF,$NULL;
			print $FHDL $ESC,"RC001;Printed By $pkg->{\"User\"}",$LF,$NULL;
			print $FHDL $ESC,"RC002;$PrintTime",$LF,$NULL;
			print $FHDL $ESC,"XS;I,0001,0002C5201",$LF,$NULL;
			print $FHDL $ESC,"C",$LF,$NULL;

			last SWITCH; 
		};
      

		$_ == 2  && do { 
			print $FHDL $ESC,"PC001;0112,0020,05,05,H,+02,11,B",$LF,$NULL;
			print $FHDL $ESC,"PC002;0062,0020,05,05,H,+02,11,B",$LF,$NULL;
			print $FHDL $ESC,"C",$LF,$NULL;
			print $FHDL $ESC,"RC001;Printed By $pkg->{\"User\"}",$LF,$NULL;
			print $FHDL $ESC,"RC002;$PrintTime",$LF,$NULL;
			print $FHDL $ESC,"XS;I,0001,0002C5201",$LF,$NULL;
			print $FHDL $ESC,"C",$LF,$NULL;

			last SWITCH;
		};

		$_ == 7  && do { 
			print $FHDL $ESC,"PC001;0010,0040,1,1,G,00,B",$LF,$NULL;
			print $FHDL $ESC,"C",$LF,$NULL;
			print $FHDL $ESC,"RC001;Printed By $pkg->{User} $PrintTime",$LF,$NULL;
			print $FHDL $ESC,"XS;I,0001,0002C5201",$LF,$NULL;
			print $FHDL $ESC,"C",$LF,$NULL;

			last SWITCH; 
		};

		warn "Barcode Module : No Header Label defined For Label Type $type\n";
	} #End Of Switch
}

#
# Print a footer label
#
sub PrintJobFooterLabel 
{
	my ($pkg, $type) = @_;
	my $FHDL = $pkg->{FHDL};
	my $PrintTime = localtime();

	return if !$pkg->{FooterLabel};

	$_ = $type;
	SWITCH: {

		$_ == 1  && do { 
			print $FHDL $ESC,"PC001;0050,0035,1,1,G,00,B",$LF,$NULL;
			print $FHDL $ESC,"PC002;0020,0065,1,1,G,00,B",$LF,$NULL;
			print $FHDL $ESC,"C",$LF,$NULL;
			print $FHDL $ESC,"RC001;* THIS IS THE BOTTOM OF YOUR LABEL LIST *",$LF,$NULL;
			print $FHDL $ESC,"RC002;TAKE CARE WHEN APPLYING LABELS TO 384 PLATES",$LF,$NULL;
			print $FHDL $ESC,"XS;I,0001,0002C5201",$LF,$NULL;
			print $FHDL $ESC,"C",$LF,$NULL;
			
			last SWITCH; 
		};


		$_ == 2  && do { 
			print $FHDL $ESC,"PC001;0112,0020,05,05,H,+02,11,B",$LF,$NULL;
			print $FHDL $ESC,"PC002;0062,0020,05,05,H,+02,11,B",$LF,$NULL;
			print $FHDL $ESC,"C",$LF,$NULL;
			print $FHDL $ESC,"RC001;BOTTOM",$LF,$NULL;
			print $FHDL $ESC,"RC002;$PrintTime",$LF,$NULL;
			print $FHDL $ESC,"XS;I,0001,0002C5201",$LF,$NULL;
			print $FHDL $ESC,"C",$LF,$NULL;
			
			last SWITCH; 
		};

		$_ == 7 && do {
			last SWITCH;
		};
			
		warn "Barcode Module : No Footer Label defined For Label Type $type\n";
	} #End Of Switch

}



sub FormatLabel {
	my ($pkg, $type) = @_;
	my $FHDL = $pkg->{"FHDL"};
	my $DriverRef = {};

	# always print a footer for loading plate labels
	if ($pkg->{Type} =~ /LP/) { $pkg->FooterLabel(1); } 

    $_ = $type;
	SWITCH: {
		#########################################
		# dn1 This is fired off for DP -> TYPE 1
		# Long labels 96 x 8 mm main label type in WP.
		#########################################
		$_ == 1  && do { 
			print $FHDL $ESC,"D0110,0920,0080",$LF,$NULL;
			print $FHDL $ESC,"AY;+08,0",$LF,$NULL;
			print $FHDL $ESC,"AX;+004,+000,+00",$LF,$NULL;
			print $FHDL $ESC,"T20C32",$LF,$NULL;	
			last SWITCH; 
		};

		# wrap around eppendorf tube labels		
		$_ == 2  && do { 
			print $FHDL $ESC,"D0430,0300,0400",$LF,$NULL;
			print $FHDL $ESC,"AY;+08,0",$LF,$NULL;
			print $FHDL $ESC,"AX;+022,+000,+00",$LF,$NULL;
			print $FHDL $ESC,"T20C32",$LF,$NULL;
			last SWITCH; 
		};
			
		# small eppendorf tube labels (Not In Use)
		$_ == 3  && do { 
			print $FHDL $ESC,"D0250,0300,0210",$LF,$NULL;
			print $FHDL $ESC,"AY;+08,0",$LF,$NULL;
			print $FHDL $ESC,"AX;-000,+000,+00",$LF,$NULL;
			print $FHDL $ESC,"T20C32",$LF,$NULL;
			last SWITCH; 
		};
			
		# Front side microtitre plate labels (Robot/Megabace plates)	
		$_ == 5  && do { 
			print $FHDL $ESC,"D0098,0710,0070",$LF,$NULL;
			#print $FHDL $ESC,"AY;+08,0",$LF,$NULL;
			print $FHDL $ESC,"AX;-000,+000,+00",$LF,$NULL;
			print $FHDL $ESC,"T20C32",$LF,$NULL;
			last SWITCH; 
		};		

		#########################################
		# dn1; *New* small labels for eg 384 DPs 
		#########################################
		$_ == 6  && do { 
			print FHDL $ESC,"D0098,0710,0070",$LF,$NULL;
			print FHDL $ESC,"C",$LF,$NULL;
			last SWITCH; 
		};

		# Ultra thin 6mm labels
		#########################################
		$_ == 7  && do { 
			print FHDL $ESC,"D0090,0720,0050",$LF,$NULL;
			print FHDL $ESC,"T20C32",$LF,$NULL;
			print FHDL $ESC,"C",$LF,$NULL;
			last SWITCH; 
		};

	} # end of SWITCH for base label type
	    

	# see If user has asked for a header label saying who this print jobe belongs to.
	$pkg->PrintJobHeaderLabel($type);
	
	# determine label layout using prefix
	$_ = $pkg->{"Type"};
	SWITCH: {
		# Customised Label Formats
		/^LG/  && do { 
			$pkg->LigationLabel();
			last SWITCH; 
		};
			
		/^DS/  && do { 
			$pkg->PetriDishLabels();
			last SWITCH; 
		};	
						
		/^GS/  && do { 
			$pkg->TextOnly_Small();
			last SWITCH; 
		};	
			
		/^ID/  && do { 
			$pkg->IdentityLabels();
			last SWITCH; 
		};

		/^FZ/  && do { 
			$pkg->FreezerLabels();
			last SWITCH; 
		};
	
		/^SA/  && do {
			$pkg->StorageAreaLabels();
			last SWITCH;
		};
		
		/^MS|MR|MW|MA|MP/  && do { 
			$pkg->MicroArrayPlateLabels();
			last SWITCH; 
		};
					
		/^MG/  && do { 
			$pkg->MegaBaceLabels();
			last SWITCH; 
		};		
	
		/^TR/  && do { 
			$pkg->ReAmplificationLabels();
			last SWITCH; 
		};
	

		# Default Label Format For Type 1 labels		
		if ($type == 1) { $pkg->DefaultLabelLayout_1(); }

		# Default Label Format For Type 2 labels
		if ($type == 2) { $pkg->DefaultLabelLayout_2(); }
      
		# Default Label Format For Type 6 labels		
		if ($type == 6) { $pkg->DefaultLabelLayout_6(); }

		# Default Label Format For Type 7 labels
		if ($type == 7) { $pkg->DefaultLabelLayout_7(); }

	} # end of SWITCH for label format

	$pkg->PrintJobFooterLabel($type);	
}

#
# retained for backwards compatibility
#
sub Labellist 
{
	my ($pkg) = @_;

	push @{$pkg->{"Label"}},{	"Barcode" 	=> $pkg->{"Barcode"}, 
                "Type"      => $pkg->{"Type"},
                "Desc"      => $pkg->{"Desc"},
				"Name" 		=> $pkg->{"Name"},
				"Project" 	=> $pkg->{"Project"}, 
				"Suffix"	=> $pkg->{"Suffix"},
				"Owner" 	=> $pkg->{"Owner"}, 
				"Date" 		=> $pkg->{"Date"},
				"HumanReadable"	=> $pkg->{"HumanReadable"}};
}


#
# Find the default printer
#
sub _findDefaultPrinter 
{
    my $pkg = shift;
    my $sql;
    my ($defaultPrinter, $labelType);
	my $sth;

	####################################################################
	# dn1; if $pkg->{"Override"} is defined then use whatever labeltype
	# is specified
	####################################################################
	if ($pkg->{Override}) {
	    
		if ($pkg->{User} =~ /^T(\d{1,3})$/) {
		    # treat owner as a team
			$sth = $pkg->{se}->virtualSqlLib('barcode','printers', 
                                    "select bp.description, bp.active_label
                                     from barcode_printer bp, default_printers dp
                                     where bp.active_label = ? and
			                         bp.iscurrent = 1 and
			                         bp.id_printer = dp.id_printer and
			                         dp.teamname = ? and
			                         rownum = 1");
			($defaultPrinter, $labelType) = $pkg->{se}->getRow($sth, [$pkg->{Override}, $1], $pkg->{dbh});
		} else {
			$sth = $pkg->{se}->virtualSqlLib('barcode','printers', 
			                                 "select bp.description, bp.active_label
			                                  from barcode_printer bp, default_printers dp, team_person tp, person p
			                                  where bp.active_label = ? and
			                                  bp.iscurrent = 1 and
			                                  bp.id_printer = dp.id_printer and
			                                  dp.teamname = tp.teamname and
			                                  tp.id_person = p.id_person and
			                                  p.iscurrent = 1 and
			                                  p.email = ? and
			                                  rownum = 1");
			($defaultPrinter, $labelType) = $pkg->{se}->getRow($sth, [$pkg->{Override}, $pkg->{User}], $pkg->{dbh});
		}

	    ####################
	    # Non override code
	    ####################
	} else {
	    
		if ($pkg->{"User"} =~ /^T(\d{1,3})$/) {
	    # treat owner as a team
			$sth = $pkg->{se}->virtualSqlLib('barcode','printers', 
			                                 "select bp.description, bp.active_label
			                                  from barcode_printer bp, default_printers dp, barcode_prefix bf
			                                  where bf.id_prefix = ? and
			                                  bf.id_label = bp.active_label and
			                                  bp.iscurrent = 1 and 
			                                  bp.id_printer = dp.id_printer and
			                                  dp.teamname = ? and
			                                  rownum = 1");
			($defaultPrinter, $labelType) = $pkg->{se}->getRow($sth, [$pkg->{Type}, $1], $pkg->{dbh});
		} else {
	
			$sth = $pkg->{se}->virtualSqlLib('barcode','printers',
			                                 "select bp.description, bp.active_label
			                                  from barcode_printer bp, default_printers dp, team_person tp, person p, barcode_prefix bf
			                                  where bf.id_prefix = ? and
			                                  bp.iscurrent = 1 and
			                                  bp.id_printer = dp.id_printer and
			                                  dp.teamname = tp.teamname and
			                                  tp.id_person = p.id_person and
			                                  p.iscurrent = 1 and
			                                  p.email = ? and
			                                  rownum = 1");
			($defaultPrinter, $labelType) = $pkg->{se}->getRow($sth, [$pkg->{Type}, $pkg->{User}], $pkg->{dbh});
		}

	}

	return ($defaultPrinter, $labelType);
}

#
# return the default printer for the user
#
sub findDefaultPrinter
{
	my $pkg = shift;
	my ($defaultPrinter, $labelType) = $pkg->_findDefaultPrinter();
	return $defaultPrinter;
}

#
# Check the printer tables in the database to find a printer, or ensure it's valid
#
sub checkPrinterTables
{
	my $pkg = shift;
    my $sql;
    my ($defaultPrinter, $labelType);
	my $sth;

	####################################################################
	# dn1; if $pkg->{"Override"} is defined then use whatever labeltype
	# is specified
	####################################################################
	if ($pkg->{Override}) {
	    ################################################################################
	    # If the programmer has *not* specified a printer -> find the teams default one
	    ################################################################################
	    if (!$pkg->{Printer}) {
			($defaultPrinter, $labelType) = $pkg->_findDefaultPrinter();
	    } else {
			##############################################
			# If the programmer *has* specified a printer
			##############################################
			$sth = $pkg->{se}->virtualSqlLib('barcode','printers', 
			                                 "select bp.description, bp.active_label
			                                  from barcode_printer bp, default_printers dp
			                                  where bp.active_label = ? and
			                                  bp.iscurrent = 1 and
			                                  bp.description = ? and
			                                  rownum = 1");
			($defaultPrinter, $labelType) = $pkg->{se}->getRow($sth, [$pkg->{Override}, $pkg->{Printer}], $pkg->{dbh});
	    }


	    ####################
	    # Non override code
	    ####################
	} else {
	    ################################################################################
	    # If the programmer has *not* specified a printer -> find the teams default one
	    ################################################################################
	    if (!$pkg->{Printer}) {
			($defaultPrinter, $labelType) = $pkg->_findDefaultPrinter();
		##############################################
		# If the programmer *has* specified a printer
		##############################################
	    } else {
			$sth = $pkg->{se}->virtualSqlLib('barcode','printers',
			                                 "select bp.description, bp.active_label
			                                  from barcode_printer bp, default_printers dp, barcode_prefix bf
			                                  where bf.id_prefix = ? and
			                                  bf.id_label = bp.active_label and
			                                  bp.iscurrent = 1 and
			                                  bp.description = ? and
			                                  rownum = 1");
			($defaultPrinter, $labelType) = $pkg->{se}->getRow($sth, [$pkg->{Type}, $pkg->{Printer}], $pkg->{dbh});
	    }
	}
	return ($defaultPrinter, $labelType);
}


#
# Check that the chosen printer is valid, and open it
#
sub Checkprinter 
{
    my $pkg = shift;
    my ($defaultPrinter, $labelType);

	if ($pkg->{NoOracle}) {
		$defaultPrinter = $pkg->{Printer};
		$labelType = $pkg->{Override};
	} else {
		($defaultPrinter, $labelType) = $pkg->checkPrinterTables();
	}

	if ( (!$defaultPrinter) && (!$pkg->{"Printer"}) ){
	    warn "Cannot Determine Which Barcode Printer to Use With $pkg->{Type}\n";
	    die "Cannot Determine Which Barcode Printer to Use With $pkg->{Type}\n";
	}
	if ( (!$defaultPrinter) && ($pkg->{"Printer"}) ){
	    warn "Invalid Printer\nYou Cannot Print $pkg->{Type} On $pkg->{Printer}\n";
	    die "Invalid Printer\nYou Cannot Print $pkg->{Type} On $pkg->{Printer}\n";
	}
	
	##########################
	# Set the default printer
	##########################
	$pkg->{Printer} = $defaultPrinter;
	
    # Check printer online status
    my $PrinterStatus = `lpq -P$pkg->{Printer}`;
    

    if ( (length($PrinterStatus) < 1) || ($PrinterStatus !~ /Printer OK/)) {
		## Erase the contents of the barcode object
		if ($pkg->{Label}) { undef $pkg->{Label}; }
		die "ERROR : Label Printer, $pkg->{Printer}, Unavailable\n\nPlease select another printer\n\n$PrinterStatus";
    }

    if (open FHDL, "| lpr -l -P$pkg->{Printer}") {
#	if (open FHDL, ">label01.txt") {
		$pkg->{FHDL} = *FHDL;
		return $labelType;
    } else {
		## Erase the contents of the barcode object
		if ($pkg->{Label}) { undef $pkg->{Label}; }
		die "Cannot open pipe to Label printer $pkg->{Printer}";	
    }
    
}






##################################################################
# Main Printing Module
##################################################################

sub Printlabel 
{
	my $pkg = shift;
	my $ref;
	my $parameters;


	# has type been set ?
	if (!$pkg->{Type}) {
		if ($pkg->{Label}) { undef $pkg->{Label}; } 
		die "ERROR : Prefix Not defined, Cannot generate Labels"; 
	}
	if (!$pkg->{User}) {
		if ($pkg->{Label}) { undef $pkg->{Label}; } 
		die "ERROR : Label owner not defined, Cannot generate Labels"; 
	}

	my $PrinterLabel = $pkg->Checkprinter();

	# Cludge For when Oracle is Down
	if (!$PrinterLabel) { 
		warn "Can't find printer label...\n";
		$PrinterLabel = 1;
		if ($pkg->{Type} =~ /DR|LG|GS/) { $PrinterLabel = 2; }
		if ($pkg->{Type} =~ /MG/) { $PrinterLabel = 5; }
	}

	$pkg->FormatLabel($PrinterLabel);	# do the actual printing

	if (!$pkg->{Quiet}) {
		my $time = localtime();
		warn "==========================================\n";
		warn "Label Printing Report\n";
		warn "User 		: $pkg->{\"User\"}\n";
		warn "Printer		: $pkg->{\"Printer\"}\n";
		warn "Label Type 	: $pkg->{\"Type\"}\n";
		warn "Format Type	: $PrinterLabel\n";
		warn "Time 		: $time\n";
		warn "==========================================\n";
	}

	#undef $pkg->{"Label"};		# js10 19 Aug 04 Removed to allow confirmPrint() to work
	close $pkg->{"FHDL"};
}


############## ############## ############## ############## ############## ############## 
############## ############## ############## ############## ############## ##############

##############################################################
# dn1; A new subroutine (copied from pt_barcode) to cope with
# 384 well DP labels
##############################################################
sub DefaultLabelLayout_6 
{
	my $pkg = shift;
    my $FHDL = $pkg->{FHDL};
    my $pad = '                ';
    my $i;
	my $HumanReadable;

##############################################################
# Set Up label postions and fonts
# Date
    print $FHDL $ESC,"PC001;0040,0025,05,1,G,+03,00,B",$LF,$NULL;
# Human Readable
    print $FHDL $ESC,"PC002;0040,0060,05,1,G,+03,00,B",$LF,$NULL;
# Name
    print $FHDL $ESC,"PC003;0510,0025,05,1,G,+00,00,B",$LF,$NULL;	# js10 19 Apr 04 made smaller
# Project
    print $FHDL $ESC,"PC004;0510,0060,05,1,G,+00,00,B",$LF,$NULL;	# js10 19 Apr 04 made smaller
# EAN 13 medium res barcode
# original
    print $FHDL $ESC,"XB01;0230,0000,5,3,02,0,0070,+0000000000,002,0,00",$LF,$NULL;
##############################################################
    
    foreach my $CurrentLabel (@{$pkg->{"Label"}}){
	# Clear label layout form printers memory
	print $FHDL $ESC,"C",$LF,$NULL;
	
	# Used ased for a blank label to be printed in middle of the job
	if($CurrentLabel->{"Barcode"} eq 'BREAK'){print $FHDL $ESC,"T20C32",$LF,$NULL; next;}
	
	($CurrentLabel->{"Barcode"}, $HumanReadable) = Calculatebarcode($pkg->{"Type"},$CurrentLabel->{"Barcode"});
print "Calculatebarcode($pkg->{Type},$CurrentLabel->{Barcode}) = ($CurrentLabel->{Barcode},$HumanReadable)\n";
	if($CurrentLabel->{"Barcode"} == -1){warn "Invalid Number Type In Sanger Barcode Calculation\n"; next;}
	
	# Restrict Amount Of Info that can be printed in any label field
#	js10 19 Apr 04  removed
#	$CurrentLabel->{"Name"} 	= substr($CurrentLabel->{"Name"},0,28);
	$CurrentLabel->{"Name"} 	=~ s/_/-/g;
	
	$CurrentLabel->{"Project"} 	= "$CurrentLabel->{\"Project\"}";
	
	# Date
	print $FHDL $ESC,"RC001;$pkg->{\"Date\"}",$LF,$NULL;
	
	# Human readable
	if ( (length $HumanReadable) > 11){ 
	    die "Cannot print human readable text (> 11-chars) Contact bug !\n";
	}
	
	print $FHDL $ESC,"RC002;$HumanReadable",$LF,$NULL;
	
	# Program name (could be used for something else)
#	js10 19 Apr 04 removed
#	$CurrentLabel->{"Name"} = substr($CurrentLabel->{"Name"}, 0, 11);
	print $FHDL $ESC,"RC003;$CurrentLabel->{\"Name\"}",$LF,$NULL;
	
	# Projectname (all 4 96 well plates should come from the same project
	$CurrentLabel->{"Project"} = substr($CurrentLabel->{"Project"}, 0, 11);
	print $FHDL $ESC,"RC004;$CurrentLabel->{\"Project\"}",$LF,$NULL;
	
	# The barcode itself
	print $FHDL $ESC,"RB01;$CurrentLabel->{\"Barcode\"}",$LF,$NULL;
	print $FHDL $ESC,"XS;I,$pkg->{\"Quantity\"},0002C3201",$LF,$NULL;
    }
} 
############## ############## ############## ############## ############## ############## 
############## ############## ############## ############## ############## ##############

sub DefaultLabelLayout_7 
{
    my $pkg = shift;
    my $FHDL = $pkg->{FHDL};
    my $pad = '                ';
    my $i;

	# Set Up label postions and fonts
	# Date
    print $FHDL $ESC,"PC001;0020,0025,05,1,G,+00,00,B",$LF,$NULL;
	# Human Readable
    print $FHDL $ESC,"PC002;0020,0050,05,1,G,+00,00,B",$LF,$NULL;
	# Name
    print $FHDL $ESC,"PC003;0480,0025,05,1,G,+00,00,B",$LF,$NULL;
	# Project
    print $FHDL $ESC,"PC004;0480,0050,05,1,G,+00,00,B",$LF,$NULL;
	# EAN 13 medium res barcode
    print $FHDL $ESC,"XB01;0200,0010,5,3,02,0,0045,+0000000000,002,0,00",$LF,$NULL;
    
    foreach my $CurrentLabel (@{$pkg->{"Label"}}) {
		# Clear label layout form printers memory
		print $FHDL $ESC,"C",$LF,$NULL;
	
		# Used ased for a blank label to be printed in middle of the job
		if($CurrentLabel->{"Barcode"} eq 'BREAK'){print $FHDL $ESC,"T20C32",$LF,$NULL; next;}
	
		my ($Barcode, $HumanReadable) = Calculatebarcode($CurrentLabel->{"Type"},$CurrentLabel->{"Barcode"});
		if ($Barcode == -1){warn "Invalid Number Type In Sanger Barcode Calculation\n"; next;}
	
		$CurrentLabel->{"Name"} 	=~ s/_/-/g;
		$CurrentLabel->{"Project"} 	= "$CurrentLabel->{\"Project\"}";
	
		print $FHDL $ESC,"RC001;$pkg->{\"Date\"}",$LF,$NULL;
		print $FHDL $ESC,"RC002;$HumanReadable $CurrentLabel->{\"Desc\"}",$LF,$NULL;
		print $FHDL $ESC,"RC003;$CurrentLabel->{\"Name\"}",$LF,$NULL;
	
		# Projectname (all 4 96 well plates should come from the same project
#		$CurrentLabel->{"Project"} = substr($CurrentLabel->{"Project"}, 0, 11);
		print $FHDL $ESC,"RC004;$CurrentLabel->{\"Project\"}",$LF,$NULL;
	
		# The barcode itself
		print $FHDL $ESC,"RB01;$Barcode",$LF,$NULL;
		print $FHDL $ESC,"XS;I,$pkg->{\"Quantity\"},0002C3201",$LF,$NULL;
    }
}


##################################################################
# This is the default label layout for type 1 labels
##################################################################

######################################
# dn1; This is used at the 'mo for DP
######################################
sub DefaultLabelLayout_1 
{
	my $pkg = shift;
	my $FHDL = $pkg->{"FHDL"};
	my $pad = '                ';
	my $i;
	my $lcounter = '0001';
	my $HumanReadable;

##############################################################
# Set Up label postions and fonts
# Date
print $FHDL $ESC,"PC001;0040,0035,1,1,G,00,B",$LF,$NULL;
# Human readable Form
print $FHDL $ESC,"PC002;0040,0065,1,1,G,00,B",$LF,$NULL;
# Name
print $FHDL $ESC,"PC003;0505,0035,1,1,G,00,B",$LF,$NULL;
# Project
print $FHDL $ESC,"PC004;0505,0065,1,1,G,00,B",$LF,$NULL;
# Suffix
print $FHDL $ESC,"PC005;0750,0035,1,1,G,00,B",$LF,$NULL;
# Owner
print $FHDL $ESC,"PC006;0750,0065,1,1,G,00,B",$LF,$NULL;

# Name 		Reduced Size
print $FHDL $ESC,"PC007;0505,0035,05,1,G,+03,00,B",$LF,$NULL;
# Project 	Reduced Size
print $FHDL $ESC,"PC008;0505,0065,05,1,G,+03,00,B",$LF,$NULL;
# Suffix 	Reduced Size
print $FHDL $ESC,"PC009;0750,0035,05,1,G,+03,00,B",$LF,$NULL;
# Owner		Reduced Size
print $FHDL $ESC,"PC010;0750,0065,05,1,G,+03,00,B",$LF,$NULL;
# Human readable Form Reduced Size
print $FHDL $ESC,"PC012;0040,0065,05,1,G,00,B",$LF,$NULL;



# Labelcounter		Reduced Size
print $FHDL $ESC,"PC011;0910,0065,05,1,G,+03,33,W",$LF,$NULL;

# 384 sidelabel
print $FHDL $ESC,"PC013;0008,0020,05,1,G,+03,11,W",$LF,$NULL;

# EAN 13 medium res barcode
print $FHDL $ESC,"XB01;0250,0000,5,3,02,0,0070,+0000000000,002,0,00",$LF,$NULL;
##############################################################


foreach my $CurrentLabel (@{$pkg->{"Label"}})
{
	my $HumanReadable;

	# Clear label layout form printers memory
	print $FHDL $ESC,"C",$LF,$NULL;
	
	# Used ased for a blank label to be printed in middle of the job
	if($CurrentLabel->{"Barcode"} eq 'BREAK'){print $FHDL $ESC,"T20C32",$LF,$NULL; next;}
	
	($CurrentLabel->{"Barcode"}, $HumanReadable) = Calculatebarcode($pkg->{"Type"},$CurrentLabel->{"Barcode"});
	if($CurrentLabel->{"Barcode"} == -1){warn "Invalid Number Type In Sanger Barcode Calculation\n"; next;}
	
	# Has Humanreadable been Overwritten by nasty nibletts 384 well stuff.......
	my $SideLabel;
	if($CurrentLabel->{"HumanReadable"})
	{
		$SideLabel = $HumanReadable;
		$SideLabel =~ s/[0-9]+/ /;
		
		print $FHDL $ESC,"RC013;$SideLabel",$LF,$NULL;
		$HumanReadable = $CurrentLabel->{"HumanReadable"};
	}
	
	# Restrict Amount Of Info that can be printed in any label field
	$HumanReadable = $HumanReadable.$pad;
	#$HumanReadable 			= substr($HumanReadable			,0,18);
	$CurrentLabel->{"Name"} 	= substr($CurrentLabel->{"Name"}	,0,18);
	$CurrentLabel->{"Project"}	= substr($CurrentLabel->{"Project"}	,0,18);
	$CurrentLabel->{"Suffix"}	= substr($CurrentLabel->{"Suffix"}	,0,14);
	$CurrentLabel->{"Owner"}	= substr($CurrentLabel->{"Owner"}	,0,14);
	
	$CurrentLabel->{"Name"} 	=~ s/_/-/g; 
	$CurrentLabel->{"Project"} 	=~ s/_/-/g;
	
	
	print $FHDL $ESC,"RC001;$pkg->{\"Date\"}",$LF,$NULL;
	
	$i = '02';
	$HumanReadable =~ s/\s *$//g;
	if(length($HumanReadable) > 9){$i = 12;}
	print $FHDL $ESC,"RC0$i;$HumanReadable",$LF,$NULL;
	
	$i = 3; 
	if(length($CurrentLabel->{"Name"}) > 9){$i = 7;}
	print $FHDL $ESC,"RC00$i;$CurrentLabel->{\"Name\"}",$LF,$NULL;
	
	$i = 4; 
	if(length($CurrentLabel->{"Project"}) > 9){$i = 8;}
	print $FHDL $ESC,"RC00$i;$CurrentLabel->{\"Project\"}",$LF,$NULL;
	
	$i = 5; 
	if(length($CurrentLabel->{"Suffix"}) > 7){$i = 9;}
	print $FHDL $ESC,"RC00$i;$CurrentLabel->{\"Suffix\"}",$LF,$NULL;
	
	$i = '06'; 
	if(length($CurrentLabel->{"Owner"}) > 7){$i = 10;}
	print $FHDL $ESC,"RC0$i;$CurrentLabel->{\"Owner\"}",$LF,$NULL;
	
	
	print $FHDL $ESC,"RC011;$lcounter",$LF,$NULL;
	
	print $FHDL $ESC,"RB01;$CurrentLabel->{\"Barcode\"}",$LF,$NULL;
	
	
	
	print $FHDL $ESC,"XS;I,$pkg->{\"Quantity\"},0002C3201",$LF,$NULL;
	$lcounter++;
	
}

}
##################################################################
# This is the freezer label layout for type 1 labels
##################################################################
sub FreezerLabels 
{
	my $pkg = shift;
	my $FHDL = $pkg->{"FHDL"};
	my $pad = '                ';
	my $i;
	my $HumanReadable;

##############################################################
# Set Up label postions and fonts

# Name
print $FHDL $ESC,"PC003;0330,0055,1,1,H,00,B",$LF,$NULL;


# EAN 13 medium res barcode
print $FHDL $ESC,"XB01;0050,0000,5,3,02,0,0070,+0000000000,002,0,00",$LF,$NULL;
##############################################################


foreach my $CurrentLabel (@{$pkg->{"Label"}})
{
	# Clear label layout form printers memory
	print $FHDL $ESC,"C",$LF,$NULL;
	
	# Used ased for a blank label to be printed in middle of the job
	if($CurrentLabel->{"Barcode"} eq 'BREAK'){print $FHDL $ESC,"T20C32",$LF,$NULL; next;}
	
	($CurrentLabel->{"Barcode"}, $HumanReadable) = Calculatebarcode($pkg->{"Type"},$CurrentLabel->{"Barcode"});
print "Calculatebarcode($pkg->{Type},$CurrentLabel->{Barcode}) = ($CurrentLabel->{Barcode},$HumanReadable)\n";
	if($CurrentLabel->{"Barcode"} == -1){warn "Invalid Number Type In Sanger Barcode Calculation\n"; next;}
	
	# Restrict Amount Of Info that can be printed in any label field
	
	$CurrentLabel->{"Name"} 	= substr($CurrentLabel->{"Name"}	,0,22);
	
	$CurrentLabel->{"Name"} 	=~ s/_/-/g;
	
	print $FHDL $ESC,"RC003;$CurrentLabel->{\"Name\"}",$LF,$NULL;
	print $FHDL $ESC,"RB01;$CurrentLabel->{\"Barcode\"}",$LF,$NULL;
	print $FHDL $ESC,"XS;I,$pkg->{\"Quantity\"},0002C3201",$LF,$NULL;
	
}

}

##################################################################
# This is the storage area label layout for type 1 labels
##################################################################
sub StorageAreaLabels 
{
	my $pkg = shift;
	my $FHDL = $pkg->{FHDL};
	my $pad = '                ';
	my $i;
    my $HumanReadable;

    ##############################################################
    # Set Up label postions and fonts

    # Name aka the storage area name.
    print $FHDL $ESC,"PC003;0330,0040,05,1,P,+00,00,B",$LF,$NULL;
    # Project aka the storage device name.
    print $FHDL $ESC,"PC004;0330,0070,05,1,G,+00,00,B",$LF,$NULL;
    # EAN 13 medium res barcode
    print $FHDL $ESC,"XB01;0050,0000,5,3,02,0,0070,+0000000000,002,0,00",$LF,$NULL;

    ##############################################################


    foreach my $CurrentLabel (@{$pkg->{"Label"}})
    {
	# Clear label layout from printers memory
	print $FHDL $ESC,"C",$LF,$NULL;
	
	# Used asked for a blank label to be printed in middle of the job
	if($CurrentLabel->{"Barcode"} eq 'BREAK'){print $FHDL $ESC,"T20C32",$LF,$NULL; next;}
	
	($CurrentLabel->{"Barcode"}, $HumanReadable) = Calculatebarcode($pkg->{"Type"},$CurrentLabel->{"Barcode"});
	print "Calculatebarcode($pkg->{Type},$CurrentLabel->{Barcode}) = ($CurrentLabel->{Barcode},$HumanReadable)\n";
    	if($CurrentLabel->{"Barcode"} == -1){warn "Invalid Number Type In Sanger Barcode Calculation\n"; next;}
	
	## Format the label Name field.
	$CurrentLabel->{"Name"}     = substr($CurrentLabel->{"Name"},0,35);
	$CurrentLabel->{"Name"}     =~ s/_/-/g;
	
	## Format the label Project (aka Storage Device) field.
	$CurrentLabel->{"Project"}  = substr($CurrentLabel->{"Project"},0,40);
	$CurrentLabel->{"Project"}  = "(" . $CurrentLabel->{"Project"} . ")";
	
	## Send the data to the barcode printer.
	print $FHDL $ESC,"RC003;$CurrentLabel->{\"Name\"}",$LF,$NULL;
	print $FHDL $ESC,"RC004;$CurrentLabel->{\"Project\"}",$LF,$NULL;
	print $FHDL $ESC,"RB01;$CurrentLabel->{\"Barcode\"}",$LF,$NULL;
	print $FHDL $ESC,"XS;I,$pkg->{\"Quantity\"},0002C3201",$LF,$NULL;
    }
    
}


##################################################################
# This is the freezer label layout for type 1 labels
##################################################################
sub ReAmplificationLabels 
{
	my $pkg = shift;
	my $FHDL = $pkg->{FHDL};
	my $pad = '                ';
	my $i;
	my $HumanReadable;

##############################################################
# Set Up label postions and fonts

# Name
print $FHDL $ESC,"PC003;0600,0030,05,05,H,+01,00,B",$LF,$NULL;

# Project
print $FHDL $ESC,"PC002;0600,0065,1,1,G,+03,00,B",$LF,$NULL;

# EAN 13 medium res barcode
print $FHDL $ESC,"XB01;0100,0000,5,3,02,0,0070,+0000000000,002,0,00",$LF,$NULL;
##############################################################


foreach my $CurrentLabel (@{$pkg->{"Label"}})
{
	# Clear label layout form printers memory
	print $FHDL $ESC,"C",$LF,$NULL;
	
	# Used ased for a blank label to be printed in middle of the job
	if($CurrentLabel->{"Barcode"} eq 'BREAK'){print $FHDL $ESC,"T20C32",$LF,$NULL; next;}
	
	($CurrentLabel->{"Barcode"}, $HumanReadable) = Calculatebarcode($pkg->{"Type"},$CurrentLabel->{"Barcode"});
print "Calculatebarcode($pkg->{Type},$CurrentLabel->{Barcode}) = ($CurrentLabel->{Barcode},$HumanReadable)\n";
	if($CurrentLabel->{"Barcode"} == -1){warn "Invalid Number Type In Sanger Barcode Calculation\n"; next;}
	
	# Restrict Amount Of Info that can be printed in any label field
	
	$CurrentLabel->{"Name"} 	= substr($CurrentLabel->{"Name"}	,0,20);
	
	
	
	$CurrentLabel->{"Name"} 	=~ s/_/-/g;
	
	print $FHDL $ESC,"RC002;$HumanReadable",$LF,$NULL;
	
	print $FHDL $ESC,"RC003;$CurrentLabel->{\"Name\"}",$LF,$NULL;
	print $FHDL $ESC,"RB01;$CurrentLabel->{\"Barcode\"}",$LF,$NULL;
	print $FHDL $ESC,"XS;I,$pkg->{\"Quantity\"},0002C3201",$LF,$NULL;
	
}

}
##################################################################
# This is the label layout for type front side labels used 
# for DP concentration plates destined for megabace machines
##################################################################
sub MegaBaceLabels 
{
	my $pkg = shift;
	my $FHDL = $pkg->{FHDL};
	my $pad = '                ';
	my $i;

##############################################################
# Set Up label postions and fonts

# Name
print $FHDL $ESC,"PC001;0430,0050,05,1,H,00,B",$LF,$NULL;

# Have to use code 128 due to limitations on the barcode s
# CODE 128
print $FHDL $ESC,"XB01;0070,0000,9,1,02,0,0080",$LF,$NULL;

##############################################################


foreach my $CurrentLabel (@{$pkg->{"Label"}})
{
	# Clear label layout form printers memory
	print $FHDL $ESC,"C",$LF,$NULL;

	# Used ased for a blank label to be printed in middle of the job
	if($CurrentLabel->{"Barcode"} eq 'BREAK'){print $FHDL $ESC,"T20C32",$LF,$NULL; next;}

	$CurrentLabel->{"Name"} 	= substr($CurrentLabel->{"Name"}	,0,22);
	$CurrentLabel->{"Name"} 	=~ s/_/-/g;

	print $FHDL $ESC,"RC001;$CurrentLabel->{\"Name\"}",$LF,$NULL;
	print $FHDL $ESC,"RB01;$CurrentLabel->{\"Barcode\"}",$LF,$NULL;
	print $FHDL $ESC,"XS;I,$pkg->{\"Quantity\"},0002C3201",$LF,$NULL;
}
}

##################################################################
# This is the default label layout for type 2 labels
##################################################################
sub DefaultLabelLayout_2 
{
	my $pkg = shift;
	my $FHDL = $pkg->{FHDL};
	my $pad = '                                ';
	my $i;

# Set Up label postions and fonts
#DATE
print $FHDL $ESC,"PC001;0038,0210,05,05,H,+03,11,B",$LF,$NULL;

#Project
print $FHDL $ESC,"PC002;0120,0210,05,05,H,+02,11,B",$LF,$NULL;
print $FHDL $ESC,"PC003;0070,0210,05,05,H,+02,11,B",$LF,$NULL;


#Name (On round Label)
print $FHDL $ESC,"PC005;0240,0165,05,1,G,+00,00,B",$LF,$NULL;
print $FHDL $ESC,"PC006;0220,0193,05,1,G,+00,00,B",$LF,$NULL;

#Suffix (On round label)
print $FHDL $ESC,"PC007;0225,0217,05,1,G,+01,00,B",$LF,$NULL;

print $FHDL $ESC,"PC008;0150,0210,05,1,G,+01,11,B",$LF,$NULL;

#EAN 13 medium res
print $FHDL $ESC,"XB01;0043,0100,5,3,01,0,0100,+0000000000,002,0,00",$LF,$NULL;

foreach my $CurrentLabel (@{$pkg->{Label}})
{
	my $HumanReadable;

	# Clear label layout form printers memory
	print $FHDL $ESC,"C",$LF,$NULL;
	
	# Used ased for a blank label to be printed in middle of the job
	if($CurrentLabel->{"Barcode"} eq 'BREAK'){print $FHDL $ESC,"T20C32",$LF,$NULL; next;}
	
	($CurrentLabel->{"Barcode"}, $HumanReadable) = Calculatebarcode($pkg->{"Type"},$CurrentLabel->{"Barcode"});
print "Calculatebarcode($pkg->{Type},$CurrentLabel->{Barcode}) = ($CurrentLabel->{Barcode},$HumanReadable)\n";
	if($CurrentLabel->{"Barcode"} == -1){warn "Invalid Number Type In Sanger Barcode Calculation\n"; next;}
	# Remove a digit from EAN 13 to convert to 128.
	#$CurrentLabel->{"Barcode"} = substr($CurrentLabel->{"Barcode"},0,3).substr($CurrentLabel->{"Barcode"},4);
	
	# Restrict Amount Of Info that can be printed in any label field
	$HumanReadable = $HumanReadable.$pad;
	
	$CurrentLabel->{"Name"} 	= $CurrentLabel->{"Name"}.$pad;
	$CurrentLabel->{"Project"} 	= $CurrentLabel->{"Project"}.$pad;
	$CurrentLabel->{"Suffix"}	= $CurrentLabel->{"Suffix"}.$pad;
	$CurrentLabel->{"Owner"}	= $CurrentLabel->{"Owner"}.$pad;
	
	$CurrentLabel->{"Name"} 	=~ s/_/-/g; 
	$CurrentLabel->{"Project"} 	=~ s/_/-/g;
	
	$HumanReadable 			= substr($HumanReadable			,0,11);
	$CurrentLabel->{"Suffix"}	= substr($CurrentLabel->{"Suffix"}	,0,8);
	$CurrentLabel->{"Owner"}	= substr($CurrentLabel->{"Owner"}	,0,12);
	
	# Printing underscopes on TEC printers is ugly, change any to dashes.
	$CurrentLabel->{"Name"} 	=~ s/_/-/g; 
	$CurrentLabel->{"Project"} 	=~ s/_/-/g;
	
	my ($ProjectLine1,$ProjectLine2) = split /-/,$CurrentLabel->{"Project"};
	$ProjectLine1 = substr($ProjectLine1,0,11);
	
	if($ProjectLine2)
	{
		$ProjectLine2 = '-'.substr($ProjectLine2,0,11)
	}
	else
	{
		$ProjectLine2 = substr($ProjectLine1,10,11);
	}
	
	my $NameLine1 = substr($CurrentLabel->{"Name"},0,2);
	my $NameLine2 = substr($CurrentLabel->{"Name"},2,10);

	print $FHDL $ESC,"RC001;$pkg->{\"Date\"}",$LF,$NULL;
	print $FHDL $ESC,"RC002;$ProjectLine1",$LF,$NULL;
	print $FHDL $ESC,"RC003;$ProjectLine2",$LF,$NULL;

	print $FHDL $ESC,"RC005;$NameLine1",$LF,$NULL;
	print $FHDL $ESC,"RC006;$NameLine2",$LF,$NULL;

	print $FHDL $ESC,"RC007;$CurrentLabel->{\"Suffix\"}",$LF,$NULL;

	print $FHDL $ESC,"RC008;$CurrentLabel->{\"Owner\"}",$LF,$NULL;
	
	print $FHDL $ESC,"RB01;$CurrentLabel->{\"Barcode\"}",$LF,$NULL;
	
	print $FHDL $ESC,"XS;I,$pkg->{\"Quantity\"},0002C3201",$LF,$NULL;
}


}

sub MicroArrayPlateLabels 
{
	my $pkg = shift;
	my $FHDL = $pkg->{FHDL};
	my $pad = '                ';
	my $i;
	my $HumanReadable;

##############################################################
# Set Up label postions and fonts
# Date
print $FHDL $ESC,"PC001;0400,0035,05,1,G,+03,00,B",$LF,$NULL;
# Human Readable
print $FHDL $ESC,"PC002;0600,0030,1,1,G,+03,00,W",$LF,$NULL;

# Name
print $FHDL $ESC,"PC003;0400,0065,1,1,G,+03,00,B",$LF,$NULL;

# EAN 13 medium res barcode
print $FHDL $ESC,"XB01;0130,0000,5,3,02,0,0070,+0000000000,002,0,00",$LF,$NULL;
##############################################################


foreach my $CurrentLabel (@{$pkg->{"Label"}})
{
	# Clear label layout form printers memory
	print $FHDL $ESC,"C",$LF,$NULL;
	
	# Used ased for a blank label to be printed in middle of the job
	if($CurrentLabel->{"Barcode"} eq 'BREAK'){print $FHDL $ESC,"T20C32",$LF,$NULL; next;}
	
	($CurrentLabel->{"Barcode"}, $HumanReadable) = Calculatebarcode($pkg->{"Type"},$CurrentLabel->{"Barcode"});
print "Calculatebarcode($pkg->{Type},$CurrentLabel->{Barcode}) = ($CurrentLabel->{Barcode},$HumanReadable)\n";
	if($CurrentLabel->{"Barcode"} == -1){warn "Invalid Number Type In Sanger Barcode Calculation\n"; next;}
	
	# Restrict Amount Of Info that can be printed in any label field
	$CurrentLabel->{"Name"} 	= substr($CurrentLabel->{"Name"},0,30);
	
	$CurrentLabel->{"Name"} 	=~ s/_/-/g;
	
	
	print $FHDL $ESC,"RC001;$pkg->{\"Date\"}",$LF,$NULL;
	print $FHDL $ESC,"RC002;$HumanReadable",$LF,$NULL;
	
	
	print $FHDL $ESC,"RC003;$CurrentLabel->{\"Name\"}",$LF,$NULL;
	print $FHDL $ESC,"RB01;$CurrentLabel->{\"Barcode\"}",$LF,$NULL;
	print $FHDL $ESC,"XS;I,$pkg->{\"Quantity\"},0002C3201",$LF,$NULL;
	
}

}

# Customised Label Formats
sub LigationLabel 
{
	my $pkg = shift;
	my $FHDL = $pkg->{FHDL};
	my $pad = '                                ';

#DATE
print $FHDL $ESC,"PC001;0030,0210,05,05,H,+03,11,B",$LF,$NULL;

#Project
print $FHDL $ESC,"PC002;0103,0210,05,05,H,+02,11,B",$LF,$NULL;
print $FHDL $ESC,"PC003;0053,0210,05,05,H,+02,11,B",$LF,$NULL;


#Name (On round Label)
print $FHDL $ESC,"PC005;0215,0184,05,1,G,+00,00,B",$LF,$NULL;
print $FHDL $ESC,"PC006;0210,0207,05,1,G,+00,00,B",$LF,$NULL;

#Suffix (On round label)
print $FHDL $ESC,"PC007;0218,0230,05,1,G,+01,00,B",$LF,$NULL;


print $FHDL $ESC,"PC008;0132,0210,05,1,G,+01,11,B",$LF,$NULL;

#EAN 13 medium res
print $FHDL $ESC,"XB01;0023,0100,5,3,01,0,0100,+0000000000,002,0,00",$LF,$NULL;

foreach my $CurrentLabel (@{$pkg->{Label}})
{
	my $HumanReadable;

	# Clear label layout form printers memory
	print $FHDL $ESC,"C",$LF,$NULL;
	
	# Used ased for a blank label to be printed in middle of the job
	if($CurrentLabel->{"Barcode"} eq 'BREAK'){print $FHDL $ESC,"T20C32",$LF,$NULL; next;}
	
	($CurrentLabel->{"Barcode"}, $HumanReadable) = Calculatebarcode($pkg->{"Type"},$CurrentLabel->{"Barcode"});
print "Calculatebarcode($pkg->{Type},$CurrentLabel->{Barcode}) = ($CurrentLabel->{Barcode},$HumanReadable)\n";
	if($CurrentLabel->{"Barcode"} == -1){warn "Invalid Number Type In Sanger Barcode Calculation\n"; next;}
	
	# Remove a digit from EAN 13 to convert to 128.
	# $CurrentLabel->{"Barcode"} = substr($CurrentLabel->{"Barcode"},0,3).substr($CurrentLabel->{"Barcode"},4);
	
	
	# Restrict Amount Of Info that can be printed in any label field
	$HumanReadable = $HumanReadable.$pad;
	
	$CurrentLabel->{"Name"} 	= $CurrentLabel->{"Name"}.$pad;
	$CurrentLabel->{"Project"} 	= $CurrentLabel->{"Project"}.$pad;
	$CurrentLabel->{"Suffix"}	= $CurrentLabel->{"Suffix"}.$pad;
	$CurrentLabel->{"Owner"}	= $CurrentLabel->{"Owner"}.$pad;
	
	$CurrentLabel->{"Name"} 	=~ s/_/-/g; 
	$CurrentLabel->{"Project"} 	=~ s/_/-/g;
	
	$HumanReadable 			= substr($HumanReadable			,0,11);
	$CurrentLabel->{"Suffix"}	= substr($CurrentLabel->{"Suffix"}	,0,8);
	$CurrentLabel->{"Owner"}	= substr($CurrentLabel->{"Owner"}	,0,12);
	
	
	
	my ($ProjectLine1,$ProjectLine2) = split /-/,$CurrentLabel->{"Project"};
	$ProjectLine1 = substr($ProjectLine1,0,11);
	
	if($ProjectLine2)
	{
		$ProjectLine2 = '-'.substr($ProjectLine2,0,11)
	}
	else
	{
		$ProjectLine2 = substr($ProjectLine1,10,11);
	}
	
	# Printing underscores on TEC printers is ugly, change any to dashes.
	$ProjectLine1 			=~ s/_/-/g; 
	$ProjectLine2 			=~ s/_/-/g;
	$CurrentLabel->{"Name"} 	=~ s/_/-/g;
	
	
	my $NameLine1 = substr($CurrentLabel->{"Name"},0,10);

	print $FHDL $ESC,"RC001;$pkg->{\"Date\"}",$LF,$NULL;
	print $FHDL $ESC,"RC002;$ProjectLine1",$LF,$NULL;
	print $FHDL $ESC,"RC003;$ProjectLine2",$LF,$NULL;

	print $FHDL $ESC,"RC005;$NameLine1",$LF,$NULL;
	print $FHDL $ESC,"RC006;$CurrentLabel->{\"Suffix\"}",$LF,$NULL;

	print $FHDL $ESC,"RC008;$CurrentLabel->{\"Owner\"}",$LF,$NULL;
	
	print $FHDL $ESC,"RB01;$CurrentLabel->{\"Barcode\"}",$LF,$NULL;
	
	print $FHDL $ESC,"XS;I,$pkg->{\"Quantity\"},0002C3201",$LF,$NULL;
}








}

sub TextOnly_Small 
{
	my $pkg = shift;
	my $FHDL = $pkg->{FHDL};
	my $pad = '                                ';

#DATE
print $FHDL $ESC,"PC001;0012,0210,05,05,H,+03,11,B",$LF,$NULL;

#Project
print $FHDL $ESC,"PC002;0103,0210,05,05,H,+02,11,B",$LF,$NULL;
print $FHDL $ESC,"PC003;0052,0210,05,05,H,+02,11,B",$LF,$NULL;


#Name (On round Label)
print $FHDL $ESC,"PC005;0218,0184,05,1,G,+00,00,B",$LF,$NULL;
print $FHDL $ESC,"PC006;0212,0207,05,1,G,+00,00,B",$LF,$NULL;

#Suffix (On round label)
print $FHDL $ESC,"PC007;0218,0230,05,1,G,+01,00,B",$LF,$NULL;

print $FHDL $ESC,"PC008;0133,0210,05,1,G,+01,11,B",$LF,$NULL;




foreach my $CurrentLabel (@{$pkg->{Label}})
{
	# Clear label layout form printers memory
	print $FHDL $ESC,"C",$LF,$NULL;
	
	# Used ased for a blank label to be printed in middle of the job
	if($CurrentLabel->{"Barcode"} eq 'BREAK'){print $FHDL $ESC,"T20C32",$LF,$NULL; next;}
	
	$CurrentLabel->{"Name"} 	= $CurrentLabel->{"Name"}.$pad;
	$CurrentLabel->{"Project"} 	= $CurrentLabel->{"Project"}.$pad;
	$CurrentLabel->{"Suffix"}	= $CurrentLabel->{"Suffix"}.$pad;
	$CurrentLabel->{"Owner"}	= $CurrentLabel->{"Owner"}.$pad;
	
	$CurrentLabel->{"Name"} 	=~ s/_/-/g; 
	$CurrentLabel->{"Project"} 	=~ s/_/-/g;
	
	$CurrentLabel->{"Suffix"}	= substr($CurrentLabel->{"Suffix"}	,0,8);
	$CurrentLabel->{"Owner"}	= substr($CurrentLabel->{"Owner"}	,0,12);
	
	
	my ($ProjectLine1,$ProjectLine2) = split /-/,$CurrentLabel->{"Project"};
	$ProjectLine1 = substr($ProjectLine1,0,11);
	
	if($ProjectLine2)
	{
		$ProjectLine2 = '-'.substr($ProjectLine2,0,11)
	}
	else
	{
		$ProjectLine2 = substr($ProjectLine1,10,11);
	}
	
	# Printing underscores on TEC printers is ugly, change any to dashes.
	$ProjectLine1 			=~ s/_/-/g; 
	$ProjectLine2 			=~ s/_/-/g;
	$CurrentLabel->{"Name"} 	=~ s/_/-/g;
	
	
	my $NameLine1 = substr($CurrentLabel->{"Name"},0,10);
	my $NameLine2 = substr($CurrentLabel->{"Name"},10,10);
	
	#Blank square
	print $FHDL $ESC,"LC;0018,0095,0140,0185,1,2,002",$LF,$NULL;
	
	print $FHDL $ESC,"RC001;$pkg->{\"Date\"}",$LF,$NULL;
	print $FHDL $ESC,"RC002;$ProjectLine1",$LF,$NULL;
	print $FHDL $ESC,"RC003;$ProjectLine2",$LF,$NULL;

	print $FHDL $ESC,"RC005;$NameLine1",$LF,$NULL;
	print $FHDL $ESC,"RC006;$NameLine2",$LF,$NULL;

	print $FHDL $ESC,"RC007;$CurrentLabel->{\"Suffix\"}",$LF,$NULL;

	print $FHDL $ESC,"RC008;$CurrentLabel->{\"Owner\"}",$LF,$NULL;
	
	print $FHDL $ESC,"XS;I,$pkg->{\"Quantity\"},0002C3201",$LF,$NULL;
}

}


sub PetriDishLabels 
{
	my $pkg = shift;
	my $FHDL = $pkg->{FHDL};
	my $pad = '                ';
	my $i;
	my $HumanReadable;

##############################################################
# Set Up label postions and fonts
# Date
print $FHDL $ESC,"PC001;0300,0035,1,1,G,00,B",$LF,$NULL;
# Name
print $FHDL $ESC,"PC003;0520,0035,1,1,G,+03,00,B",$LF,$NULL;
# Project
print $FHDL $ESC,"PC004;0300,0065,1,1,G,+03,00,B",$LF,$NULL;
# Suffix
print $FHDL $ESC,"PC005;0770,0035,1,1,G,+03,00,B",$LF,$NULL;

# Name 		Reduced Size
print $FHDL $ESC,"PC007;0520,0065,05,1,G,+03,00,B",$LF,$NULL;
# Project 	Reduced Size
print $FHDL $ESC,"PC008;0300,0065,05,1,G,+03,00,B",$LF,$NULL;
# Suffix 	Reduced Size
print $FHDL $ESC,"PC009;0770,0035,05,1,G,+03,00,B",$LF,$NULL;

# EAN 13 medium res barcode
print $FHDL $ESC,"XB01;0030,0000,5,3,02,0,0070,+0000000000,002,0,00",$LF,$NULL;
##############################################################


foreach my $CurrentLabel (@{$pkg->{Label}})
{
	# Clear label layout form printers memory
	print $FHDL $ESC,"C",$LF,$NULL;
	
	# Used ased for a blank label to be printed in middle of the job
	if($CurrentLabel->{"Barcode"} eq 'BREAK'){print $FHDL $ESC,"T20C32",$LF,$NULL; next;}
	
	($CurrentLabel->{"Barcode"}, $HumanReadable) = Calculatebarcode($pkg->{"Type"},$CurrentLabel->{"Barcode"});
	if($CurrentLabel->{"Barcode"} == -1){warn "Invalid Number Type In Sanger Barcode Calculation\n"; next;}
	
	# Restrict Amount Of Info that can be printed in any label field
	
	$CurrentLabel->{"Name"} 	= substr($CurrentLabel->{"Name"}	,0,22);
	$CurrentLabel->{"Project"}	= substr($CurrentLabel->{"Project"}	,0,60);
	$CurrentLabel->{"Suffix"}	= substr($CurrentLabel->{"Suffix"}	,0,9);
	
	$CurrentLabel->{"Name"} 	=~ s/_/-/g; 
	$CurrentLabel->{"Project"} 	=~ s/_/-/g;
	
	
	print $FHDL $ESC,"RC001;$pkg->{\"Date\"}",$LF,$NULL;
	
	
	$i = 3; 
	if(length($CurrentLabel->{"Name"}) > 18){$i = 7;}
	print $FHDL $ESC,"RC00$i;$CurrentLabel->{\"Name\"}",$LF,$NULL;
	
	$i = 4; 
	if(length($CurrentLabel->{"Project"}) > 30){$i = 8;}
	
	print $FHDL $ESC,"RC00$i;$CurrentLabel->{\"Project\"}",$LF,$NULL;
	print $FHDL $ESC,"RC005;$CurrentLabel->{\"Suffix\"}",$LF,$NULL;
	print $FHDL $ESC,"RB01;$CurrentLabel->{\"Barcode\"}",$LF,$NULL;
	print $FHDL $ESC,"XS;I,$pkg->{\"Quantity\"},0002C3201",$LF,$NULL;
	
}

}


sub IdentityLabels 
{
	my $pkg = shift;
	my $FHDL = $pkg->{FHDL};
	my $pad = '                ';
	my $i;
	my $HumanReadable;

##############################################################
# Set Up label postions and fonts

# Name
print $FHDL $ESC,"PC003;0600,0035,1,1,G,00,B",$LF,$NULL;
# Owner
print $FHDL $ESC,"PC006;0600,0065,1,1,G,00,B",$LF,$NULL;

print $FHDL $ESC,"PC004;0300,0035,1,1,G,00,B",$LF,$NULL;
print $FHDL $ESC,"PC005;0300,0065,1,1,G,00,B",$LF,$NULL;


# EAN 13 medium res barcode
print $FHDL $ESC,"XB01;0030,0005,5,3,02,0,0070,+0000000000,002,0,00",$LF,$NULL;
##############################################################


foreach my $CurrentLabel (@{$pkg->{"Label"}})
{
	# Clear label layout form printers memory
	print $FHDL $ESC,"C",$LF,$NULL;
	print $FHDL $ESC,"LC;0580,0010,0580,0075,0,2",$LF,$NULL;
	
	# Used ased for a blank label to be printed in middle of the job
	if($CurrentLabel->{"Barcode"} eq 'BREAK'){print $FHDL $ESC,"T20C32",$LF,$NULL; next;}
	
	($CurrentLabel->{"Barcode"}, $HumanReadable) = Calculatebarcode($pkg->{"Type"},$CurrentLabel->{"Barcode"});
print "Calculatebarcode($pkg->{Type},$CurrentLabel->{Barcode}) = ($CurrentLabel->{Barcode},$HumanReadable)\n";
	if($CurrentLabel->{"Barcode"} == -1){warn "Invalid Number Type In Sanger Barcode Calculation\n"; next;}
	
	# Restrict Amount Of Info that can be printed in any label field
	
	$CurrentLabel->{"Name"} 	= substr($CurrentLabel->{"Name"}	,0,20);
	$CurrentLabel->{"Owner"}	= substr($CurrentLabel->{"Owner"}	,0,20);
	
	$CurrentLabel->{"Name"} 	=~ s/_/-/g; 
	$CurrentLabel->{"Owner"} 	=~ s/_/-/g;
	
	
	print $FHDL $ESC,"RC003;$CurrentLabel->{\"Name\"}",$LF,$NULL;
	print $FHDL $ESC,"RC006;$CurrentLabel->{\"Owner\"}",$LF,$NULL;
	
	print $FHDL $ESC,"RB01;$CurrentLabel->{\"Barcode\"}",$LF,$NULL;
	
	print $FHDL $ESC,"RC004;ORACLE (LIVE)",$LF,$NULL;
	print $FHDL $ESC,"RC005;Sample Tracking",$LF,$NULL;
	
	print $FHDL $ESC,"XS;I,$pkg->{\"Quantity\"},0002C3201",$LF,$NULL;
	
}

}

sub addLabel
{
	my ($pkg,%args) = @_;
	
	$pkg->Type($args{Prefix})			if (defined($args{Prefix}));
	$pkg->Barcode($args{Barcode})		if (defined($args{Barcode}));
	$pkg->Name($args{Name})				if (defined($args{Name}));
	$pkg->Project($args{Project})		if (defined($args{Project}));
	$pkg->Desc($args{Desc})				if (defined($args{Desc}));

	$pkg->Labellist();
}

sub printLabels
{
	my $pkg = shift;
	eval { $pkg->Printlabel(); };
	die "$@\n" if ($@);
}

sub getPrinters
{
	my $pkg = shift;
	my %args = (@_);

	my @plist;
	my $printers;

	if (defined($args{-Prefix})) {
		my $sth = $pkg->{se}->virtualSqlLib('barcode','printers', 
		                                    "select a.description 
		                                     from barcode_printer a, barcode_prefix b 
		                                     where a.active_label=b.id_label and a.iscurrent=1 and b.id_prefix=?
		                                     order by a.description");
		$printers = $pkg->{se}->getAll($sth, [$args{-Prefix}], $pkg->{dbh});
	} elsif (defined($args{-Override})) {
		my $sth = $pkg->{se}->virtualSqlLib('barcode','printers', 
		                                    "select description 
		                                     from barcode_printer 
		                                     where iscurrent=1 and active_label=?
		                                     order by description");
		$printers = $pkg->{se}->getAll($sth, [$args{-Override}], $pkg->{dbh});
	} else {
		my $sth = $pkg->{se}->virtualSqlLib('barcode','printers', 
		                                    "select description 
		                                     from barcode_printer
		                                     where iscurrent=1
		                                     order by description");
		$printers = $pkg->{se}->getAll($sth, [], $pkg->{dbh});
	}

	foreach my $p (@$printers) {
		push (@plist,@$p);
	}
	return \@plist;
}

sub Viewprinters
{
	my $pkg = shift;
	viewPrinters($pkg->{Override}, $pkg->{Type}, \$pkg->{Printer}, $pkg->{se}, $pkg->{dbh});
}


1;

=head1 NAME

 SIBarcode

=head1 SYNOPSYS

 use SIBarcode;

 # create a new barcode object
 my $barcode = new Barcode(-Printer=>'d318bc', -Type=>'EQ');

 # add some labels
 $barcode->addLabel(Barcode => '123456789');
 $barcode->addLabel(Barcode => '3141592');

 # print them all
 $barcode->printLabels();

=head1 DESCRIPTION

For a full and frank description of using the SIBarcode module, see the Module Documentation
section of http://intweb.sanger.ac.uk/Teams/Team71/Prod_sw_group/

=cut

