/*******************************************************************************
 * 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.core.gui.widgets.templates;

import java.awt.Cursor;
import java.io.File;
import java.io.FileInputStream;
import java.util.Date;

import lu.tudor.santec.gecamed.core.ejb.entity.beans.Template;
import lu.tudor.santec.gecamed.core.ejb.session.beans.TemplateManagerBean;
import lu.tudor.santec.gecamed.core.ejb.session.interfaces.TemplateManagerInterface;
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.progress.ProgressDialog;
import lu.tudor.santec.gecamed.core.gui.widgets.progress.ProgressEvent;
import lu.tudor.santec.gecamed.core.gui.widgets.progress.ProgressEventDispatcher;
import lu.tudor.santec.gecamed.core.gui.widgets.progress.ProgressListener;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.reporting.gui.JRXMLParser;
import lu.tudor.santec.i18n.Relocalizable;

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

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

public class TemplateWorker implements Relocalizable
{
	private TemplateManagerInterface 	m_TemplateInterface;
	private File						m_TemplateFile;
	private Template					m_Template;
	
	private String						m_TemplateName;
	private String						m_TemplateType;
	private Integer						m_PhysicianId;
	private Date						m_TemplateExpiry;
	
	private SwingWorker  				m_BulkWorker;
	private ProgressDialog				m_ProgressDialog;

	private boolean						m_Busy;
	private boolean						m_Aborted;
	
	private ProgressEventDispatcher		m_ProgressEventDispatcher;
	private ProgressEvent				m_ProgressEvent;
	
	private static Logger m_Logger = Logger.getLogger (TemplateWorker.class.getName());

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

	public static final String c_UploadDone		= "TemplateWorker.UploadDone";
	public static final String c_UploadAborted	= "TemplateWorker.UploadAborted";
	
	private final static int	c_InterruptWaitTime	= 500;
	private final static int	c_MaxWaitCycles		= 10;

//***************************************************************************
//* Constructors                                       						*
//***************************************************************************

public TemplateWorker ()
	{	
	m_Busy = false;
	m_ProgressDialog = new ProgressDialog ();
	
	this.relocalize();
	m_ProgressEventDispatcher = new ProgressEventDispatcher();
	m_ProgressEvent = new ProgressEvent (this,ProgressEvent.c_None);
	}
	
//***************************************************************************
//* Primitives                                      						*
//***************************************************************************

//---------------------------------------------------------------------------
/**
 * The private getStatisticsInterface returns an instance of the TemplateManagerBean
 * session bean. On the first call, the TemplateManagerBean 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 TemplateManagerBean session bean.
 */
//---------------------------------------------------------------------------

private TemplateManagerInterface getTemplateInterface ()
	{
	if (m_TemplateInterface != null) return m_TemplateInterface;

	try {
		m_TemplateInterface = (TemplateManagerInterface) ManagerFactory.getRemote(TemplateManagerBean.class);
		} 
	catch (Exception p_Exception) 
		{
		m_Logger.warn(p_Exception.getLocalizedMessage());
		}

	return m_TemplateInterface;
	}

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

private Template getTemplate (Template p_Template)
	{
	TemplateManagerInterface l_Interface  = null;
		
	if (p_Template == null) 
		{
		p_Template = new Template ();
		}
	else
		{
		l_Interface = this.getTemplateInterface();
		if (l_Interface == null) return p_Template;
		
		try	{
			p_Template = l_Interface.getTemplateByID(p_Template.getId());
			}
		catch (Exception p_Exception)
			{
			m_Logger.warn(p_Exception.getLocalizedMessage());
			}
		}
		
	return p_Template;
	}

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

private Template saveTemplate (Template p_Template)
	{
	TemplateManagerInterface l_Interface  = null;
	
	l_Interface = this.getTemplateInterface();
	if (l_Interface == null) return p_Template;
		
	try	{
		p_Template = l_Interface.saveTemplate(p_Template);
		}
	catch (Exception p_Exception)
		{
	    	m_Logger.log(Level.WARN, p_Exception.getLocalizedMessage(), p_Exception);
	    	ErrorDialog.showErrorDialog(MainFrame.getInstance(), p_Exception);
		}
	
	return p_Template;
	}

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

private String getTemplateName (byte[] p_Template) 
	{
	JRXMLParser l_Parser = new JRXMLParser();
	String		l_TemplateName = null;
	
	try {
		l_Parser.parseFile (p_Template);
		l_TemplateName = l_Parser.getReportName();
		} 
	catch (Exception p_Exception) 
		{
		ErrorDialog.showErrorDialog(MainFrame.getInstance(), p_Exception);
		}
	
	return l_TemplateName;
	}

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

