/*******************************************************************************
 * 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.statistics;

import java.awt.Cursor;
import java.util.Collection;
import java.util.Date;

import lu.tudor.santec.gecamed.billing.ejb.entity.beans.InvoiceStub;
import lu.tudor.santec.gecamed.billing.ejb.session.beans.StatisticsBean;
import lu.tudor.santec.gecamed.billing.ejb.session.interfaces.StatisticsInterface;
import lu.tudor.santec.gecamed.billing.gui.print.InvoicePrinter;
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.progress.ProgressDialog;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.core.utils.querybuilder.WhereClause;
import lu.tudor.santec.i18n.Relocalizable;
import lu.tudor.santec.i18n.Translatrix;

import org.apache.log4j.Logger;

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

public class InvoiceWorker implements Relocalizable
{
	private StatisticsInterface 		m_StatisticsInterface;
	private Collection <InvoiceStub>	m_IssuedInvoices;
	private WhereClause					m_WhereClause;
	private Date						m_FromDate;
	private Date						m_UntilDate;
	private boolean						m_OnlyTotals;
	
	private SwingWorker  				m_BulkWorker;
	private ProgressDialog				m_ProgressDialog;

	private boolean						m_Busy;
	private boolean						m_Aborted;
	
	private static Logger m_Logger = Logger.getLogger (InvoiceWorker.class.getName());

//***************************************************************************
//* Class Constants                                                         *
//***************************************************************************

	private final static int	c_InterruptWaitTime	= 500;
	private final static int	c_MaxWaitCycles		= 10;

	private final static String c_Title  				  = "InvoiceWorker.Title";
	private final static String c_Message  				  = "InvoiceWorker.Message";
	
	private final static String c_FetchingIssuedInvoices  = "InvoiceWorker.FetchingIssuedInvoices";
	private final static String c_IssuedInvoicesFound     = "InvoiceWorker.IssuedInvoicesFound";
	private final static String c_NoIssuedInvoicesFound   = "InvoiceWorker.NoIssuedInvoicesFound";
	private final static String c_PrintingListOfInvoices  = "InvoiceWorker.PrintingListOfInvoices";
	
	private final static String c_Aborting				  = "InvoiceWorker.Aborting";
	
	
//***************************************************************************
//* Constructors                                       						*
//***************************************************************************

public InvoiceWorker ()
	{	
	m_Busy = false;
	m_ProgressDialog = new ProgressDialog ();
	
	this.relocalize();
	}
	
//***************************************************************************
//* Primitives                                      						*
//***************************************************************************

//---------------------------------------------------------------------------
/**
 * The private getInvoiceInterface returns an instance of the StatisticsBean
 * session bean. On the first call, the StatisticsBean will actualy be looked up
 * via JNDI. Once it has been found, the reference to the bean will be stored
 * in a private data member. Doing so avoids JNDI lookups on later calls.
 * @return an instance of the StatisticsBean session bean.
 */
//---------------------------------------------------------------------------

private StatisticsInterface getStatisticsInterface ()
	{
	if (m_StatisticsInterface != null) return m_StatisticsInterface;

	try {
		m_StatisticsInterface = (StatisticsInterface) ManagerFactory.getRemote(StatisticsBean.class);
		} 
	catch (Exception p_Exception) 
		{
		m_Logger.warn(p_Exception.getLocalizedMessage());
		}

	return m_StatisticsInterface;
	}

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

private Collection <InvoiceStub> getIssuedInvoices (WhereClause p_WhereClause)
	{
	Collection <InvoiceStub>	l_IssuedInvoices = null;
	StatisticsInterface 		l_Interface  = null;
		
	l_Interface = this.getStatisticsInterface();
	if (l_Interface == null) return l_IssuedInvoices;
		
	m_Logger.info(p_WhereClause.toString());
		
	try	{
		l_IssuedInvoices = l_Interface.getInvoiceStubsByWhereClause (p_WhereClause);
		}
	catch (Exception p_Exception)
		{
		m_Logger.warn(p_Exception.getLocalizedMessage());
		}

	return l_IssuedInvoices;
	}

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

