package lu.tudor.santec.gecamed.billing.gui.reminder;

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

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.border.TitledBorder;

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.gui.BillingModule;
import lu.tudor.santec.gecamed.billing.gui.invoice.stub.InvoiceStubUtils;
import lu.tudor.santec.gecamed.core.gui.GECAMedColors;
import lu.tudor.santec.gecamed.core.gui.GECAMedIconNames;
import lu.tudor.santec.gecamed.core.gui.GECAMedModule;
import lu.tudor.santec.gecamed.core.gui.MainFrame;
import lu.tudor.santec.gecamed.core.gui.utils.SwingWorker;
import lu.tudor.santec.gecamed.core.utils.Logger;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.Insurance;
import lu.tudor.santec.i18n.Relocalizable;
import lu.tudor.santec.i18n.Translatrix;

import org.apache.log4j.Level;

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

public class ThirdPartyDialog extends JDialog implements ItemListener,
														 ActionListener,
														 Relocalizable
	{
	private JLabel						m_Message;	

	private JPanel						m_SponsorPanel;
	private TitledBorder				m_SponsorBorder;
	private JComboBox					m_ThirdPartySponsor;
		
	private JPanel						m_SwitchPanel;
	private TitledBorder				m_SwitchBorder;
	private JButton						m_SwitchButton;
	private JProgressBar				m_SwitchProgress;
	
	private SwingWorker  				m_BatchSwitcher;
	private JButton						m_CancelButton;
		
	private boolean						m_Busy;
	private boolean						m_Aborted;
	private boolean						m_Failure;
	private boolean 					m_Canceled;

	private Collection <InvoiceStub>	m_InvoiceStubs;
	private Collection <InvoiceStub>	m_SwitchedInvoiceStubs;
	
	private static Logger m_Logger = new Logger (ThirdPartyDialog.class);
	
//---------------------------------------------------------------------------
//***************************************************************************
//* Constants	                                                            *
//***************************************************************************
//---------------------------------------------------------------------------

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private final static int	   c_IconTextGap   = 10;

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

	private final static String c_Columns			= 	"3dlu,75dlu," +
  														"3dlu,75dlu,3dlu";

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

	private final static String c_SponsorColumns 	= 	"3dlu,140dlu,3dlu";

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

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

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

	//=======================================================================
	//= I18N Strings
	//=======================================================================

	private final static String c_Title					= "ThirdPartyDialog.Title";
	
	private final static String c_Message				= "ThirdPartyDialog.Message";
	private final static String c_SponsorBorder			= "ThirdPartyDialog.InsuranceBorder";
	
	private final static String c_SwitchBorder			= "ThirdPartyDialog.SwitchBorder";
	private final static String c_SwitchButton			= "ThirdPartyDialog.SwitchButton";
	private final static String c_SwitchProgressIdle	= "ThirdPartyDialog.SwitchProgressIdle";
	private final static String c_SwitchProgressDone	= "ThirdPartyDialog.SwitchProgressDone";
	private final static String c_SwitchProgressAbort	= "ThirdPartyDialog.SwitchProgressAbort";
	private final static String c_SwitchProgressFailed	= "ThirdPartyDialog.SwitchProgressFailed";

//---------------------------------------------------------------------------
//***************************************************************************
//* Constructor	                                                            *
//***************************************************************************
//---------------------------------------------------------------------------

public ThirdPartyDialog ()
	{
	super (MainFrame.getInstance(),Translatrix.getTranslationString(c_Title),true);
	
	CellConstraints	l_Constraints;
	FormLayout		l_Layout;	
	
	this.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
	
	l_Constraints  = new CellConstraints();
		
	this.buildSponsorPanel();
	this.buildSwitchPanel();
	
	m_CancelButton = new JButton ();
	m_CancelButton.setIcon(GECAMedModule.getSmallIcon(GECAMedIconNames.CANCEL));
	m_CancelButton.setText(Translatrix.getTranslationString("core.cancel"));
	m_CancelButton.addActionListener(this);
	
	l_Constraints  	= new CellConstraints();
	l_Layout		= new FormLayout(c_Columns, c_Rows);

	this.setLayout(l_Layout);

	this.add (m_SponsorPanel,	l_Constraints.xywh(2, 2, 3, 1));
	this.add (m_SwitchPanel,	l_Constraints.xywh(2, 4, 3, 1));
	this.add (m_CancelButton, 	l_Constraints.xywh(4, 6, 1, 1));
	
	this.getContentPane().setBackground(GECAMedColors.c_GECAMedBackground);
	this.relocalize();
	
	m_Busy = false;
	}
	
//---------------------------------------------------------------------------
//***************************************************************************
//* Primitives		                                                        *
//***************************************************************************
//---------------------------------------------------------------------------

private void updateMessage ()
	{
	int			l_InvoiceCount;
	String []	l_Filler;
	
	
	if (m_Message == null) return;
	
	l_InvoiceCount = (m_InvoiceStubs != null)?m_InvoiceStubs.size():0;
	
	l_Filler = new String [1];
	l_Filler [0] = Integer.valueOf(l_InvoiceCount).toString();
	
	m_Message.setText (Translatrix.getTranslationString(c_Message,l_Filler));
	}

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

private void buildSponsorPanel ()
	{
	CellConstraints	l_Constraints;
	FormLayout		l_Layout;	
	
	l_Layout = new FormLayout(c_SponsorColumns, c_SponsorRows);	
	l_Constraints  = new CellConstraints();
	
	m_SponsorBorder = new TitledBorder (Translatrix.getTranslationString(c_SponsorBorder));
	
	m_SponsorPanel = new JPanel ();
	m_SponsorPanel.setOpaque(false);
	m_SponsorPanel.setLayout(l_Layout);
	m_SponsorPanel.setBorder(m_SponsorBorder);
	
	m_Message = new JLabel ();
	m_Message.setText (Translatrix.getTranslationString(c_Message));

	m_ThirdPartySponsor = new JComboBox ();
	m_ThirdPartySponsor.addItemListener(this);
	
	m_SponsorPanel.add (m_Message, 		 	 l_Constraints.xywh(2, 2, 1, 1));
	m_SponsorPanel.add (m_ThirdPartySponsor, l_Constraints.xywh(2, 4, 1, 1));
	}

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

private void buildSwitchPanel ()
	{
	CellConstraints	l_Constraints;
	FormLayout		l_Layout;	
	
	l_Layout = new FormLayout(c_SwitchColumns, c_SwitchRows);	
	l_Constraints  = new CellConstraints();
	
	m_SwitchBorder = new TitledBorder (Translatrix.getTranslationString(c_SwitchBorder));
	
	m_SwitchPanel = new JPanel ();
	m_SwitchPanel.setOpaque(false);
	m_SwitchPanel.setLayout(l_Layout);
	m_SwitchPanel.setBorder(m_SwitchBorder);
	
    m_SwitchButton = new JButton ();
    m_SwitchButton.setIcon(BillingModule.getIconResource("rmndr_thirdparty.png"));
    m_SwitchButton.setText(Translatrix.getTranslationString(c_SwitchButton));
    m_SwitchButton.setIconTextGap(c_IconTextGap);
    m_SwitchButton.addActionListener(this);
    m_SwitchButton.setEnabled(false);
    
	m_SwitchProgress = new JProgressBar ();
	m_SwitchProgress.setMinimum(0);
	m_SwitchProgress.setValue(0);
	m_SwitchProgress.setStringPainted(true);
	m_SwitchProgress.setString (Translatrix.getTranslationString(c_SwitchProgressIdle));

	m_SwitchPanel.add (m_SwitchButton,    l_Constraints.xywh(2, 2, 1, 1));
	m_SwitchPanel.add (m_SwitchProgress,   l_Constraints.xywh(2, 4, 1, 1));
	}

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

private Invoice switchToThirdParty (Invoice p_Invoice, Insurance p_ThirdParty)
	{
	m_Logger.log (Level.INFO,"Setting Third Party Payer for invoice " + p_Invoice.formatInvoiceNumber(false, true) + " to " + p_ThirdParty.getAcronym());

	p_Invoice.setThirdPartyPayer (p_ThirdParty);	
	
	return p_Invoice;
	}

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

Object BatchSwitcher ()
	{
	this.batchSwitchThirdParty();
	return "";
	}

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

private synchronized void batchSwitchThirdParty ()
	{
	InvoiceStubUtils		l_InvoiceStubUtils;
	Insurance				l_ThirdPartyPayer;
	
	Iterator <InvoiceStub>	l_InvoiceStubIterator;
	InvoiceStub				l_InvoiceStub;
	Invoice					l_Invoice;
	
	int						l_InvoiceCount	= 0;
	int						l_SwitchCount	= 0;
	
	if ((m_InvoiceStubs == null) || (m_InvoiceStubs.size() == 0)) return;
	
	l_ThirdPartyPayer = (Insurance) m_ThirdPartySponsor.getSelectedItem();
	
	l_InvoiceStubUtils = new InvoiceStubUtils ();
	l_InvoiceCount     = m_InvoiceStubs.size();
	
	m_SwitchedInvoiceStubs = new LinkedHashSet <InvoiceStub> (); 
	l_SwitchCount         = 0;
	
	m_SwitchProgress.setMinimum (0);
	m_SwitchProgress.setMaximum (l_InvoiceCount);
	m_SwitchProgress.setValue	(0);
	
	m_Failure = false;
	
	try	{
		l_InvoiceStubIterator = m_InvoiceStubs.iterator();
		while (l_InvoiceStubIterator.hasNext() && !m_Aborted)
			{
			l_InvoiceStub = l_InvoiceStubIterator.next();
			l_Invoice = l_InvoiceStubUtils.fetchInvoiceForStub(l_InvoiceStub,false);
			if (l_Invoice != null)
				{
				m_SwitchProgress.setString (l_Invoice.formatInvoiceNumber(Invoice.c_LongFormat, true));
				m_SwitchProgress.setValue  (l_SwitchCount + 1);

				l_Invoice = this.switchToThirdParty (l_Invoice, l_ThirdPartyPayer);
				l_Invoice = l_InvoiceStubUtils.saveInvoice(l_Invoice);
				
				m_SwitchedInvoiceStubs.add(l_InvoiceStub);
				}
			l_SwitchCount++;
			}
		}
	catch (Exception p_Exception)
		{
		m_Failure = true;
		m_Logger.log (Level.ERROR,"Failed to switch invoices to third party!",p_Exception);
		}
	
	if (m_Aborted)
		{
		m_SwitchProgress.setString (Translatrix.getTranslationString(c_SwitchProgressAbort));	
		}
	else if (m_Failure)
		{
		m_SwitchProgress.setString (Translatrix.getTranslationString(c_SwitchProgressFailed));	
		}
	else
		{
		m_SwitchProgress.setString (Translatrix.getTranslationString(c_SwitchProgressDone));
		this.setVisible (false);
		}
	}

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

private void startBatchSwitching ()
	{
	m_BatchSwitcher = new SwingWorker() 
	{
	public Object construct() 
		{
		return BatchSwitcher ();
		}
	public void start ()
		{
		m_Aborted = false;
		m_Busy    = true;
		super.start();
		}
	public void finished ()
		{
		m_Busy 	  = false;
		}
	public void interrupt ()
		{
		m_Busy 	  = false;
		m_Aborted = true;
		super.interrupt();
		}
	};

	m_BatchSwitcher.start ();  	
	}

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

private void abortBatchSwitching ()
	{
	if (m_BatchSwitcher != null && m_Busy) m_BatchSwitcher.interrupt();
	}

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

public void setInsurances (Collection <Insurance> p_Insurances)
	{
	Iterator <Insurance> l_InsuranceIterator;
	Insurance			 l_Insurance;
	
	if (p_Insurances == null) return;
	
	m_ThirdPartySponsor.removeAllItems();
	
	l_InsuranceIterator = p_Insurances.iterator();
	while (l_InsuranceIterator.hasNext())
		{
		l_Insurance = l_InsuranceIterator.next();
		if (l_Insurance.getThirdParty()) m_ThirdPartySponsor.addItem (l_Insurance);
		}
	}

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

public void setInvoiceStubs (Collection <InvoiceStub> p_InvoiceStubs)
	{
	m_InvoiceStubs = p_InvoiceStubs;
	this.updateMessage();
	}

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

public boolean wasAborted ()
	{
	return m_Aborted;
	}

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

public boolean hasFailed ()
	{
	return m_Failure;
	}

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

public Collection <InvoiceStub> getSwitchedInvoiceStubs ()
	{
	return m_SwitchedInvoiceStubs;
	}

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

public Insurance getThirdPartySponsor ()
	{
	return (Insurance) m_ThirdPartySponsor.getSelectedItem();
	}

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

public void itemStateChanged(ItemEvent p_Event) 
	{
	Insurance	l_SelectItem;
	
	if (p_Event.getSource().equals(m_ThirdPartySponsor))
		{
		l_SelectItem = (Insurance) m_ThirdPartySponsor.getSelectedItem();
		m_SwitchButton.setEnabled(l_SelectItem.getId() > 0);
		}
	}

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

public void actionPerformed(ActionEvent p_Event) 
	{
	if (p_Event.getSource().equals(m_SwitchButton))
	{
	this.startBatchSwitching();
	}
else if (p_Event.getSource().equals(m_CancelButton))
	{
	this.abortBatchSwitching();
	this.m_Canceled = true;
	this.setVisible(false);
	}
	}

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

public void relocalize() 
	{
	this.setTitle(Translatrix.getTranslationString(c_Title));
	
	if (m_SponsorBorder != null)
		m_SponsorBorder.setTitle (Translatrix.getTranslationString(c_SponsorBorder));

	if (m_Message != null)
		m_Message.setText (Translatrix.getTranslationString(c_Message));

	if (m_SwitchBorder != null)
		m_SwitchBorder.setTitle (Translatrix.getTranslationString(c_SwitchBorder));

	if (m_SwitchButton != null)
		m_SwitchButton.setText(Translatrix.getTranslationString(c_SwitchButton));
	 
	if (m_SwitchProgress != null)
		m_SwitchProgress.setString (Translatrix.getTranslationString(c_SwitchProgressIdle));
		
	if (m_CancelButton != null)
		m_CancelButton.setText(Translatrix.getTranslationString("core.cancel"));
	}

public boolean canceled()
	{
	return m_Canceled;
	}


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

	}
