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

import java.util.Comparator;
import java.util.Date;
import java.util.Vector;

import lu.tudor.santec.gecamed.billing.ejb.entity.beans.InvoiceStub;

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

/**
 * The InvoiceStubComparator implements a Comparator for InvoiceStubs. A
 * dedicated method allows to specify which properties are to be used in
 * comparison operation.
 * @author nico.mack@tudor.lu
 */

public class InvoiceStubComparator implements Comparator <InvoiceStub>
	{
	private Vector<Integer>	m_SortingProperty;
	private Vector<Integer>	m_SortDirection;
	
//---------------------------------------------------------------------------
//***************************************************************************
//* Constants					                                            *
//***************************************************************************
//---------------------------------------------------------------------------

	public static final int	c_Ascending			= 1;
	public static final int	c_Descending		= -1;
	
	public static final int	c_None				= -1;
	
	public static final int	c_Id				= 0;
	public static final int	c_PatientId			= 1;
	public static final int	c_PhysicianId		= 2;
	public static final int	c_PatientName		= 3;
	public static final int	c_PatientFirstName	= 4;
	public static final int c_PatientFullName   = 5;
	public static final int	c_ThirdPartyPayerId	= 6;
	public static final int	c_PatientSSN		= 7;
	public static final int	c_InvoiceDate		= 8;
	public static final int	c_DueDate			= 9;
	public static final int	c_State				= 10;
	public static final int	c_Reminders			= 11;
	public static final int	c_ReminderDate		= 12;
	public static final int	c_Amount			= 13;
	public static final int	c_Payment			= 14;
	public static final int	c_Deduction			= 15;
	public static final int	c_Balance			= 16;
	public static final int	c_Grouping			= 17;
	
	public static final int c_PropertyCount		= 18;
	
	
	public static final int GROUP_NONE 			= 0;
	public static final int GROUP_PHYSICIAN 	= 1;
	public static final int GROUP_BAILIF		= 2;
	public static final int GROUP_BAILIF_MONTH 	= 3;
	
	
//---------------------------------------------------------------------------
//***************************************************************************
//* Constructor					                                            *
//***************************************************************************
//---------------------------------------------------------------------------
/**
 * Creates a new instance of InvoiceStubComparator
 */
//---------------------------------------------------------------------------

	
public InvoiceStubComparator ()
	{
	m_SortingProperty 	= new Vector <Integer> ();
	m_SortDirection 	= new Vector <Integer> ();
	}
	
//---------------------------------------------------------------------------
//***************************************************************************
//* Primitives					                                            *
//***************************************************************************
//---------------------------------------------------------------------------
/**
 * Helper Method that compares two strings. String comparison is based on
 * String compareToIgnoreCase method.
 * @param p_String0 specifies the first string to compare.
 * @param p_String1 specifies the second string to compare.
 * @return if both strings are not <code>null</code>, method returns
 * value of compareTo method of p_String0 with p_String1 as argument.
 * if only first string is <code>null</code>, method will return -1. If only
 * second string is <code>null</code>, method will return 1. If both strings
 * are <code>null</code>, method will return 0.
 * @see String#compareToIgnoreCase(String)
 */
//---------------------------------------------------------------------------

public int compareStrings (String p_String0, String p_String1)	
	{
	int	l_Comparison = 0;
	
	if ((p_String0 != null) && (p_String1 != null))
		{
		l_Comparison = p_String0.compareToIgnoreCase(p_String1);
		}
	else if ((p_String0 == null) && (p_String1 != null)) l_Comparison = -1;
		 else if ((p_String0 != null) && (p_String1 == null)) l_Comparison = 1;
	 		
	return l_Comparison;
	}

//---------------------------------------------------------------------------
/**
 * Helper Method that compares two dates. Date comparison is based on
 * Date compareTo method.
 * @param p_Date0 specifies the first date to compare.
 * @param p_Date1 specifies the second date to compare.
 * @return if both dates are not <code>null</code>, method returns
 * value of compareTo method of p_Date0 with p_Date1 as argument.
 * if only first date is <code>null</code>, method will return -1. If only
 * second date is <code>null</code>, method will return 1. If both dates
 * are <code>null</code>, method will return 0.
 * @see Date#compareTo(Date)
 */
//---------------------------------------------------------------------------

public int compareDates (Date p_Date0, Date p_Date1)	
	{
	int	l_Comparison = 0;
	
	if ((p_Date0 != null) && (p_Date1 != null))
		{
		l_Comparison = p_Date0.compareTo(p_Date1);
		}
	else if ((p_Date0 == null) && (p_Date1 != null)) l_Comparison = -1;
		else if ((p_Date0 != null) && (p_Date1 == null)) l_Comparison = 1;
			
	return l_Comparison;
	}

//---------------------------------------------------------------------------
/**
 * Helper Method that compares two integers. Integer comparison is based on
 * Integer compareTo method.
 * @param p_Integer0 specifies the first integer to compare.
 * @param p_Integer1 specifies the second integer to compare.
 * @return if both integers are not <code>null</code>, method returns
 * value of compareTo method of p_Integer0 with p_Integer1 as argument.
 * if only first integer is <code>null</code>, method will return -1. If only
 * second integer is <code>null</code>, method will return 1. If both integers
 * are <code>null</code>, method will return 0.
 * @see Integer#compareTo(Integer)
 */
//---------------------------------------------------------------------------

public int compareIntegers (Integer p_Integer0, Integer p_Integer1)	
	{
	int	l_Comparison = 0;
	
	if ((p_Integer0 != null) && (p_Integer1 != null))
		{
		l_Comparison = p_Integer0.compareTo(p_Integer1);
		}
	else if ((p_Integer0 == null) && (p_Integer1 != null)) l_Comparison = -1;
	else if ((p_Integer0 != null) && (p_Integer1 == null)) l_Comparison = 1;
			
	return l_Comparison;
	}

//---------------------------------------------------------------------------
/**
 * Helper Method that compares two doubles. Double comparison is based on
 * Double compareTo method.
 * @param p_Double0 specifies the first double to compare.
 * @param p_Double1 specifies the second double to compare.
 * @return if both doubles are not <code>null</code>, method returns
 * value of compareTo method of p_Double0 with p_Double1 as argument.
 * if only first double is <code>null</code>, method will return -1. If only
 * second double is <code>null</code>, method will return 1. If both doubles
 * are <code>null</code>, method will return 0.
 * @see Double#compareTo(Double)
 */
//---------------------------------------------------------------------------

public int compareDoubles (Double p_Double0, Double p_Double1)	
	{
	int	l_Comparison = 0;
	
	if ((p_Double0 != null) && (p_Double1 != null))
		{
		l_Comparison = p_Double0.compareTo(p_Double1);
		}
	else if ((p_Double0 == null) && (p_Double1 != null)) l_Comparison = -1;
	else if ((p_Double0 != null) && (p_Double1 == null)) l_Comparison = 1;
			
	return l_Comparison;
	}

//---------------------------------------------------------------------------
//***************************************************************************
//* Class Body					                                            *
//***************************************************************************
//---------------------------------------------------------------------------
/**
 * Adds the specified property to applicable sort criteria.
 * @param p_Property specifies the property to add to sort criteria.
 * Possible values are:
 * <ul>
 * 	<li>c_Id : Invoice Id</li>
 * 	<li>c_PatientId : Patient Id</li>
 * 	<li>c_PhysicianId : Physician Id</li>
 * 	<li>c_PatientName : Name of Patient</li>
 * 	<li>c_PatientFirstName : First Name of Patient</li>
 * 	<li>c_PatientFullName : Full Name of Patient</li>
 * 	<li>c_ThirdPartyPayerId : Id of Third Party Paying Insurance</li>
 * 	<li>c_PatientSSN : Social Security Number of Patient</li>
 * 	<li>c_InvoiceDate : Invoice creation date</li>
 * 	<li>c_DueDate : Invoice due date</li>
 * 	<li>c_State : State of invoice</li>
 * 	<li>c_Reminders : Number of reminders already issued</li>
 * 	<li>c_ReminderDate : Date the last reminder was issued</li>
 * 	<li>c_Amount : Total amount of invoice</li>
 * 	<li>c_Payment : Already paid amount</li>
 * 	<li>c_Deduction : Deduced amount of total amount</li>
 * 	<li>c_Balance : Invoice balance</li>
 * </ul>
 * @param p_Direction specifies the sorting direction. Possible values
 * are:
 * <ul>
 * <li>c_Ascending : Ascending Order, i.e. lower values first.</li>
 * <li>c_Descending : Descending Order, i.e. higher values first.</li>
 * </ul>
 */
//---------------------------------------------------------------------------

public void addSortCriterion (int p_Property, int p_Direction)
	{
	int l_Direction;
	
	if ((p_Property >= 0) && (p_Property < c_PropertyCount))
		{
		l_Direction = (p_Direction > 0)?c_Ascending:c_Descending;
		
		m_SortingProperty.add (p_Property);
		m_SortDirection.add (l_Direction);	
		}
	}

//---------------------------------------------------------------------------
/**
 * Method is part of Comparator interface. Compares its two arguments for 
 * order.  Criteria being used for comparison are defined by calling addSrtCriterion 
 * method.
 * @param p_Stub0 specifies the first invoice stub to compare
 * @param p_Stub1 specifies the second invoice stub to compare
 * @return Returns a negative integer, zero, or a positive integer as the first 
 * argument is less than, equal to, or greater than the second.
 * @see #addSortCriterion(int, int)
 */
//---------------------------------------------------------------------------

public int compare (InvoiceStub p_Stub0, InvoiceStub p_Stub1) 
	{
	int	l_CriterionIndex	= 0;
	int	l_Criterion			= 0;
	int	l_Direction			= 0;
	int	l_Comparison		= 0;
	
	while ((l_CriterionIndex < m_SortingProperty.size()) && (l_Comparison == 0))
		{
		l_Criterion = m_SortingProperty.elementAt(l_CriterionIndex);
		l_Direction = m_SortDirection.elementAt(l_CriterionIndex);
		
		if ((p_Stub0 == null) && (p_Stub1 != null)) return 1 * l_Direction;
		else if ((p_Stub0 != null) && (p_Stub1 == null)) return -1 * l_Direction;
		else if ((p_Stub0 == null) && (p_Stub1 == null)) return 0;
		
		switch (l_Criterion)
			{
			case c_Id:
				
				l_Comparison = this.compareIntegers (p_Stub0.getId(), p_Stub1.getId());
				break;
			
			case c_PatientId:
				
				l_Comparison = this.compareIntegers (p_Stub0.getPatientId(), p_Stub1.getPatientId());
				break;
			
			case c_PhysicianId:
				
				l_Comparison = this.compareIntegers (p_Stub0.getPhysicianId(), p_Stub1.getPhysicianId());
				break;
			
			case c_PatientName:
				
				l_Comparison = this.compareStrings (p_Stub0.getPatientName(), p_Stub1.getPatientName());
				break;
			
			case c_PatientFirstName:
				
				l_Comparison = this.compareStrings (p_Stub0.getPatientFirstName(), p_Stub1.getPatientFirstName());
				break;
			
			case c_PatientFullName:
				
				l_Comparison = this.compareStrings (p_Stub0.getPatientFullName(), p_Stub1.getPatientFullName());
				break;

			case c_ThirdPartyPayerId:
				
				l_Comparison = this.compareIntegers (p_Stub0.getThirdPartyPayerId(), p_Stub1.getThirdPartyPayerId());
				break;
			
			case c_PatientSSN:
				
				l_Comparison = this.compareStrings (p_Stub0.getPatientSSN(), p_Stub1.getPatientSSN());
				break;
			
			case c_InvoiceDate:
				
				l_Comparison = this.compareDates (p_Stub0.getInvoiceDate(), p_Stub1.getInvoiceDate());
				break;
			
			case c_DueDate:
				
				l_Comparison = this.compareDates (p_Stub0.getDueDate(), p_Stub1.getDueDate());
				break;
			
			case c_State:
				
				l_Comparison = this.compareIntegers (p_Stub0.getState(), p_Stub1.getState());
				break;
			
			case c_Reminders:
				
				l_Comparison = this.compareIntegers (p_Stub0.getNumberOfReminders(), p_Stub1.getNumberOfReminders());
				break;
			
			case c_ReminderDate:
				
				l_Comparison = this.compareDates (p_Stub0.getReminderDate(), p_Stub1.getReminderDate());
				break;
			
			case c_Amount:
				
				l_Comparison = this.compareDoubles (p_Stub0.getAmount(), p_Stub1.getAmount());
				break;
			
			case c_Payment:
				
				l_Comparison = this.compareDoubles (p_Stub0.getPayment(), p_Stub1.getPayment());
				break;
			
			case c_Deduction:
				
				l_Comparison = this.compareDoubles (p_Stub0.getDeduction(), p_Stub1.getDeduction());
				break;
			
			case c_Balance:
				
				l_Comparison = this.compareDoubles (p_Stub0.getBalance(), p_Stub1.getBalance());
				break;
		
			case c_Grouping:
			
				l_Comparison = this.compareStrings (p_Stub0.getGroupingString(), p_Stub1.getGroupingString());
				break;

			}
		
			l_Comparison *= l_Direction;
			l_CriterionIndex++;
		}
	
	return l_Comparison;
	}

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