/*******************************************************************************
 * This file is part of GECAMed.
 * 
 * GECAMed is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License (L-GPL) as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GECAMed is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License (L-GPL)
 * along with GECAMed.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * GECAMed is Copyrighted by the Centre de Recherche Public Henri Tudor (http://www.tudor.lu)
 * (c) CRP Henri Tudor, Luxembourg, 2008
 *******************************************************************************/
package lu.tudor.santec.gecamed.billing.gui.print;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.Timer;

import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Invoice;
import lu.tudor.santec.gecamed.billing.ejb.entity.beans.InvoiceStub;
import lu.tudor.santec.gecamed.billing.ejb.session.beans.InvoiceBean;
import lu.tudor.santec.gecamed.billing.ejb.session.interfaces.InvoiceInterface;
import lu.tudor.santec.gecamed.billing.gui.BillingModule;
import lu.tudor.santec.gecamed.billing.gui.invoice.stub.InvoiceStubComparator;
import lu.tudor.santec.gecamed.billing.utils.InvoiceWorkflow;
import lu.tudor.santec.gecamed.core.gui.GECAMedColors;
import lu.tudor.santec.gecamed.core.gui.GECAMedLog;
import lu.tudor.santec.gecamed.core.gui.MainFrame;
import lu.tudor.santec.gecamed.core.gui.utils.SwingWorker;
import lu.tudor.santec.gecamed.core.gui.widgets.ErrorDialog;
import lu.tudor.santec.gecamed.core.gui.widgets.animatedicon.AnimatedIcon;
import lu.tudor.santec.gecamed.core.gui.widgets.print.PrintParameterFetcher;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.usermanagement.gui.settings.UserSettingsPlugin;
import lu.tudor.santec.i18n.Relocalizable;
import lu.tudor.santec.i18n.Translatrix;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

//***************************************************************************
//* Class Definition and Members                                            *
//***************************************************************************