private void uploadTemplateFile (File p_TemplateFile)
	{
	byte [] 				l_TemplateData;
//	ByteArrayOutputStream	l_TemplateStream;
	String[]				l_Filler;
	
	if (p_TemplateFile == null) return;
		
	try	{
		l_TemplateData = new byte [(int)p_TemplateFile.length()];
		new FileInputStream (p_TemplateFile).read(l_TemplateData);
		
		m_TemplateName = this.getTemplateName(l_TemplateData);
		
		l_Filler = new String [1];
		l_Filler[0] = m_TemplateName;
		m_ProgressDialog.setTask("TemplateWorker.UploadingTemplate", l_Filler);

//		l_TemplateStream = new ByteArrayOutputStream();
							
//		JasperCompileManager.compileReportToStream(new ByteArrayInputStream(l_TemplateData), l_TemplateStream);
							
		m_Template.setType			(m_TemplateType);
		m_Template.setPhysicianID	(m_PhysicianId);
		m_Template.setName			(m_TemplateName);
		m_Template.setExpiry		(m_TemplateExpiry);
		m_Template.setJrxml 		(l_TemplateData);
		m_Template.setJasper 		(null);
							
		m_Template = this.saveTemplate (m_Template);
		}
	catch (Exception p_Exception) 
		{
		ErrorDialog.showErrorDialog(MainFrame.getInstance(), p_Exception);
		m_Aborted = true;
		}	
	}

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

Object TemplateBulkOperation ()
	{	
	m_ProgressDialog.setTask("TemplateWorker.ReadingTemplate", null);
	m_Template = this.getTemplate (m_Template);
	
	if (m_Template != null)
		{
		this.uploadTemplateFile(m_TemplateFile);
		}

	return "";
	}

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

private void startBulkOperation ()
	{		
	m_BulkWorker = new SwingWorker() 
		{
		public Object construct() 
			{
			return TemplateBulkOperation ();
			}
		public void start ()
			{
			m_Busy 	  = true;
			MainFrame.getInstance().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
			m_Aborted = false;
			m_ProgressEvent.setType(ProgressEvent.c_Started);
			m_ProgressEventDispatcher.notifyProgressListeners(m_ProgressEvent);			
			super.start();
			}
		public void finished ()
			{
			MainFrame.getInstance().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
			m_Aborted = false;
			m_Busy    = false;
			m_ProgressDialog.setVisible(false);
			m_ProgressEvent.setType(ProgressEvent.c_Completed);
			m_ProgressEventDispatcher.notifyProgressListeners(m_ProgressEvent);			
			}
		public void interrupt ()
			{
			m_Aborted = true;
			MainFrame.getInstance().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
			super.interrupt();
			m_ProgressDialog.setVisible(false);
			m_ProgressEvent.setType(ProgressEvent.c_Aborted);
			m_ProgressEventDispatcher.notifyProgressListeners(m_ProgressEvent);			
			}
		};

	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 addProgressListener (ProgressListener p_Listener)
	{
	m_ProgressEventDispatcher.addProgressListener(p_Listener);
	}

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

public void removeProgressListener (ProgressListener p_Listener)
	{
	m_ProgressEventDispatcher.removeProgressListener(p_Listener);
	}

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

public Template getTemplate ()
	{
	return m_Template;
	}

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

public void setTemplate (Template p_Template)
	{
	m_Template = p_Template;
	if (m_Template != null)
		{
		m_TemplateName 	 = m_Template.getName();
		m_TemplateType 	 = m_Template.getType();
		m_TemplateExpiry = m_Template.getExpiry();
		m_PhysicianId    = m_Template.getPhysicianID();
		}
	}

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

public void setTemplateFile (File p_TemplateFile)
	{
	m_TemplateFile = p_TemplateFile;
	}

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

public void setTemplateName (String p_TemplateName)
	{
	m_TemplateName = p_TemplateName;
	}

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

public void setTemplateType (String p_TemplateType)
	{
	m_TemplateType = p_TemplateType;
	}

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

public void setTemplateExpiry (Date p_ExpiryDate)
	{
	m_TemplateExpiry = p_ExpiryDate;
	}

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

public void setPhysicianId (Integer p_PhysicianId)
	{
	m_PhysicianId = p_PhysicianId;
	}
	
//---------------------------------------------------------------------------

public void importTemplate ()
	{
	m_ProgressDialog.setProgressBarMode(ProgressDialog.c_Indetermined);
	m_ProgressDialog.setCancelable(true);
	m_ProgressDialog.pack();
	m_ProgressDialog.setAlwaysOnTop(true);
	
	MainFrame.showDialogCentered (m_ProgressDialog);

	
	if (m_Busy)
		{
		m_ProgressDialog.setTask("TemplateWorker.Aborting", null);
		this.abortBulkOperation();
		this.waitUntilNoLongerBusy();
		}
	
	this.startBulkOperation();
	}

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

public void updateTemplate ()
	{
	if (m_Template != null)
		{
		m_Template.setType			(m_TemplateType);
		m_Template.setPhysicianID	(m_PhysicianId);
		m_Template.setName			(m_TemplateName);
		m_Template.setExpiry		(m_TemplateExpiry);
	
		m_Template = this.saveTemplate(m_Template);
		}
	}

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

public void relocalize() 
	{
	m_ProgressDialog.setTitle   ("TemplateWorker.ImportingTemplateTitle");
	m_ProgressDialog.setMessage ("TemplateWorker.ImportingTemplateMessage",null);
	}

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

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