private void printIssuedInvoicesList (Collection <InvoiceStub> p_IssuedInvoices, Date p_FromDate, Date p_UntilDate, boolean p_OnlyTotals)
	{
	if ((p_IssuedInvoices != null) && (!p_IssuedInvoices.isEmpty())) 
		{
		InvoicePrinter l_InvoicePrinter;
	
		l_InvoicePrinter = new InvoicePrinter();
		l_InvoicePrinter.printIssuedInvoiceList (p_IssuedInvoices, p_FromDate, p_UntilDate,p_OnlyTotals);
		l_InvoicePrinter.close();
		}
	else
		{
		MainFrame.getInstance().showMessage(Translatrix.getTranslationString(c_NoIssuedInvoicesFound));
		}
	}

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

Object StatisticsBulkOperation ()
	{
	String [] l_Filler;
	
	m_ProgressDialog.setTask(c_FetchingIssuedInvoices, null);
	m_IssuedInvoices = this.getIssuedInvoices (m_WhereClause);
	
	if (m_IssuedInvoices != null)
		{
		l_Filler = new String [1];
		l_Filler [0] = Integer.valueOf (m_IssuedInvoices.size()).toString();
		
		m_ProgressDialog.setProgress(0,c_IssuedInvoicesFound,l_Filler);
		}
		
	m_ProgressDialog.setTask(c_PrintingListOfInvoices, null);	
	this.printIssuedInvoicesList (m_IssuedInvoices, m_FromDate, m_UntilDate,m_OnlyTotals);
	return "";
	}

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

private void startBulkOperation ()
	{		
	m_BulkWorker = new SwingWorker() 
		{
		public Object construct() 
			{
			return StatisticsBulkOperation ();
			}
		public void start ()
			{
			m_Busy 	  = true;
			MainFrame.getInstance().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
			m_Aborted = false;
			super.start();
			}
		public void finished ()
			{
			MainFrame.getInstance().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
			m_Aborted = false;
			m_Busy    = false;
			m_ProgressDialog.setVisible(false);
			}
		public void interrupt ()
			{
			m_Aborted = true;
			MainFrame.getInstance().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
			super.interrupt();
			m_ProgressDialog.setVisible(false);
			}
		};

	m_BulkWorker.start ();  	
	}

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

private void abortBulkOperation ()
	{
	if (m_BulkWorker != null) m_BulkWorker.interrupt();
	}

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

private synchronized boolean waitUntilNoLongerBusy ()
	{
	int	l_WaitCycles = 0;

	while ((m_Busy) && (l_WaitCycles < c_MaxWaitCycles))
		{
		try	{
			this.wait (c_InterruptWaitTime);
			}
		catch (Exception p_Exception)
			{
			m_Logger.warn(p_Exception.getLocalizedMessage());
			}
		l_WaitCycles ++;		
		}
	
	if (l_WaitCycles < c_MaxWaitCycles) 
		 return true;
	else return false;
	}

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

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

public void setWhereClause (WhereClause p_WhereClause)
	{
	m_WhereClause = p_WhereClause;
	}

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

public void setFromDate (Date p_FromDate)
	{
	m_FromDate = p_FromDate;
	}
		
//---------------------------------------------------------------------------

public void setUntilDate (Date p_UntilDate)
	{
	m_UntilDate = p_UntilDate;
	}
		
//---------------------------------------------------------------------------

public void setOnlyTotals (boolean p_OnlyTotals)
	{
	m_OnlyTotals = p_OnlyTotals;
	}
		
//---------------------------------------------------------------------------

public void printIssuedInvoices ()
	{
	m_ProgressDialog.setProgressBarMode(ProgressDialog.c_Indetermined);
	m_ProgressDialog.setCancelable(true);
	m_ProgressDialog.pack();
	
	MainFrame.showDialogCentered (m_ProgressDialog);
	
	if (m_Busy)
		{
		m_ProgressDialog.setTask(c_Aborting, null);
		this.abortBulkOperation();
		this.waitUntilNoLongerBusy();
		}
	
	this.startBulkOperation();
	}

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

public void relocalize() 
	{
	m_ProgressDialog.setTitle(c_Title);
	m_ProgressDialog.setMessage(c_Message,null);
	}

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

//***************************************************************************
//* End Of Class                                                            *
//***************************************************************************
//---------------------------------------------------------------------------
}