public class BatchPrintPanel extends JPanel implements ItemListener,
													   ActionListener,
													   Relocalizable
{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private JCheckBox					m_PrintAll;
	private JLabel						m_PrintFromLabel;
	private JSpinner					m_PrintFrom;
	private JLabel						m_PrintToLabel;
	private JSpinner					m_PrintTo;
	private JButton						m_PrintMailingButton;
	private JProgressBar				m_PrintMailingProgress;
	
	private ImageIcon					m_InvoicePrintIcon;
	private ImageIcon					m_SuspendPrintIcon;
	private AnimatedIcon				m_ResumePrintIcon;

	private SwingWorker  				m_BatchPrinter;
	
	private Timer						m_Timer;
	private int							m_BatchSize;
	private int							m_Current;
	private boolean						m_Suspend;
	private boolean						m_Paused;
	private boolean						m_Aborted;
	private boolean						m_PrintCopy;
	
	private InvoiceInterface			m_InvoiceInterface;
	private InvoicePrinter				m_Printer;
	
	private Collection <InvoiceStub>	m_InvoiceStubs;
	private Collection <InvoiceStub>	m_PrintedInvoiceStubs;
	
	private boolean						m_CopyOverride;
	private int							m_NumberOfCopies;
	private int							m_SortingProperty;
	private int							m_SortDirection;
	
//***************************************************************************
//* Class Constants                                                         *
//***************************************************************************

	
	private final static int	   c_IconTextGap   = 10;

	private final static int	   c_TimerDelay	   = 5000;

	//=======================================================================
	//= Layout Strings
	//=======================================================================

	private final static String c_Columns 	= 	"3dlu,fill:pref," +
				  								"3dlu,fill:pref:grow," +
	  											"3dlu,fill:pref," +
	  											"3dlu,fill:pref:grow,3dlu";


	private final static String c_Rows 		= 	"3dlu,fill:pref," +
	  											"3dlu,fill:pref," +
	  											"3dlu,fill:pref," +
	  											"3dlu,fill:pref,3dlu";
	
	//=======================================================================
	//= I18N Strings
	//=======================================================================

	private final static String c_PrintAllLabel				= "BatchPrintPanel.PrintAllLabel";
	private final static String c_PrintFromLabel			= "BatchPrintPanel.PrintFromLabel";
	private final static String c_PrintToLabel				= "BatchPrintPanel.PrintToLabel";
	private final static String c_BatchPrintButton			= "BatchPrintPanel.BatchPrintButton";
	private final static String c_PrintSuspendButton		= "BatchPrintPanel.PrintSuspendButton";
	private final static String c_PrintResumeButton			= "BatchPrintPanel.PrintResumeButton";
	private final static String c_PrintProgressIdle			= "BatchPrintPanel.PrintProgressIdle";
	private final static String c_PrintProgressDone			= "BatchPrintPanel.PrintProgressDone";
	private final static String c_PrintProgressAbort		= "BatchPrintPanel.PrintProgressAbort";
	private final static String c_PrintProgressPaused		= "BatchPrintPanel.PrintProgressPaused";
	private final static String c_WaitingForPrinter			= "BatchPrintPanel.WaitingForPrinter";

	private final static String c_PrintErrorTitle			= "BatchPrintPanel.PrintErrorTitle";
	private final static String c_PrintErrorMessage			= "BatchPrintPanel.PrintErrorMessage";

	private final static String c_NoError					= "BatchPrintPanel.NoError"; 
	private final static String c_TooManyJobsInQueue		= "BatchPrintPanel.TooManyJobsInQueue"; 
	private final static String c_DidNotAcceptJobs			= "BatchPrintPanel.DidNotAcceptJobs"; 

	private static Logger m_Logger = Logger.getLogger (BatchPrintPanel.class.getName());

//---------------------------------------------------------------------------
//***************************************************************************
//* Constructor                                                             *
//***************************************************************************
//---------------------------------------------------------------------------
	
public BatchPrintPanel ()
	{
	CellConstraints	l_Constraints;
	FormLayout		l_Layout;	
	
	m_CopyOverride	  = false;
	m_NumberOfCopies  = 1;
	m_SortingProperty = InvoiceStubComparator.c_None;
	m_SortDirection   = InvoiceStubComparator.c_Ascending;
	
	l_Constraints  = new CellConstraints();

	m_PrintFromLabel		= new JLabel ();
	m_PrintFromLabel.setForeground(GECAMedColors.c_LabelColor);
	
	m_PrintToLabel		= new JLabel ();
	m_PrintToLabel.setForeground(GECAMedColors.c_LabelColor);

	this.setBackground(GECAMedColors.c_GECAMedBackground);
	this.relocalize();
		
	//=======================================================================
	//= Assemble Print Panel
	//=======================================================================

	l_Layout = new FormLayout(c_Columns, c_Rows);
	this.setOpaque(false);
	this.setLayout(l_Layout);
	
	m_PrintAll = new JCheckBox (Translatrix.getTranslationString (c_PrintAllLabel));
	m_PrintAll.setOpaque(false);
    m_PrintAll.addItemListener(this);
	m_PrintAll.setSelected(true);
	
    m_PrintFrom   = new JSpinner (new SpinnerNumberModel ());
	m_PrintFrom.setEnabled(false);
	m_PrintFromLabel.setEnabled(false);
	
	m_PrintTo = new JSpinner (new SpinnerNumberModel ());
	m_PrintTo.setEnabled(false);
	m_PrintToLabel.setEnabled(false);

    m_InvoicePrintIcon = BillingModule.getIconResource("rmndr_batch_print.png");
    m_SuspendPrintIcon = BillingModule.getIconResource("rmndr_print_suspend.png");
    m_ResumePrintIcon  = new AnimatedIcon (BillingModule.getIconResource("rmndr_print_paused.gif"));

    m_PrintMailingButton = new JButton ();
	m_PrintMailingButton.setIcon(m_InvoicePrintIcon);
	m_PrintMailingButton.setText(Translatrix.getTranslationString(c_BatchPrintButton));
	m_PrintMailingButton.setIconTextGap(c_IconTextGap);
	m_PrintMailingButton.addActionListener(this);
	
	m_PrintMailingProgress = new JProgressBar ();
	m_PrintMailingProgress.setMinimum(0);
	m_PrintMailingProgress.setValue(0);
	m_PrintMailingProgress.setStringPainted(true);
	m_PrintMailingProgress.setString (Translatrix.getTranslationString(c_PrintProgressIdle));
	
	this.add (m_PrintAll,	  	l_Constraints.xywh( 2, 2, 7, 1));
	this.add (m_PrintFromLabel,	l_Constraints.xywh( 2, 4, 1, 1));
	this.add (m_PrintFrom,		l_Constraints.xywh( 4, 4, 1, 1));
	this.add (m_PrintToLabel,	l_Constraints.xywh( 6, 4, 1, 1));
	this.add (m_PrintTo,			l_Constraints.xywh( 8, 4, 1, 1));
	
	this.add (m_PrintMailingButton, l_Constraints.xywh( 2, 6, 7, 1));
	this.add (m_PrintMailingProgress, l_Constraints.xywh( 2, 8, 7, 1));	
	}

//---------------------------------------------------------------------------
//***************************************************************************
//* Class Primitives                                                        *
//***************************************************************************

//---------------------------------------------------------------------------

private void toggleSuspendButton (boolean p_SuspendButton)
	{
	if (p_SuspendButton)
		{
		m_PrintMailingButton.setIcon(m_SuspendPrintIcon);
		m_PrintMailingButton.setText(Translatrix.getTranslationString(c_PrintSuspendButton));	
		}
	else
		{
		m_PrintMailingButton.setIcon(m_InvoicePrintIcon);
		m_PrintMailingButton.setText(Translatrix.getTranslationString(c_BatchPrintButton));	
		}
	}

//---------------------------------------------------------------------------

private void toggleResumeButton (boolean p_ResumeButton)
	{
	if (p_ResumeButton)
		{
		m_PrintMailingButton.setIcon(m_ResumePrintIcon);
		m_PrintMailingButton.setText(Translatrix.getTranslationString(c_PrintResumeButton));	
		}
	else
		{
		m_PrintMailingButton.setIcon(m_SuspendPrintIcon);
		m_PrintMailingButton.setText(Translatrix.getTranslationString(c_PrintSuspendButton));	
		}
	}

//---------------------------------------------------------------------------

private int getPrintFrom ()
	{
	int	l_PrintFrom;
	int l_PrintTo;
	
	l_PrintFrom = ((Integer)m_PrintFrom.getValue()).intValue();
	l_PrintTo   = ((Integer)m_PrintTo.getValue()).intValue();
	
	return Math.min(l_PrintFrom, l_PrintTo);
	}

//---------------------------------------------------------------------------

private int getPrintTo ()
	{
	int	l_PrintFrom;
	int l_PrintTo;
	
	l_PrintFrom = ((Integer)m_PrintFrom.getValue()).intValue();
	l_PrintTo   = ((Integer)m_PrintTo.getValue()).intValue();
	
	return Math.max(l_PrintFrom, l_PrintTo);
	}

//---------------------------------------------------------------------------

private String getMeaningOf (int p_PrinterStatus)
	{
	switch (p_PrinterStatus)
		{
		case InvoicePrinter.c_NoError 			 : return Translatrix.getTranslationString(c_NoError);
		case InvoicePrinter.c_TooManyJobsInQueue : return Translatrix.getTranslationString(c_TooManyJobsInQueue);
		case InvoicePrinter.c_DidNotAcceptJobs	 : return Translatrix.getTranslationString(c_DidNotAcceptJobs);
		}
	return "";
	}

//---------------------------------------------------------------------------

private void showPrintError (int p_PrinterStatus, Exception p_Exception, String[] p_Filler)
	{
	String l_PrinterStatus;
	
	if (p_Exception == null)
		{
		l_PrinterStatus = this.getMeaningOf (p_PrinterStatus);
		
		ErrorDialog.showErrorDialog	(MainFrame.getInstance(), 
									 Translatrix.getTranslationString(c_PrintErrorTitle), 
									 Translatrix.getTranslationString(c_PrintErrorMessage,p_Filler),
									 l_PrinterStatus);
		}
	else	
		{
		ErrorDialog.showErrorDialog	(MainFrame.getInstance(), 
									 Translatrix.getTranslationString(c_PrintErrorTitle), 
									 Translatrix.getTranslationString(c_PrintErrorMessage,p_Filler),
									 p_Exception);	
		}
	}
						
//---------------------------------------------------------------------------

private Collection <InvoiceStub> sortInvoiceStubs (Collection <InvoiceStub> p_Unsorted)
	{
	Collection <InvoiceStub>	l_InvoiceStubs;
	InvoiceStub []				l_InvoiceStubArray;
	InvoiceStubComparator		l_Comparator;
	int							l_Index;
	
	if (p_Unsorted == null) return null;
	
	l_InvoiceStubArray = new InvoiceStub[p_Unsorted.size()];
	l_InvoiceStubArray = p_Unsorted.toArray(l_InvoiceStubArray);
	
	l_Comparator = new InvoiceStubComparator ();
	l_Comparator.addSortCriterion(InvoiceStubComparator.c_PhysicianId, InvoiceStubComparator.c_Ascending);
	l_Comparator.addSortCriterion(m_SortingProperty, m_SortDirection);
		
	Arrays.sort (l_InvoiceStubArray,l_Comparator);

	l_InvoiceStubs = new LinkedHashSet <InvoiceStub> ();
	for (l_Index = 0; l_Index < l_InvoiceStubArray.length; l_Index++)
		{
		l_InvoiceStubs.add (l_InvoiceStubArray [l_Index]);
		}
	
	return l_InvoiceStubs;
	}

//---------------------------------------------------------------------------
//***************************************************************************
//* Interface Getters                                                       *
//***************************************************************************
//---------------------------------------------------------------------------

private InvoiceInterface getInvoiceInterface ()
	{
	if (m_InvoiceInterface != null) return m_InvoiceInterface;

	try {
		m_InvoiceInterface = (InvoiceInterface) ManagerFactory.getRemote(InvoiceBean.class);
//		InitialContext l_Context = new InitialContext();
//		m_InvoiceInterface = (InvoiceInterface) l_Context.lookup("InvoiceBean/remote");
//		l_Context.close();
		} 
	catch (Exception p_Exception) 
		{
		m_Logger.warn(p_Exception.getLocalizedMessage());
		}

	return m_InvoiceInterface;
	}

//---------------------------------------------------------------------------

private Invoice fetchInvoiceForStub (InvoiceStub p_InvoiceStub)
	{
	Invoice	l_Invoice = null;
	
	InvoiceInterface	l_InvoiceInterface;
	
	l_InvoiceInterface = this.getInvoiceInterface();
	if (l_InvoiceInterface == null) return l_Invoice;
	
	try	{
		l_Invoice = l_InvoiceInterface.getInvoiceByID(p_InvoiceStub.getId());
		l_Invoice = l_InvoiceInterface.fetchPatientForInvoice(l_Invoice);
		}
	catch (Exception p_Exception)
		{
		m_Logger.warn(p_Exception.getLocalizedMessage());
		}
	
	return l_Invoice;
	}

//***************************************************************************
//* Swing Worker Thread                                                     *
//***************************************************************************
//---------------------------------------------------------------------------

Object BatchPrinter ()
	{
	this.batchPrintInit ();
	this.batchPrintMailing();
	return "";
	}

//---------------------------------------------------------------------------

protected synchronized String	getSuspendedMessage ()
	{
	String[]	l_Filler;

	l_Filler = new String [2];
	l_Filler [0] = Integer.valueOf (m_Current).toString();
	l_Filler [1] = Integer.valueOf (m_InvoiceStubs.size()).toString();
			
	return Translatrix.getTranslationString(c_PrintProgressPaused,l_Filler);	
	}

//---------------------------------------------------------------------------

protected synchronized void batchPrintInit ()
	{
	int			l_PrintFrom	= 0;
	int			l_PrintTo	= 0;

	this.toggleSuspendButton(true);
	
	if ((Boolean)MainFrame.getInstance().userSettings.getValue(UserSettingsPlugin.PRINTER_BATCH_SPLIT_ENABLED))
		 m_BatchSize = (Integer) MainFrame.getInstance().userSettings.getValue(UserSettingsPlugin.PRINTER_BATCH_SIZE);
	else m_BatchSize = 0;	
	
	m_Paused	= false;
	m_Suspend	= false;
	m_Current	= 0;
	
	m_PrintMailingProgress.setMinimum(0);

	if (!m_PrintAll.isSelected())
		{
		// Minus 1 because Invoice positions on statement start with one
		// and internally we're using 0 based indexes.
		
		l_PrintFrom = this.getPrintFrom() - 1;
		l_PrintTo = this.getPrintTo() - 1;			
		
		m_PrintMailingProgress.setMaximum(l_PrintTo - l_PrintFrom + 1);
		}
	else
		{
		m_PrintMailingProgress.setMaximum(m_InvoiceStubs.size());
		}
	

	if (m_SortingProperty != InvoiceStubComparator.c_None)
		{
		m_InvoiceStubs = this.sortInvoiceStubs(m_InvoiceStubs);
		}

	//========================================================================
	//= Step 1. Get instance of InvoicePrinter object. In the case of batch
	//= print, we don't want neither a preview nor a print dialog. Setting
	//= InvoicePrinters' print immediately flag makes sure they won't show.
	//========================================================================
	
	m_Printer = new InvoicePrinter ();
	m_Printer.setPrintImmediately(true);
	m_Printer.setQueueSizeRetries      (10);
	m_Printer.setQueueSizeDelay     (10000);
	m_Printer.setJobAcceptanceRetries  (10);
	m_Printer.setJobAcceptanceDelay  (1000);
	}

//---------------------------------------------------------------------------

protected synchronized boolean prePrintProcessing (Invoice p_Invoice, int	p_Count)
	{
	int		l_Action;
	boolean	l_PrintIt;
	
	l_Action = InvoiceWorkflow.changeInvoiceState (p_Invoice, InvoiceWorkflow.c_PrintAction);
	if (   (l_Action == InvoiceWorkflow.c_DoPrint) 
//		|| (l_Action == InvoiceWorkflow.c_DoPrintCopy))
		|| (l_Action == InvoiceWorkflow.c_DoPrintOriginal))
		{
//		if (m_CopyOverride == false) m_PrintCopy = (l_Action == InvoiceWorkflow.c_DoPrintCopy);
		if (m_CopyOverride == false) m_PrintCopy = BillingModule.copyRequired (p_Invoice,l_Action);
		
		m_PrintMailingProgress.setString(p_Invoice.formatInvoiceNumber(Invoice.c_LongFormat, true));
		m_PrintMailingProgress.setValue(p_Count);
		l_PrintIt = true;
		}
	else l_PrintIt = false;
	
	return l_PrintIt;
	}

//---------------------------------------------------------------------------

protected synchronized boolean postPrintProcessing (Invoice p_Invoice, int	p_Count)
	{
	InvoiceInterface	l_InvoiceInterface;
	
	l_InvoiceInterface = this.getInvoiceInterface();
	if (l_InvoiceInterface != null)
		{
		try	{
//			if (!p_Invoice.alreadyPrinted()) p_Invoice.setPrintDate (new Date ());
			p_Invoice = l_InvoiceInterface.saveInvoice(p_Invoice);	
			}
		catch (Exception p_Exception)
			{
			m_Logger.log(Level.ERROR, "Failed to save Invoice state\n" + p_Exception.getLocalizedMessage());
			m_Aborted = true;
			}
		}
	return true;
	}

//---------------------------------------------------------------------------

protected synchronized boolean doPrint (Invoice p_Invoice, int p_NumberOfCopies)
	{
	boolean					l_WasPrinted;
	HashMap<String, Object> l_Parameter = PrintParameterFetcher.createDefaultPrintParameter(p_Invoice);
	
	l_WasPrinted = false;
	l_WasPrinted = m_Printer.printInvoice (p_Invoice, p_NumberOfCopies, m_PrintCopy, false, l_Parameter);
	
	if (l_WasPrinted) GECAMedLog.user ("Billing","PRINT Invoice","Printed Invoice with ID " + p_Invoice.getId());
	
	return l_WasPrinted;			
	}

//---------------------------------------------------------------------------

protected synchronized void handlePrintError (Invoice p_Invoice)
	{
	String[]				l_Filler;

	l_Filler = new String [2];
	l_Filler[0] = p_Invoice.formatInvoiceNumber(Invoice.c_LongFormat, true);
	l_Filler[1] = Integer.valueOf(m_Current).toString();
						
	this.showPrintError (m_Printer.getStatus(), m_Printer.getException(), l_Filler);
	m_Aborted = true;
	}

//---------------------------------------------------------------------------

protected synchronized void batchPrintMailing ()
	{
	Iterator <InvoiceStub>  l_InvoiceStubIterator;
	InvoiceStub			    l_InvoiceStub;
	Invoice					l_Invoice;
	boolean					l_Done		   = false;

	int						l_AlreadyPrinted   	= 0;
	int						l_PrintFrom	   		= 0;
	int						l_PrintTo	   		= 0;
	
	m_Timer 			  = new Timer (c_TimerDelay,this);
	m_PrintedInvoiceStubs = new LinkedHashSet <InvoiceStub> ();
	
	l_InvoiceStubIterator = m_InvoiceStubs.iterator();
	while (l_InvoiceStubIterator.hasNext() && !l_Done && !m_Aborted)
		{
		//====================================================================
		//= Step 1. If user specified a print from boundary, then we have to
		//= fast forward iterator to specified position.
		//====================================================================
			
		if (l_PrintFrom > 0)
			{
			l_InvoiceStub = l_InvoiceStubIterator.next();
			l_PrintFrom--;
			m_Current++;
			continue;
			}
		
		//====================================================================
		//= Step 2. If user specified a print to boundary, then we have to
		//= make sure we stop at the desired location.
		//====================================================================

		if ((l_PrintTo > 0) && (m_Current >= l_PrintTo)) l_Done = true;
	
		//====================================================================
		//= Step 3. If either user clicked on Suspend button or if a maximum
		//= batch size was specified and number of already printed invoices
		//= has reached that number, then we have to suspend batch printing
		//= process.
		//====================================================================
		
		if (m_Suspend || ((m_BatchSize > 0) && (l_AlreadyPrinted == m_BatchSize)))
			{
			m_PrintMailingProgress.setString (this.getSuspendedMessage());	
			this.suspendBatchPrinting();
			l_AlreadyPrinted = 0;
			m_Suspend = false;
			}			

		l_InvoiceStub = l_InvoiceStubIterator.next();
		l_Invoice     = this.fetchInvoiceForStub(l_InvoiceStub);	
		l_Invoice.monetize();
		
		if (this.prePrintProcessing(l_Invoice, m_Current))
			{
			m_Timer.restart ();	
			if (this.doPrint (l_Invoice,m_NumberOfCopies))
				{
				this.postPrintProcessing (l_Invoice, m_Current);
				m_PrintedInvoiceStubs.add (l_InvoiceStub);
				}
			else
				{
				this.handlePrintError (l_Invoice);
				}
			}
		m_Current++;
		l_AlreadyPrinted++;
		}
	
	this.toggleSuspendButton(false);
	m_Timer.stop ();
	
	m_PrintMailingProgress.setValue(0);
	if (m_Aborted)
		{
		m_PrintMailingProgress.setString (Translatrix.getTranslationString(c_PrintProgressAbort));	
		}
	else
		{
		m_PrintMailingProgress.setString (Translatrix.getTranslationString(c_PrintProgressDone));
		}
	}

//---------------------------------------------------------------------------

public void startBatchPrinting ()
	{
	m_BatchPrinter = new SwingWorker() 
	{
	public Object construct() 
		{
		return BatchPrinter ();
		}
	public void start ()
		{
		m_Aborted = false;
		super.start();
		}
	public void finished ()
		{
		m_Printer.close();
		}
	public void interrupt ()
		{
		m_Aborted = true;
		m_Printer.close();
		super.interrupt();
		}
	};

	m_BatchPrinter.start ();  	
	}

//---------------------------------------------------------------------------

public void abortBatchPrinting ()
	{
	m_Aborted = true;
	if (m_BatchPrinter != null) m_BatchPrinter.interrupt();
	}

//---------------------------------------------------------------------------

private synchronized void suspendBatchPrinting ()
	{
	m_Paused = true;
	m_Timer.stop();
	this.toggleResumeButton(true);
	while (m_Paused) 
		try {wait(500);} 
		catch (Exception p_Exception) 
			{
			m_Logger.log(Level.ERROR, "Exception while suspended!", p_Exception);
			m_Paused = false;
			};
			
	this.toggleResumeButton(false);
	m_Timer.start();
	}

//---------------------------------------------------------------------------

private void resumeBatchPrinting ()
	{
	m_Paused = false;
	}

//---------------------------------------------------------------------------
//***************************************************************************
//* Class Body		                                                        *
//***************************************************************************
//---------------------------------------------------------------------------

public void setInvoiceStubs (Collection <InvoiceStub> p_InvoiceStubs)
	{
	if (p_InvoiceStubs != null)
		{
		m_InvoiceStubs = p_InvoiceStubs;
		}
	}

//---------------------------------------------------------------------------

public void setSortingCriteria (int p_SortingProperty, int p_SortDirection)
	{
	m_SortingProperty = p_SortingProperty;
	m_SortDirection   = p_SortDirection;
	}

//---------------------------------------------------------------------------

public void setNumberOfCopies (int p_NumberOfCopies)
	{
	m_NumberOfCopies = p_NumberOfCopies;
	}

//---------------------------------------------------------------------------

public void setCopyOverride (boolean p_CopyOverride, boolean p_PrintCopy)
	{
	m_CopyOverride = p_CopyOverride;
	m_PrintCopy	   = p_PrintCopy;
	}

//---------------------------------------------------------------------------

public Collection <InvoiceStub> getPrintedInvoiceStubs ()
	{
	return m_PrintedInvoiceStubs;
	}

//---------------------------------------------------------------------------

public boolean wasAborted ()
	{
	return m_Aborted;
	}

//---------------------------------------------------------------------------

public void relocalize() 
	{	
	if (m_PrintMailingButton != null)
		m_PrintMailingButton.setText(Translatrix.getTranslationString(c_BatchPrintButton));
	
	if (m_PrintAll != null) 
		m_PrintAll.setText(Translatrix.getTranslationString(c_PrintAllLabel));

	if (m_PrintFromLabel != null) 
		m_PrintFromLabel.setText(Translatrix.getTranslationString(c_PrintFromLabel));
	
	if (m_PrintToLabel != null) 
		m_PrintToLabel.setText(Translatrix.getTranslationString(c_PrintToLabel));
	}

//---------------------------------------------------------------------------

public void actionPerformed(ActionEvent p_Event) 
	{
	if (p_Event.getSource().equals(m_PrintMailingButton))
		{		
		if (m_PrintMailingButton.getText().equals(Translatrix.getTranslationString(c_BatchPrintButton)))
			{
			this.startBatchPrinting();
			}
		else if (m_PrintMailingButton.getText().equals(Translatrix.getTranslationString(c_PrintSuspendButton)))
			{
			m_Suspend = true;
			}	
		else if (m_PrintMailingButton.getText().equals(Translatrix.getTranslationString(c_PrintResumeButton)))
			{
			this.resumeBatchPrinting();
			}	
		}
	else if (p_Event.getSource().equals (m_Timer))
		{
		m_PrintMailingProgress.setString (Translatrix.getTranslationString(c_WaitingForPrinter));	
		}
	}

//---------------------------------------------------------------------------

public void itemStateChanged(ItemEvent p_Event) 
	{
	boolean l_EnableIt;
	
	if (p_Event.getSource().equals (m_PrintAll))
		{
		l_EnableIt = (p_Event.getStateChange() == ItemEvent.DESELECTED)?true:false; 

		if (	(m_PrintFromLabel == null) || (m_PrintToLabel == null)
				|| (m_PrintFrom	  == null) || (m_PrintTo      == null)) return;
		
		m_PrintFromLabel.setEnabled(l_EnableIt);
		m_PrintFrom.setEnabled(l_EnableIt);
		m_PrintToLabel.setEnabled(l_EnableIt);
		m_PrintTo.setEnabled(l_EnableIt);
		
		if (l_EnableIt)
			{
			if ((m_InvoiceStubs != null) && (m_InvoiceStubs.size() > 0))
				{
				m_PrintFrom.setValue(Integer.valueOf (1));
				m_PrintTo.setValue((Integer)m_InvoiceStubs.size());
				}
			}
		}	
	}

//---------------------------------------------------------------------------	
//***************************************************************************
//* End of Class				                            				*
//***************************************************************************
//---------------------------------------------------------------------------	
}

