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

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Iterator;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.ScrollPaneConstants;
import javax.swing.border.TitledBorder;

import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Account;
import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Settlement;
import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Statement;
import lu.tudor.santec.gecamed.billing.ejb.session.beans.SettlementBean;
import lu.tudor.santec.gecamed.billing.ejb.session.interfaces.SettlementInterface;
import lu.tudor.santec.gecamed.billing.gui.BillingModule;
import lu.tudor.santec.gecamed.core.gui.GECAMedColors;
import lu.tudor.santec.gecamed.core.gui.GECAMedIconNames;
import lu.tudor.santec.gecamed.core.gui.GECAMedLists;
import lu.tudor.santec.gecamed.core.gui.GECAMedModule;
import lu.tudor.santec.gecamed.core.gui.MainFrame;
import lu.tudor.santec.gecamed.core.gui.utils.GECAMedGuiUtils;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.office.ejb.entity.beans.Physician;
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 org.apache.log4j.Logger;

import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.toedter.calendar.JDateChooser;

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

public class StatementDialog extends JDialog implements ActionListener,
														PropertyChangeListener,
													    ItemListener,
													    ComponentListener,
													    Relocalizable
{
	private static final long serialVersionUID = 1L;
	
	private JPanel					m_InsurancePanel;
	private TitledBorder			m_InsuranceBorder;
	private JList					m_InsuranceList;
	private InsuranceListModel		m_Insurances;
	
	private JPanel					m_PhysicianPanel;
	private TitledBorder			m_PhysicianBorder;
	private JCheckBox				m_AllPhysicians;	
	private JList					m_PhysicianList;
	private PhysicianListModel		m_Physicians;
	
	private JPanel					m_PeriodPanel;
	private TitledBorder			m_PeriodBorder;
	private JLabel					m_StartDateLabel;
	private JLabel					m_EndDateLabel;
	private JDateChooser			m_StartDate;
	private JDateChooser			m_EndDate;

	private JPanel					m_SettlementPanel;
	private TitledBorder			m_SettlementBorder;
	private JLabel					m_AccountLabel;
	private JLabel					m_SettlementDateLabel;
	private JComboBox				m_AccountChooser;
	private JDateChooser			m_SettlementDate;
	
	private JButton					m_OkayButton;
	private JButton					m_CancelButton;

	private int[]					m_Selection;
	private boolean					m_Accepted;
	
	private static Logger m_Logger = Logger.getLogger ("gecamed.billing.gui.statement.StatementDialog");

//***************************************************************************
//* Class Constants                                                         *
//***************************************************************************
		
	private static final Date c_Epoch = new Date (0);
	   
	private final static Dimension c_PreferredSize = new Dimension (550,300);
	
	//=======================================================================
	//= Layout Strings
	//=======================================================================

	private final static String c_Columns	= 	"3dlu,fill:max(50dlu;pref):grow," +
												"3dlu,fill:max(50dlu;pref):grow," +
												"3dlu,fill:max(75dlu;pref):grow,3dlu";
		
	private final static String c_Rows		=   "3dlu,fill:pref:grow," +
												"3dlu,fill:pref," +
												"3dlu,fill:pref,3dlu";

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

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

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

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

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

	private final static String c_PeriodRows 		= "3dlu,fill:pref," +
													  "3dlu,fill:pref," +
													  "3dlu,fill:pref," +
													  "3dlu,fill:pref,3dlu:grow";
	
	private final static String c_AccountColumns 	= "3dlu,fill:pref," +
													  "3dlu,fill:max(75dlu;pref)," +
													  "3dlu,fill:pref:grow,3dlu";

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

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

	private final static String c_Title					= "StatementDialog.Title";
	private final static String c_TitleNew				= "StatementDialog.TitleNew";
	private final static String c_InsuranceBorder		= "StatementDialog.InsuranceBorder";
	private final static String c_PhysicianBorder		= "StatementDialog.PhysicianBorder";
	private final static String c_AllPhysicians			= "StatementDialog.AllPhysicians";
	private final static String c_PeriodBorder			= "StatementDialog.PeriodBorder";
	private final static String c_StartDateLabel		= "StatementDialog.StartDateLabel";
	private final static String c_EndDateLabel			= "StatementDialog.EndDateLabel";
	private final static String c_SettlementBorder		= "StatementDialog.SettlementBorder";
	private final static String c_AccountLabel			= "StatementDialog.AccountLabel";
	private final static String c_SettlementDateLabel	= "StatementDialog.SettlementDateLabel";
	
//***************************************************************************
//* Constructor                                                             *
//***************************************************************************
	
public StatementDialog ()	
	{	
	super (MainFrame.getInstance(),Translatrix.getTranslationString(c_TitleNew),true);
	
	CellConstraints	l_Constraints;
	FormLayout		l_Layout;	
	JScrollPane		l_InsuranceScroller;
	JScrollPane		l_PhysicianScroller;
	
	this.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
	
	l_Constraints  = new CellConstraints();
	
	//=======================================================================
	//= Assemble Insurance Panel
	//=======================================================================
	
	l_Layout = new FormLayout(c_InsuranceColumns, c_InsuranceRows);
	m_InsuranceBorder = new TitledBorder (Translatrix.getTranslationString(c_InsuranceBorder));
	
	m_InsurancePanel = new JPanel ();
	m_InsurancePanel.setOpaque(false);
	m_InsurancePanel.setLayout(l_Layout);
	m_InsurancePanel.setBorder(m_InsuranceBorder);
	
	m_Insurances    = new InsuranceListModel ();
	
	m_InsuranceList = new JList (m_Insurances);
	m_InsuranceList.setSelectionMode (ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
	m_InsuranceList.setLayoutOrientation(JList.VERTICAL);
	m_InsuranceList.setVisibleRowCount(-1);
	
	l_InsuranceScroller = new JScrollPane (m_InsuranceList);
	l_InsuranceScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
	
	m_InsurancePanel.add (l_InsuranceScroller, l_Constraints.xywh( 2, 2, 1, 1));
		
	//=======================================================================
	//= Assemble Physician Panel
	//=======================================================================
	
	l_Layout = new FormLayout(c_PhysicianColumns, c_PhysicianRows);
	m_PhysicianBorder = new TitledBorder (Translatrix.getTranslationString(c_PhysicianBorder));

	m_PhysicianPanel = new JPanel ();
	m_PhysicianPanel.setOpaque(false);
	m_PhysicianPanel.setLayout(l_Layout);
	m_PhysicianPanel.setBorder(m_PhysicianBorder);
	
	m_AllPhysicians = new JCheckBox ();
	m_AllPhysicians.setOpaque(false);
	m_AllPhysicians.setSelected(true);
	m_AllPhysicians.addItemListener(this);
	
	m_Physicians = new PhysicianListModel ();
	
	m_PhysicianList = new JList (m_Physicians);
	m_PhysicianList.setSelectionMode (ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
	m_PhysicianList.setLayoutOrientation(JList.VERTICAL);
	m_PhysicianList.setVisibleRowCount(-1);
	m_PhysicianList.setEnabled(false);
	
	l_PhysicianScroller = new JScrollPane (m_PhysicianList);
	l_PhysicianScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

	m_PhysicianPanel.add (m_AllPhysicians,  	l_Constraints.xywh(2, 2, 1, 1));
	m_PhysicianPanel.add (l_PhysicianScroller,  l_Constraints.xywh(2, 4, 1, 1));
	
	//=======================================================================
	//= Assemble Period Panel
	//=======================================================================
	
	l_Layout = new FormLayout(c_PeriodColumns, c_PeriodRows);
	m_PeriodBorder = new TitledBorder (Translatrix.getTranslationString(c_PeriodBorder));
	
	m_PeriodPanel = new JPanel ();
	m_PeriodPanel.setOpaque(false);
	m_PeriodPanel.setLayout(l_Layout);
	m_PeriodPanel.setBorder(m_PeriodBorder);

	m_StartDateLabel = new JLabel ();
	m_EndDateLabel	 = new JLabel ();
	
	m_StartDate		 = GECAMedGuiUtils.getDateChooser(false);
	m_StartDate.setDate(new Date());
	m_StartDate.addPropertyChangeListener(this);
	
	m_EndDate		 = GECAMedGuiUtils.getDateChooser(false);
	m_EndDate.setDate(null);
	
	m_PeriodPanel.add (m_StartDateLabel,  l_Constraints.xywh(2, 2, 1, 1));
	m_PeriodPanel.add (m_StartDate,       l_Constraints.xywh(2, 4, 1, 1));
	m_PeriodPanel.add (m_EndDateLabel,    l_Constraints.xywh(2, 6, 1, 1));
	m_PeriodPanel.add (m_EndDate,         l_Constraints.xywh(2, 8, 1, 1));
	
	//=======================================================================
	//= Assemble Account Panel
	//=======================================================================
	
	l_Layout = new FormLayout(c_AccountColumns, c_AccountRows);
	m_SettlementBorder = new TitledBorder (Translatrix.getTranslationString(c_SettlementBorder));
	
	m_SettlementPanel = new JPanel ();
	m_SettlementPanel.setOpaque(false);
	m_SettlementPanel.setLayout(l_Layout);
	m_SettlementPanel.setBorder(m_SettlementBorder);
	
	m_AccountLabel = new JLabel ();
	m_SettlementDateLabel = new JLabel ();
	
	m_AccountChooser = new JComboBox ();
	
	m_SettlementDate = GECAMedGuiUtils.getDateChooser(false);
	
	m_SettlementPanel.add (m_AccountLabel,    		l_Constraints.xywh(2, 2, 1, 1));
	m_SettlementPanel.add (m_AccountChooser,  		l_Constraints.xywh(4, 2, 3, 1));
	m_SettlementPanel.add (m_SettlementDateLabel,   l_Constraints.xywh(2, 4, 1, 1));
	m_SettlementPanel.add (m_SettlementDate,  		l_Constraints.xywh(4, 4, 1, 1));
	
	//=======================================================================
	//= Assemble Main Panel
	//=======================================================================
	
	this.getContentPane().setBackground(GECAMedColors.c_GECAMedBackground);
	this.relocalize();

	l_Layout = new FormLayout(c_Columns, c_Rows);
	this.setLayout (l_Layout);
	
	m_OkayButton    = new JButton ();
	m_OkayButton.setIcon(GECAMedModule.getSmallIcon(GECAMedIconNames.OK));
	m_OkayButton.addActionListener(this);
	
	m_CancelButton    = new JButton ();
	m_CancelButton.setIcon(GECAMedModule.getSmallIcon(GECAMedIconNames.CANCEL));
	m_CancelButton.addActionListener(this);

	this.add (m_InsurancePanel,  	l_Constraints.xywh(2, 2, 1, 1));
	this.add (m_PhysicianPanel,  	l_Constraints.xywh(4, 2, 1, 1));
	this.add (m_PeriodPanel,  		l_Constraints.xywh(6, 2, 1, 1));
	this.add (m_SettlementPanel,  	l_Constraints.xywh(2, 4, 5, 1));
	this.add (m_OkayButton,  		l_Constraints.xywh(4, 6, 1, 1));
	this.add (m_CancelButton,  		l_Constraints.xywh(6, 6, 1, 1));
	
	this.populateThirdPartyPayers();
	this.populatePhysicians();
	this.populateAccountChooser();

	this.setSize(c_PreferredSize);
	this.addComponentListener (this);
	}

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

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

private SettlementInterface getSettlementInterface ()
	{
	SettlementInterface l_SettlementInterface = null;

	try {
		l_SettlementInterface = (SettlementInterface) ManagerFactory.getRemote(SettlementBean.class);
//		InitialContext l_Context = new InitialContext();
//		l_SettlementInterface = (SettlementInterface) l_Context.lookup("SettlementBean/remote");
//		l_Context.close();
		} 
	catch (Exception p_Exception) 
		{
		m_Logger.log(Level.ERROR, "Failed to get Settlement Interface!", p_Exception);
		}

	return l_SettlementInterface;
	}

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

private void populateThirdPartyPayers ()
	{
	Collection <Insurance>  l_Insurances;
	Collection <Insurance>  l_ThirdPartyPayers = null;
	Iterator <Insurance>	l_InsuranceIterator;
	Insurance				l_Insurance;
	
	l_Insurances = BillingModule.getInstance().getHealthInsurances();
	if (l_Insurances == null) return;
	
	l_ThirdPartyPayers = new ArrayList <Insurance> ();
	
	l_InsuranceIterator = l_Insurances.iterator();
	while (l_InsuranceIterator.hasNext())
		{	
		l_Insurance = l_InsuranceIterator.next();
		if (l_Insurance.getId() == 0) continue;
		
		if (l_Insurance.getThirdParty()) l_ThirdPartyPayers.add(l_Insurance);
		}
	
	m_Insurances.setInsurances(l_ThirdPartyPayers);
	}

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

private void populatePhysicians ()
	{
	m_Physicians.setPhysicians(GECAMedLists.getListCopy(Physician.class));
	}

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

private void populateAccountChooser ()
	{
	SettlementInterface  	l_SettlementInterface;
	Collection <Settlement>	l_Settlements;
	Iterator <Settlement>	l_SettlementIterator;
	Settlement				l_Settlement;
	Account					l_Account;
	
	l_SettlementInterface = this.getSettlementInterface();
	if (l_SettlementInterface != null)
		{
		try	{
			l_Settlements = l_SettlementInterface.getTransferSettlements();
			if (l_Settlements != null)
				{
				l_SettlementIterator = l_Settlements.iterator();
				while (l_SettlementIterator.hasNext())
					{
					l_Settlement = l_SettlementIterator.next();
					l_Account    = l_Settlement.getTransferAccount();
					if (l_Account != null) m_AccountChooser.addItem	(l_Account);		
					}	
				}
			}
		catch (Exception p_Exception)
			{
			m_Logger.log(Level.WARN, "Failed to fetch Accounts!", p_Exception);
			}
		}
	}

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

public void setSelection (boolean p_SelectIt)
	{
	if ((m_PhysicianList != null) && (m_Selection != null))
		{
		if (p_SelectIt) m_PhysicianList.setSelectedIndices(m_Selection);
				   else m_PhysicianList.clearSelection();
		}
	}

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

private boolean checkValidity (boolean p_NotifyUser)
	{
	Collection <Insurance> l_ThirdPartyPayers;
	Collection <Physician> l_Physicians;
	
	l_ThirdPartyPayers = this.getThirdPartyPayers();
	if ((l_ThirdPartyPayers == null) || (l_ThirdPartyPayers.size() == 0))
		{
		if (p_NotifyUser) BillingModule.notifyUser("StatementDialog.NoThirdPartyPayersTitle", 
												   "StatementDialog.NoThirdPartyPayersMessage", null);
		return false;
		
		}
	
	l_Physicians = this.getPhysicians();
	if (this.getAllPhysicians() == false)
		{
		l_Physicians = this.getPhysicians();
		if ((l_Physicians == null) || (l_Physicians.size() == 0))
			{
			if (p_NotifyUser) BillingModule.notifyUser("StatementDialog.NoPhysiciansTitle", 
													   "StatementDialog.NoPhysiciansMessage", null);
			return false;			
			}
		}
	
	if (this.getStartDate() == null)
		{
		if (p_NotifyUser) BillingModule.notifyUser("StatementDialog.NoStartDateTitle", 
			   								   	   "StatementDialog.NoStartDateMessage", null);
		return false;
		}
	
	if (this.getEndDate() == null)
		{
		if (p_NotifyUser) BillingModule.notifyUser("StatementDialog.NoEndDateTitle", 
			   								   	   "StatementDialog.NoEndDateMessage", null);
		return false;
		}
	
	return true;
	}

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

public Date earliestOfDay (Date p_Date)
	{
	GregorianCalendar	l_Earliest;
		
	l_Earliest = new GregorianCalendar();
	l_Earliest.setTime (p_Date);
	l_Earliest.set (Calendar.HOUR_OF_DAY,0);
	l_Earliest.set (Calendar.MINUTE,0);
	l_Earliest.set (Calendar.SECOND,0);
	l_Earliest.set (Calendar.MILLISECOND,0);
	
	return l_Earliest.getTime();
	}

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

public Date latestOfDay (Date p_Date)
	{
	GregorianCalendar	l_Latest;
		
	l_Latest = new GregorianCalendar();
	l_Latest.setTime (p_Date);
	l_Latest.set (Calendar.HOUR_OF_DAY,23);
	l_Latest.set (Calendar.MINUTE,59);
	l_Latest.set (Calendar.SECOND,59);
	l_Latest.set (Calendar.MILLISECOND,999);
	
	return l_Latest.getTime();
	}

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

public void actionPerformed (ActionEvent p_ActionEvent) 
	{
	if (p_ActionEvent.getSource() == m_CancelButton)
		{
		m_Accepted = false;
		this.setVisible (false);
		}
	else if (p_ActionEvent.getSource() == m_OkayButton)
		{
		m_Accepted = this.checkValidity(true);
		
		if (m_Accepted == true) this.setVisible (false);
		}
	}

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

public void relocalize() 
	{
	this.setTitle(Translatrix.getTranslationString(c_Title));

	if (m_InsuranceBorder != null)
		m_InsuranceBorder.setTitle (Translatrix.getTranslationString(c_InsuranceBorder));
	
	if (m_PhysicianBorder != null)
		m_PhysicianBorder.setTitle (Translatrix.getTranslationString(c_PhysicianBorder));

	if (m_AllPhysicians != null)
		m_AllPhysicians.setText (Translatrix.getTranslationString(c_AllPhysicians));
	
	if (m_PeriodBorder != null)
		m_PeriodBorder.setTitle (Translatrix.getTranslationString(c_PeriodBorder));

	if (m_StartDateLabel != null)
		m_StartDateLabel.setText (Translatrix.getTranslationString(c_StartDateLabel));
	
//	if (m_StartDate != null) 
//		{
//		m_StartDate.setLocale (Translatrix.getLocale());
//		m_StartDate.setDateFormatString("d MMMM yyyy");   
//		m_StartDate.getDateEditor().setLocale (Translatrix.getLocale());
//		}
	
	if (m_EndDateLabel != null)
		m_EndDateLabel.setText (Translatrix.getTranslationString(c_EndDateLabel));
	
//	if (m_EndDate != null) 
//		{
//		m_EndDate.setLocale (Translatrix.getLocale());
//		m_EndDate.setDateFormatString("d MMMM yyyy");   
//		m_EndDate.getDateEditor().setLocale (Translatrix.getLocale());
//		}

	if (m_SettlementBorder != null)
		m_SettlementBorder.setTitle (Translatrix.getTranslationString(c_SettlementBorder));

	if (m_AccountLabel != null)
		m_AccountLabel.setText (Translatrix.getTranslationString(c_AccountLabel));

	if (m_SettlementDateLabel != null)
		m_SettlementDateLabel.setText (Translatrix.getTranslationString(c_SettlementDateLabel));
	
	if (m_SettlementDate != null)
		{
		m_SettlementDate.setLocale (Translatrix.getLocale());
		m_SettlementDate.setDateFormatString("d MMMM yyyy");   
		m_SettlementDate.getDateEditor().setLocale (Translatrix.getLocale());
		}
	
	if (m_OkayButton != null)
		m_OkayButton.setText (Translatrix.getTranslationString("core.ok"));
	
	if (m_CancelButton != null)
		m_CancelButton.setText(Translatrix.getTranslationString("core.cancel"));
	}



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

public void itemStateChanged(ItemEvent p_ItemEvent) 
	{
	Object	l_Source;
	
	l_Source = p_ItemEvent.getItemSelectable();
	if (l_Source == m_AllPhysicians)
		{
		if (p_ItemEvent.getStateChange() == ItemEvent.DESELECTED)
			{
			m_PhysicianList.setEnabled(true);
			this.setSelection(true);
			}
		else if (p_ItemEvent.getStateChange() == ItemEvent.SELECTED)
			{
			m_PhysicianList.setEnabled(false);
			m_Selection = m_PhysicianList.getSelectedIndices();
			this.setSelection(false);
			}
		}
	}

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

public void componentHidden (ComponentEvent p_Event) 
	{
	}

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

public void componentMoved (ComponentEvent p_Event) 
	{
	}

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

public void componentResized (ComponentEvent p_Event) 
	{
	this.removeComponentListener(this);
	this.setSize( Math.max (this.getSize().width, c_PreferredSize.width), 
				  Math.max (this.getSize().height, c_PreferredSize.height) );
	this.addComponentListener(this);   
	}

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

public void componentShown (ComponentEvent p_Event) 
	{
	}

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

public void propertyChange(PropertyChangeEvent p_Event) 
	{
	Date				l_StartDate;
	Date				l_EndDate;
	
	if (   (p_Event.getSource() == m_StartDate)
		&& ("date".equals(p_Event.getPropertyName()))) 
		{
		l_StartDate = m_StartDate.getDate();
		l_EndDate   = m_EndDate.getDate();
		
		if (l_StartDate == null) return;
		
		if ((l_EndDate == null) || (l_StartDate.after (l_EndDate))) 
			{
			l_EndDate = BillingModule.lastOfMonth(l_StartDate);
			m_EndDate.setDate (l_EndDate);
			}
		}
	}
//---------------------------------------------------------------------------

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

public void setStatement (Statement p_Statement)
	{
	if (p_Statement == null) return;
	
	if (p_Statement.isPersistent())
		{
		this.setTitle(Translatrix.getTranslationString(c_Title) + " " + p_Statement.formatStatementNumber());
		this.setThirdPartyPayers(p_Statement.getThirdPartyPayers());
		this.setAllPhysicians(p_Statement.getAllPhysicians());
		this.setPhysicians (p_Statement.getPhysicians());
		this.setStartDate(p_Statement.getStartDate());
		this.setEndDate(p_Statement.getEndDate());
		this.setSettlementAccount(p_Statement.getAccount());
		this.setSettlementDate(p_Statement.getSettlementDate());
		}
	else
		{
		this.setTitle(Translatrix.getTranslationString(c_TitleNew));
		this.resetThirdPartyPayers ();
		this.resetAllPhysicians();
		this.resetPhysicians();
		this.resetStartDate ();
		this.resetEndDate ();
		this.resetSettlementAccount();
		this.resetSettlementDate();
		}
	}

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

public boolean updateStatement (Statement p_Statement)
	{
	boolean l_StatementModified = false;
	
	if (p_Statement == null) return false;
	
	//-- Third Party Payers --------------------------------------------------
	
	if (!this.getThirdPartyPayers().equals (p_Statement.getThirdPartyPayers()))
		{
		p_Statement.setThirdPartyPayers (new HashSet <Insurance> (this.getThirdPartyPayers()));
		l_StatementModified = true;
		}
	
	//-- Physicians ----------------------------------------------------------
	
	if (!this.getPhysicians().equals (p_Statement.getPhysicians()))
		{
		p_Statement.setPhysicians (new HashSet <Physician> (this.getPhysicians()));
		l_StatementModified = true;
		}
	
	//-- All Physicians Flag -------------------------------------------------
	
	if (!this.getAllPhysicians().equals(p_Statement.getAllPhysicians()))
		{
		if (this.getAllPhysicians() == true) p_Statement.setPhysicians (new HashSet <Physician> ());
		p_Statement.setAllPhysicians(this.getAllPhysicians());
		l_StatementModified = true;
		}
	
	//-- Start Date ----------------------------------------------------------
	
	if (!this.getStartDate().equals (p_Statement.getStartDate()))
		{
		p_Statement.setStartDate (this.getStartDate());
		l_StatementModified = true;
		}
	
	//-- End Date ------------------------------------------------------------
	
	if (!this.getEndDate().equals (p_Statement.getEndDate()))
		{
		p_Statement.setEndDate (this.getEndDate());
		l_StatementModified = true;
		}
	
	//-- Settlement Account --------------------------------------------------
	
	if (!this.getSettlementAccount().equals (p_Statement.getAccount()))
		{
		p_Statement.setAccount (this.getSettlementAccount());
		l_StatementModified = true;
		}
	
	//-- Settlement Date -----------------------------------------------------
	
	if (!this.getSettlementDate().equals (p_Statement.getSettlementDate()))
		{
		if (this.getSettlementDate().equals(c_Epoch))
			 p_Statement.setSettlementDate (null);
		else p_Statement.setSettlementDate (this.getSettlementDate());
		l_StatementModified = true;
		}
	
	return l_StatementModified;
	}

//---------------------------------------------------------------------------
//===========================================================================
//= Third Party Payer Accessors
//===========================================================================
//---------------------------------------------------------------------------

public void setThirdPartyPayers (Collection <Insurance> p_ThirdPartyPayers)
	{
	Iterator <Insurance> l_InsuranceIterator;
	Insurance			 l_ThirdPartyPayer;
	int					 l_Position;
	int					 l_Index;
	int[]				 l_Selection;
	
	
	if (p_ThirdPartyPayers != null)
		{
		m_InsuranceList.clearSelection();

		l_Index = 0;
		l_Selection = new int[p_ThirdPartyPayers.size()];

		l_InsuranceIterator = p_ThirdPartyPayers.iterator();
		while (l_InsuranceIterator.hasNext())
			{
			l_ThirdPartyPayer = l_InsuranceIterator.next();
			l_Position = m_Insurances.getElementPosition(l_ThirdPartyPayer);
			if (l_Position >= 0) l_Selection [l_Index++] = l_Position; 
			}
		
		m_InsuranceList.setSelectedIndices (l_Selection);
		}	
	}

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

public Collection <Insurance> getThirdPartyPayers ()
	{
	Collection <Insurance> l_ThirdPartyPayers;
	Insurance			   l_ThirdPartyPayer;
	int []				   l_Selection;
	int					   l_Index;
	
	l_ThirdPartyPayers = new HashSet <Insurance> ();
	
	l_Selection = m_InsuranceList.getSelectedIndices();
	if (l_Selection != null)
		{
		for (l_Index = 0; l_Index < l_Selection.length; l_Index++)
			{
			l_ThirdPartyPayer = m_Insurances.getElementAt(l_Selection[l_Index]);
			l_ThirdPartyPayers.add(l_ThirdPartyPayer);
			}
		}
		
	return l_ThirdPartyPayers;
	}

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

public void resetThirdPartyPayers ()
	{
	m_InsuranceList.clearSelection();
	}

//---------------------------------------------------------------------------
//===========================================================================
//= Physician Accessors
//===========================================================================
//---------------------------------------------------------------------------

public void setAllPhysicians (Boolean p_AllPhysicians)
	{
	m_AllPhysicians.setSelected(p_AllPhysicians);
	}

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

public Boolean getAllPhysicians ()
	{
	return m_AllPhysicians.isSelected();
	}

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

public void resetAllPhysicians ()
	{
	m_AllPhysicians.setSelected(true);
	}

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

public void setPhysicians (Collection <Physician> p_Physicians)
	{
	Iterator <Physician> l_PhysicianIterator;
	Physician			 l_Physician;
	int					 l_Position;
	int					 l_Index;
	int[]				 l_Selection;

	if (p_Physicians != null)
		{
		m_PhysicianList.clearSelection();
		
		l_Index = 0;
		l_Selection = new int[p_Physicians.size()];
		
		l_PhysicianIterator = p_Physicians.iterator();
		while (l_PhysicianIterator.hasNext())
			{
			l_Physician = l_PhysicianIterator.next();
			l_Position = m_Physicians.getElementPosition(l_Physician);
			if (l_Position >= 0) l_Selection [l_Index++] = l_Position;
			}
		m_PhysicianList.setSelectedIndices(l_Selection);
		}	
	}

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

public Collection <Physician> getPhysicians ()
	{
	Collection <Physician> l_Physicians;
	Physician			   l_Physician;
	int []				   l_Selection;
	int					   l_Index;
	
	if (m_AllPhysicians.isSelected())
		{
		l_Physicians = m_Physicians.getPhysicians();
		}
	else
		{
		l_Physicians = new HashSet <Physician> ();
	
		l_Selection = m_PhysicianList.getSelectedIndices();
		if (l_Selection != null)
			{
			for (l_Index = 0; l_Index < l_Selection.length; l_Index++)
				{
				l_Physician = m_Physicians.getElementAt(l_Selection[l_Index]);
				l_Physicians.add (l_Physician);
				}
			}
		}
		
	return l_Physicians;
	}

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

public void resetPhysicians ()
	{
	m_PhysicianList.clearSelection();
	}

//---------------------------------------------------------------------------
//===========================================================================
//= Start Date Accessors
//===========================================================================
//---------------------------------------------------------------------------

public void setStartDate (Date p_StartDate)
	{
	m_StartDate.setDate (p_StartDate);
	}

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

public Date getStartDate ()
	{
	if (m_StartDate.getDate() != null) 
		 return this.earliestOfDay(m_StartDate.getDate());
	else return new Date ();
	}

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

public void resetStartDate ()
	{
	m_StartDate.setDate (null);
	}

//---------------------------------------------------------------------------
//===========================================================================
//= End Date Accessors
//===========================================================================
//---------------------------------------------------------------------------

public void setEndDate (Date p_EndDate)
	{
	m_EndDate.setDate (p_EndDate);
	}

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

public Date getEndDate ()
	{
	if (m_EndDate.getDate() != null) 
		 return this.latestOfDay(m_EndDate.getDate());
	else return new Date ();
	}

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

public void resetEndDate ()
	{
	m_EndDate.setDate (null);
	}

//---------------------------------------------------------------------------
//===========================================================================
//= Settlement Account Accessors
//===========================================================================
//---------------------------------------------------------------------------

public Account getSettlementAccount ()
	{
	Account	l_SettlementAccount;

	l_SettlementAccount = (Account) m_AccountChooser.getSelectedItem();
	return l_SettlementAccount;
	}

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

public void setSettlementAccount (Account p_SettlementAccount)
	{
	if (p_SettlementAccount != null) 
		{
		m_AccountChooser.setSelectedItem (p_SettlementAccount);
		}
	else resetSettlementAccount ();
	}

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

public void resetSettlementAccount ()
	{
	if (m_AccountChooser.getItemCount() > 0) m_AccountChooser.setSelectedIndex(0);
	}

//---------------------------------------------------------------------------
//===========================================================================
//= Settlement Date Accessors
//===========================================================================
//---------------------------------------------------------------------------

public Date getSettlementDate ()
	{
	Date	l_SettlementDate;

	l_SettlementDate = (Date) m_SettlementDate.getDate();
	if (l_SettlementDate == null) l_SettlementDate = c_Epoch;
	
	return l_SettlementDate;
	}

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

public void setSettlementDate (Date p_SettlementDate)
	{
	if (p_SettlementDate != null) 
		{
		m_SettlementDate.setDate (p_SettlementDate);
		}
	else resetSettlementDate ();
	}

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

public void resetSettlementDate ()
	{
	m_SettlementDate.setDate(null);
	}

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

public boolean wasAccepted ()
	{
	return m_Accepted;
	}

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