/*******************************************************************************
 * 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.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Date;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
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.gui.BillingModule;
import lu.tudor.santec.gecamed.billing.gui.statement.PhysicianListModel;
import lu.tudor.santec.gecamed.billing.utils.BillingAdminSettings;
import lu.tudor.santec.gecamed.billing.utils.InvoiceWorkflow;
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.ComponentTitledPanel;
import lu.tudor.santec.gecamed.core.gui.widgets.FromUntilDatePanel;
import lu.tudor.santec.gecamed.core.utils.querybuilder.Group;
import lu.tudor.santec.gecamed.core.utils.querybuilder.HibernateCondition;
import lu.tudor.santec.gecamed.core.utils.querybuilder.HibernateList;
import lu.tudor.santec.gecamed.core.utils.querybuilder.HibernateOperator;
import lu.tudor.santec.gecamed.core.utils.querybuilder.WhereClause;
import lu.tudor.santec.gecamed.office.ejb.entity.beans.Physician;
import lu.tudor.santec.i18n.Relocalizable;
import lu.tudor.santec.i18n.Translatrix;

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

public class InvoiceListDialog extends JDialog implements ItemListener,
														  ActionListener,
														  Relocalizable
{
	private static final long serialVersionUID = 1L;
	
	private ComponentTitledPanel	m_PhysicianBorder;
	private JPanel					m_PhysicianPanel;
	private JCheckBox				m_SearchByPhysician;
	private PhysicianListModel		m_Physicians;
	private JList					m_PhysicianList;
	private JScrollPane				m_PhysicianScroller;
	
	private TitledBorder			m_PeriodBorder;
	private FromUntilDatePanel		m_PeriodPanel;

	private TitledBorder			m_OptionsBorder;
	private JPanel					m_OptionsPanel;
	private JCheckBox				m_IncludeOpenInvoices;
	private JCheckBox				m_IncludeThirdParty;
	private JCheckBox				m_OnlyTotals;

	private JButton					m_OkayButton;	
	private JButton					m_CancelButton;
	
	private WhereClause				m_WhereClause;
	private boolean					m_Validated;

    private static final Vector <Integer> m_OpenStates = new Vector <Integer> ();
    
    static 	{
    		m_OpenStates.add(Integer.valueOf(InvoiceWorkflow.c_NewState));
    		m_OpenStates.add(Integer.valueOf(InvoiceWorkflow.c_OpenState));
    		m_OpenStates.add(Integer.valueOf(InvoiceWorkflow.c_VerifiedState));
    		m_OpenStates.add(Integer.valueOf(InvoiceWorkflow.c_ClosedState));
    		}

	
//---------------------------------------------------------------------------
//***************************************************************************
//* Constants	                                                            *
//***************************************************************************
//---------------------------------------------------------------------------
	
	private static final String	c_Title					= "InvoiceListDialog.Title";
	private static final String	c_PhysicianSwitch		= "InvoiceListDialog.PhysicianSwitch";

	private static final String	c_PeriodBorder			= "InvoiceListDialog.PeriodBorder";
	
	private static final String	c_OptionsBorder			= "InvoiceListDialog.OptionsBorder";
	private static final String c_IncludeOpenInvoices	= "InvoiceListDialog.IncludeOpenInvoices";
	private static final String c_IncludeThirdParty	    = "InvoiceListDialog.IncludeThirdParty";
	private static final String	c_OnlyTotals            = "InvoiceListDialog.OnlyTotals";
	
	private final static String c_Columns				= "3dlu,fill:max(70dlu;pref)," + 
														  "3dlu,fill:max(70dlu;pref),3dlu";

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

	private final static String c_PhysicianPanelColumns	= "3dlu,fill:max(100dlu;pref),3dlu";
	
	private final static String c_PhysicianPanelRows	= "3dlu,fill:max(70dlu;pref),3dlu";

	private final static String c_OptionsPanelColumns	= "3dlu,fill:pref,3dlu";
	
	private final static String c_OptionsPanelRows		= "3dlu,fill:pref," +
														  "3dlu,fill:pref," +
														  "3dlu,fill:pref,3dlu";
	
//---------------------------------------------------------------------------
//***************************************************************************
//* Constructor	                                                            *
//***************************************************************************
//---------------------------------------------------------------------------

public InvoiceListDialog ()
	{
	super (MainFrame.getInstance(),Translatrix.getTranslationString(c_Title),true);
	
	CellConstraints	l_Constraints;
	FormLayout		l_Layout;
	l_Constraints  = new CellConstraints();

	m_Validated = false;
	this.getContentPane().setBackground(GECAMedColors.c_GECAMedBackground);

	buildPhysiciansPanel ();
	buildPeriodPanel ();
	buildOptionsPanel ();
	
	l_Constraints  = new CellConstraints();
	l_Layout = new FormLayout(c_Columns, c_Rows);
	this.setLayout(l_Layout);
	
	this.add(m_PhysicianBorder,  l_Constraints.xywh(2, 2, 3, 1));
	this.add(m_PeriodPanel,      l_Constraints.xywh(2, 4, 3, 1));
	this.add(m_OptionsPanel,	 l_Constraints.xywh(2, 6, 3, 1));

	m_OkayButton = new JButton (Translatrix.getTranslationString("core.ok"));
	m_OkayButton.setIcon(GECAMedModule.getSmallIcon(GECAMedIconNames.OK));
	m_OkayButton.addActionListener(this);

	m_CancelButton = new JButton (Translatrix.getTranslationString("core.cancel"));
	m_CancelButton.setIcon(GECAMedModule.getSmallIcon(GECAMedIconNames.CANCEL));
	m_CancelButton.addActionListener(this);

	this.add (m_OkayButton,  	l_Constraints.xywh(2, 8, 1, 1));
	this.add (m_CancelButton,   l_Constraints.xywh(4, 8, 1, 1));
	}

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

private void buildPhysiciansPanel ()
	{
	CellConstraints	l_Constraints;
	FormLayout		l_Layout;
	
	l_Constraints  = new CellConstraints();
	
	m_PhysicianPanel = new JPanel ();

	l_Layout = new FormLayout(c_PhysicianPanelColumns, c_PhysicianPanelRows);
	m_PhysicianPanel.setLayout (l_Layout);
	m_PhysicianPanel.setOpaque(true);
	
	m_SearchByPhysician = new JCheckBox (Translatrix.getTranslationString(c_PhysicianSwitch));
    m_SearchByPhysician.setBackground(GECAMedColors.c_GECAMedBackground);
    m_SearchByPhysician.setSelected(false);
    m_SearchByPhysician.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_PhysicianScroller = new JScrollPane (m_PhysicianList);
	m_PhysicianScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
	
	m_PhysicianPanel.add (m_PhysicianScroller, l_Constraints.xywh(2, 2, 1, 1));

	m_PhysicianBorder = new ComponentTitledPanel (m_SearchByPhysician,m_PhysicianPanel);
    m_PhysicianBorder.setOpaque(false);	

	m_Physicians.setPhysicians(GECAMedLists.getListReference(Physician.class));
	
	this.enablePhysicianPanel(false);
	}

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

private void buildPeriodPanel ()
	{
	m_PeriodBorder = new TitledBorder (Translatrix.getTranslationString (c_PeriodBorder));
	
	m_PeriodPanel = new FromUntilDatePanel (FromUntilDatePanel.c_UntilDateToLastOfMonth);
	m_PeriodPanel.setBorder(m_PeriodBorder);
	}

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

private void buildOptionsPanel ()
	{
	CellConstraints	l_Constraints;
	FormLayout		l_Layout;
	
	l_Constraints  = new CellConstraints();

	l_Layout = new FormLayout(c_OptionsPanelColumns, c_OptionsPanelRows);
	m_OptionsBorder = new TitledBorder (Translatrix.getTranslationString (c_OptionsBorder));
	
	m_OptionsPanel = new JPanel ();
	m_OptionsPanel.setOpaque(false);
	m_OptionsPanel.setLayout(l_Layout);
	m_OptionsPanel.setBorder(m_OptionsBorder);
	
	m_IncludeOpenInvoices = new JCheckBox ();
	m_IncludeOpenInvoices.setText (Translatrix.getTranslationString (c_IncludeOpenInvoices));
	m_IncludeOpenInvoices.setBackground(GECAMedColors.c_GECAMedBackground);
	
	m_IncludeThirdParty = new JCheckBox ();
	m_IncludeThirdParty.setText (Translatrix.getTranslationString (c_IncludeThirdParty));
	m_IncludeThirdParty.setBackground(GECAMedColors.c_GECAMedBackground);
	
	m_OnlyTotals = new JCheckBox ();
	m_OnlyTotals.setText (Translatrix.getTranslationString (c_OnlyTotals));
	m_OnlyTotals.setBackground(GECAMedColors.c_GECAMedBackground);
	
	m_OptionsPanel.add (m_IncludeOpenInvoices, l_Constraints.xywh(2, 2, 1, 1));
	m_OptionsPanel.add (m_IncludeThirdParty,      l_Constraints.xywh(2, 4, 1, 1));
	m_OptionsPanel.add (m_OnlyTotals,            l_Constraints.xywh(2, 6, 1, 1));
	}

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

private void setBackground (JComponent p_Component, boolean p_EnableIt)
	{
	if (p_EnableIt)
		 p_Component.setBackground (GECAMedColors.c_GECAMedDarkerBackground);
	else p_Component.setBackground (GECAMedColors.c_GECAMedBackground);
	}

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

private boolean showOnlyInvoicesOfCurrentPhysician ()
	{
	boolean l_ShowOnlyCurrentPhysician;
	
	l_ShowOnlyCurrentPhysician = 
	
	!BillingModule.userHasPermission(MainFrame.PERMISSIONS_CORE, MainFrame.PERMISSION_CHANGE_PHYSICIAN)
	
	&&
		
	(Boolean)BillingModule.getSetting(BillingAdminSettings.c_SplitBillingSetting);
	
	return l_ShowOnlyCurrentPhysician;
	}

//===========================================================================
//= Panel Enabling
//===========================================================================
//---------------------------------------------------------------------------	

private void enablePhysicianPanel (boolean p_EnableIt)
	{
	this.setBackground (m_PhysicianPanel,p_EnableIt);
	m_PhysicianList.setEnabled(p_EnableIt);
	m_PhysicianScroller.getVerticalScrollBar().setEnabled(p_EnableIt);	
	
	if (!p_EnableIt)
		{
		m_PhysicianList.clearSelection();
		}
	else
		{
		m_PhysicianList.setSelectedValue(GECAMedModule.getCurrentPhysician(), true);
		}
	}

//---------------------------------------------------------------------------	
//===========================================================================
//= Search Expressions
//===========================================================================
//---------------------------------------------------------------------------	

private void assembleWhereClause ()
	{
	Group		l_SearchExpression;

	m_WhereClause = new WhereClause();
	m_WhereClause.setOperator(HibernateOperator.c_AndOperator);
		
	l_SearchExpression = this.getPhysicianSearchExpression();
	m_WhereClause.addGroup(l_SearchExpression);
	
	l_SearchExpression = this.getPeriodSearchExpression();
	m_WhereClause.addGroup(l_SearchExpression);
	
	l_SearchExpression = this.getOptionsSearchExpression();
	m_WhereClause.addGroup(l_SearchExpression);
	
	if (showOnlyInvoicesOfCurrentPhysician ())
		{
		l_SearchExpression = this.getSplitBillingDiscriminator();
		m_WhereClause.addGroup(l_SearchExpression);
		}
	}

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

private Group getSplitBillingDiscriminator ()
	{
	Group				l_SearchDiscriminator   = null;
	HibernateCondition	l_Condition 			= null;
	Physician			l_CurrentPhysician  	= null;

	l_CurrentPhysician = BillingModule.getCurrentPhysician();
	if ((l_CurrentPhysician == null) || (!l_CurrentPhysician.isPersistent())) return null;
	
	l_SearchDiscriminator = new Group (HibernateOperator.c_AndOperator);
	
	l_Condition = new HibernateCondition ("physicianId",
										   HibernateOperator.c_EqualOperator,
										   l_CurrentPhysician.getId());
	
	l_SearchDiscriminator.addCondition(l_Condition);
	
	return l_SearchDiscriminator;
	}

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

private Group getPhysicianSearchExpression ()
	{
	int[]				l_SelectedIndices;
	Physician			l_Physician;
	Group				l_SearchExpression 	= null;
	HibernateCondition	l_Condition 		= null;
	int					l_Index;
	
	if (m_SearchByPhysician.isSelected())
		{
		l_SearchExpression = new Group (HibernateOperator.c_OrOperator);
		
		l_SelectedIndices = m_PhysicianList.getSelectedIndices();
		if (l_SelectedIndices != null)
			{
			for (l_Index = 0; l_Index < l_SelectedIndices.length; l_Index++)
				{
				l_Physician = m_Physicians.getElementAt(l_SelectedIndices[l_Index]);
				
				l_Condition = new HibernateCondition ("physicianId",
													  HibernateOperator.c_EqualOperator,
													  l_Physician.getId());
					
				l_SearchExpression.addCondition (l_Condition);
				}			
			}
		}
	
	return l_SearchExpression;
	}

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

private Group getPeriodSearchExpression ()
	{
	Group				l_SearchExpression 	= null;
	HibernateCondition	l_Condition 		= null;
	
	l_SearchExpression = new Group (HibernateOperator.c_AndOperator);
		
	if (m_PeriodPanel.getFromDate() != null)
		{
		l_Condition = new HibernateCondition ("invoiceDate",
											  HibernateOperator.c_GreaterOrEqualOperator, 
											  m_PeriodPanel.getFromDate());
			
		l_Condition.setParameter("PeriodFromDate");
		}
		
	l_SearchExpression.addCondition (l_Condition);
		
	if (m_PeriodPanel.getWithUntilDate() && m_PeriodPanel.getUntilDate() != null)
		{			
		l_Condition = new HibernateCondition ("invoiceDate",
											  HibernateOperator.c_LowerOrEqualOperator,
											  m_PeriodPanel.getUntilDate());
			
		l_Condition.setParameter("PeriodUntilDate");
		l_SearchExpression.addCondition (l_Condition);
		}
	
	return l_SearchExpression;
	}

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

private Group getOptionsSearchExpression ()
	{
	Group				l_SearchExpression 		= null;
	Group				l_ThirdPartyExpression 	= null;
	HibernateCondition	l_Condition 			= null;
	HibernateList		l_OpenStates			= null;
	
	
	l_SearchExpression = new Group (HibernateOperator.c_AndOperator);

	if (!m_IncludeOpenInvoices.isSelected())
		{
		
		l_OpenStates = new HibernateList ("intValue",Integer.class,m_OpenStates);
		
		l_Condition = new HibernateCondition ("state",
											  HibernateOperator.c_NotInOperator,
											  l_OpenStates); 
		
		l_SearchExpression.addCondition(l_Condition);
		}
	
	if (!m_IncludeThirdParty.isSelected())
		{
		l_ThirdPartyExpression = new Group (HibernateOperator.c_OrOperator);
		
		l_Condition = new HibernateCondition ("thirdPartyPayerId",
				  							  HibernateOperator.c_IsOperator,
				  							  HibernateCondition.c_Null); 
		
		l_ThirdPartyExpression.addCondition(l_Condition);
		
		l_Condition = new HibernateCondition ("thirdPartyPayerId",
				  							  HibernateOperator.c_EqualOperator,
				  							  Integer.valueOf(0)); 
		
		l_ThirdPartyExpression.addCondition(l_Condition);
		
		l_SearchExpression.addGroup(l_ThirdPartyExpression);
		}
		
	return l_SearchExpression;
	}
	
//---------------------------------------------------------------------------
//***************************************************************************
//* Class Body	                                                            *
//***************************************************************************
//---------------------------------------------------------------------------

public Date getFromDate ()
	{
	return m_PeriodPanel.getFromDate();
	}

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

public Date getUntilDate ()
	{
	return m_PeriodPanel.getUntilDate();
	}

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

public boolean includeOpenInvoices ()
	{
	return m_IncludeOpenInvoices.isSelected();
	}

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

public void setIncludeOpenInvoices (boolean p_IncludeThem)
	{
	m_IncludeOpenInvoices.setSelected (p_IncludeThem);
	}

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

public boolean includeThirdParty ()
	{
	return m_IncludeThirdParty.isSelected();
	}

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

public void setIncludeThirdParty (boolean p_IncludeThem)
	{
	m_IncludeThirdParty.setSelected (p_IncludeThem);
	}

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

public boolean onlyTotals ()
	{
	return m_OnlyTotals.isSelected();
	}

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

public void setOnlyTotals (boolean p_OnlyTotals)
	{
	m_OnlyTotals.setSelected(p_OnlyTotals);
	}

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

public boolean wasValidated ()
	{
	return m_Validated;
	}

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

public WhereClause getWhereClause ()
	{
	return m_WhereClause;
	}

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

public void itemStateChanged (ItemEvent p_ItemEvent) 
	{
	boolean l_EnableIt;
	
	l_EnableIt = (p_ItemEvent.getStateChange() == ItemEvent.SELECTED)?true:false; 
	
	if (p_ItemEvent.getSource().equals (m_SearchByPhysician))
		{
		this.enablePhysicianPanel(l_EnableIt);
		}
	}

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

public void setVisible (boolean p_ShowIt)
	{
	if (p_ShowIt) m_Validated = false;
	
	if ((p_ShowIt) && (showOnlyInvoicesOfCurrentPhysician ()))
		{	
		this.enablePhysicianPanel(false);
		m_SearchByPhysician.setSelected(false);
		m_SearchByPhysician.setEnabled(false);
		m_PhysicianList.setSelectedValue(BillingModule.getCurrentPhysician(), true);
		}
	super.setVisible(p_ShowIt);
	}

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

public void actionPerformed (ActionEvent p_Event) 
	{
	if (p_Event.getSource().equals(m_OkayButton))
	{
	m_Validated = true;
	this.assembleWhereClause();
	this.setVisible(false);
	}	
else if (p_Event.getSource().equals(m_CancelButton))
	{
	m_Validated = false;
	m_WhereClause = null;
	this.setVisible(false);
	}	
	}

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

public void relocalize() 
	{
	if (m_SearchByPhysician != null)
		m_SearchByPhysician.setText (Translatrix.getTranslationString(c_PhysicianSwitch));
	
	if (m_PeriodBorder != null)
		m_PeriodBorder.setTitle (Translatrix.getTranslationString (c_PeriodBorder));

	if (m_PeriodPanel != null) m_PeriodPanel.relocalize();
	
	if (m_IncludeOpenInvoices != null)
		m_IncludeOpenInvoices.setText(Translatrix.getTranslationString (c_IncludeOpenInvoices));
		
	if (m_IncludeThirdParty != null)
		m_IncludeThirdParty.setText(Translatrix.getTranslationString (c_IncludeThirdParty));
		
	if (m_OnlyTotals != null)
		m_OnlyTotals.setText (Translatrix.getTranslationString (c_OnlyTotals));	
	}

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

}
