/*******************************************************************************
 * 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
 *******************************************************************************/
/*
 * InvoiceListModel.java
 *
 * Created on March 31, 2006
 */

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

/**
 *
 * @author  santec
 */

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;

import javax.swing.table.AbstractTableModel;

import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Account;
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.ejb.entity.beans.Payment;
import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Settlement;
import lu.tudor.santec.gecamed.billing.gui.invoice.stub.GenericInvoiceStubListInterface;
import lu.tudor.santec.gecamed.core.gui.GECAMedLists;
import lu.tudor.santec.gecamed.core.utils.SSNChecker;
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.Translatrix;

//***************************************************************************
//* Class Members                                                           *
//***************************************************************************

public class InvoiceStubListModel extends AbstractTableModel implements GenericInvoiceStubListInterface
    {
 	private static final long serialVersionUID = 1L;
	
    private Vector      	<InvoiceStub> m_InvoiceStubs;        
    
    private HashMap			<Integer, String> m_Physicians;
      
    public static final Date c_Epoch = new Date (0);
    
	private HashMap<Integer, Insurance> insurances = new HashMap<Integer, Insurance>();
	private HashMap<Integer, Settlement> settlements = new HashMap<Integer, Settlement>();
    
//***************************************************************************
//* Class Constants                                                         *
//***************************************************************************

    public static final String c_TickedHeader				= "InvoiceListModel.TickedHeader";
    public static final String c_InvoiceStatusHeader		= "InvoiceListModel.StatusHeader";
    public static final String c_ClassHeader 				= "InvoiceListModel.ClassHeader";
    public static final String c_PatientNameHeader			= "InvoiceListModel.PatientNameHeader";
    public static final String c_PatientSSNHeader			= "InvoiceListModel.PatientSSNHeader";
    public static final String c_InsuranceHeader 			= "InvoiceListModel.HealthInsuranceHeader";
    public static final String c_TPPHeader 					= "InvoiceListModel.ThirdPartyHeader";
    public static final String c_InvoiceNumberHeader 		= "InvoiceListModel.InvoiceNumberHeader";
    public static final String c_PhysicianHeader			= "InvoiceListModel.PhysicianHeader";
    public static final String c_InvoiceDateHeader 			= "InvoiceListModel.InvoiceDateHeader";
    public static final String c_ClosureDateHeader 			= "InvoiceListModel.ClosureDateHeader";
    public static final String c_PrintedDateHeader 			= "InvoiceListModel.PrintedDateHeader";
    public static final String c_DueDateHeader 				= "InvoiceListModel.DueDateHeader";
    public static final String c_ReminderDateHeader 		= "InvoiceListModel.ReminderDateHeader";
    public static final String c_ReminderHeader 			= "InvoiceListModel.ReminderHeader";
    public static final String c_AmountHeader 				= "InvoiceListModel.AmountHeader";
    public static final String c_PaymentHeader 				= "InvoiceListModel.PaymentHeader";
    public static final String c_DeductionHeader 			= "InvoiceListModel.DeductionHeader";
    public static final String c_BalanceHeader 				= "InvoiceListModel.BalanceHeader";
    public static final String c_PaymentDateHeader 			= "InvoiceListModel.SettlementDateHeader";
    public static final String c_PaymentTypeHeader 			= "InvoiceListModel.SettlementHeader";
    
    public static final int		c_TickedColumn				= 0;
    public static final int		c_InvoiceStatusColumn		= 1;
    public static final int		c_ClassColumn				= 2;
    public static final int		c_PatientNameColumn			= 3;
    public static final int		c_PatientSSNColumn			= 4;
    public static final int		c_InsuranceColumn			= 5;
    public static final int		c_TPPColumn					= 6;
    public static final int		c_InvoiceNumberColumn		= 7;
    public static final int		c_PhysicianColumn			= 8;
    public static final int		c_InvoiceDateColumn			= 9;
    public static final int		c_InvoiceClosureDateColumn	= 10;
    public static final int		c_InvoicePrintedColumn		= 11;
    public static final int		c_DueDateColumn				= 12;
    public static final int		c_ReminderDateColumn		= 13;
    public static final int		c_ReminderColumn			= 14;
    public static final int		c_AmountColumn				= 15;
    public static final int		c_PaymentColumn				= 16;
    public static final int		c_DeductionColumn			= 17;
    public static final int		c_BalanceColumn				= 18;
    public static final int		c_PaymentDateColumn			= 19;
    public static final int		c_PaymentTypeColumn			= 20;
 
    static final public String c_TableHeaders [] = { 	c_TickedHeader,
    													c_InvoiceStatusHeader,
    													c_ClassHeader,
    													c_PatientNameHeader,
    													c_PatientSSNHeader,
    													c_InsuranceHeader,
    												    c_TPPHeader,
    													c_InvoiceNumberHeader,
    													c_PhysicianHeader,
       													c_InvoiceDateHeader,
       													c_ClosureDateHeader,
       													c_PrintedDateHeader,
       													c_DueDateHeader,
       													c_ReminderDateHeader,
       													c_ReminderHeader,
       													c_AmountHeader,
    													c_PaymentHeader,
    													c_DeductionHeader,
    													c_BalanceHeader,
    													c_PaymentDateHeader,
    													c_PaymentTypeHeader
    													};
 
//***************************************************************************
//* Constructor(s)                                                          *
//***************************************************************************

public InvoiceStubListModel ()
    {
    m_InvoiceStubs  = new Vector <InvoiceStub> ();
    
    /**
     * @author ferring
     * Creates a HashMap, containing all physician names assigned to their ID.
     * This enables a fast access to all existing physicians as it is needed
     * while building the table.
     */
    m_Physicians	= new HashMap<Integer, String>();
    loadPhysicianMap();
    
	GECAMedLists.addPropertyChangeListener(new PropertyChangeListener() 
		{
		public void propertyChange(PropertyChangeEvent evt) 
			{
			loadPhysicianMap();
			}
		}, Physician.class);
    }

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

private String getPatientName (InvoiceStub p_InvoiceStup)
	{
	String  l_Name		= "-";

	if (p_InvoiceStup != null)
		{
		l_Name = (p_InvoiceStup.getPatientName() != null) ? p_InvoiceStup.getPatientName().toUpperCase() : "";
		l_Name += " ";
		l_Name += (p_InvoiceStup.getPatientFirstName() != null) ? p_InvoiceStup.getPatientFirstName() : "";
		}
	
	return l_Name;
	}

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

private String getPatientSSN (InvoiceStub p_InvoiceStup)
	{
	String  l_SSN		= "-";

	if (p_InvoiceStup != null && p_InvoiceStup.getPatientSSN() != null)
		{
		l_SSN = SSNChecker.getFormattedSSN(p_InvoiceStup.getPatientSSN(), false);
		}

	return l_SSN;
	}

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

/**
 * @author ferring
 * loads (or reloads) the list containing all physicians in the system 
 */
private void loadPhysicianMap ()
	{
	Physician[] l_Physicians = GECAMedLists.getArray(Physician.class);
	
	m_Physicians.clear();
	for (Physician physician : l_Physicians) 
		{
		m_Physicians.put(physician.getId(), physician.toString());
		}
	}

/**
 * @author ferring
 * Returns the physicians name from the hash map.
 * 
 * @param p_PhysicianId
 * @return the name of the physician
 */
private String getPhysicianName (Integer p_PhysicianId)
	{
	String l_PhysicianName = m_Physicians.get(p_PhysicianId);
	
	if (l_PhysicianName == null) 
		 return "";
	else return l_PhysicianName;
	}

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

public String getColumnName (int p_Column)
    {
    if ((p_Column >=0) && (p_Column < c_TableHeaders.length))
    		{
    		return (Translatrix.getTranslationString(c_TableHeaders[p_Column]));
    		}
    else return ("");
    }

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

public int getColumnCount ()
    {
    return (c_TableHeaders.length);
    }

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

public int getRowCount ()
    {
    return (m_InvoiceStubs.size());
    }

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

public Object getValueAt (int p_Row, int p_Column)
    {
    InvoiceStub  l_InvoiceStub;
    
    l_InvoiceStub = new InvoiceStub ();
    
    if ((p_Row >= 0) && (p_Row < m_InvoiceStubs.size()))
        {
    	l_InvoiceStub = m_InvoiceStubs.elementAt (p_Row);
    	if (l_InvoiceStub == null) l_InvoiceStub = new InvoiceStub ();
        }
    
    switch (p_Column)
        {
        case  c_TickedColumn: 		return (l_InvoiceStub.getTicked() != null) ? l_InvoiceStub.getTicked() : false;
        case  c_InvoiceStatusColumn:return l_InvoiceStub.getState();
        case  c_ClassColumn: 		return (l_InvoiceStub.getHospitalisationClassId() != null) ? lu.tudor.santec.gecamed.billing.gui.reminder.InvoiceStubListModel.getHospitalisationClass(l_InvoiceStub.getHospitalisationClassId()) : "";
        case  c_PatientNameColumn: 	return this.getPatientName (l_InvoiceStub);
        case  c_PatientSSNColumn: 	return this.getPatientSSN (l_InvoiceStub);
        case  c_InsuranceColumn:	return this.getInsuranceName(l_InvoiceStub.getInsuranceId());
        case  c_TPPColumn: 			return this.getInsuranceName(l_InvoiceStub.getThirdPartyPayerId());
        case  c_InvoiceNumberColumn:return l_InvoiceStub.formatInvoiceNumber(Invoice.c_ShortFormat, true);
        case  c_PhysicianColumn:	return this.getPhysicianName(l_InvoiceStub.getPhysicianId());
        case  c_InvoiceDateColumn: 	return (l_InvoiceStub.getInvoiceDate() != null) ? l_InvoiceStub.getInvoiceDate() : c_Epoch;
        case  c_InvoiceClosureDateColumn: return (l_InvoiceStub.getClosureDate() != null) ? l_InvoiceStub.getClosureDate() : c_Epoch;
        case  c_InvoicePrintedColumn: return (l_InvoiceStub.getPrintedDate() != null) ? l_InvoiceStub.getPrintedDate() : c_Epoch;
        case  c_DueDateColumn: 		return (l_InvoiceStub.getDueDate() != null) ? l_InvoiceStub.getDueDate() : c_Epoch;
        case  c_ReminderDateColumn: return (l_InvoiceStub.getReminderDate() != null) ? l_InvoiceStub.getReminderDate() : c_Epoch;
        case  c_ReminderColumn: 	return (l_InvoiceStub.getNumberOfReminders() != null) ? l_InvoiceStub.getNumberOfReminders() : 0;
        case  c_AmountColumn: 		return (l_InvoiceStub.getAmount() != null) ? l_InvoiceStub.getAmount() : 0;
        case  c_PaymentColumn: 		return (l_InvoiceStub.getPayment() != null) ? l_InvoiceStub.getPayment() : 0;
        case  c_DeductionColumn: 	return (l_InvoiceStub.getDeduction() != null) ? l_InvoiceStub.getDeduction() : 0;
        case  c_BalanceColumn: 		return (l_InvoiceStub.getBalance() != null) ? l_InvoiceStub.getBalance() : 0;
        case  c_PaymentDateColumn:  return (l_InvoiceStub.getSettlementDate() != null) ? l_InvoiceStub.getSettlementDate() : c_Epoch;
        case  c_PaymentTypeColumn:  return this.getSettlement(l_InvoiceStub.getSettlementId());
        
        default: return "";
        }
    }
 
private String getInsuranceName(Integer id) {
	try {
		return insurances.get(id).getAcronym();					
	} catch (Exception e) {
		return "";
	}
}

public void setInsurances(Collection<Insurance> l_Insurances) {
	insurances.clear();
	for (Insurance ins : l_Insurances) {
		insurances.put(ins.getId(), ins);
	}
}

	private String getSettlement(Integer id) {

		Settlement p_Settlement = settlements.get(id);

		Payment l_Payment;
		Account l_Account;
		String l_Settlement = "";

		if (p_Settlement == null)
			return "";

		if (p_Settlement.getPayment() != null) {
			l_Payment = p_Settlement.getPayment();
			l_Settlement = l_Payment.getMethod();
		} else {
			l_Account = p_Settlement.getTransferAccount();
			if (l_Account.getLabel() != null && l_Account.getLabel().trim().length() > 0)
				l_Settlement = l_Account.getLabel();
			else
				l_Settlement = l_Account.getIban();
		}

		return l_Settlement;
	}

public void setSettlements(Collection<Settlement> l_Settlements) {
	settlements.clear();
	for (Settlement ins : l_Settlements) {
		settlements.put(ins.getId(), ins);
	}
}

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

public Class<?> getColumnClass (int p_Column) 
    {
    if (getValueAt(0, p_Column) != null)
    		 return (Class<?>) getValueAt(0, p_Column).getClass();
    else return null;
    }

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

public boolean isEditable ()
	{
	return true;
	}

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

public void setEditable (boolean p_Editable)
	{
	}

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

public boolean isCellEditable   (int p_Row, int p_Column)
    {
	if (p_Column == c_TickedColumn) 
		 return true;
	else return false;
    }

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

public void setValueAt (Object p_Value, int p_Row, int p_Column)
	{
	InvoiceStub	l_InvoiceStub;
	
	if ((p_Row >= 0) && (p_Row < m_InvoiceStubs.size()))
		{
		l_InvoiceStub = m_InvoiceStubs.elementAt (p_Row);
		if (l_InvoiceStub == null) return;
	
		switch (p_Column)
			{
			case  c_TickedColumn: l_InvoiceStub.setTicked((Boolean)p_Value);
									m_InvoiceStubs.setElementAt(l_InvoiceStub, p_Row);
									break;
			}
		fireTableCellUpdated (p_Row,p_Column);
		}
	}
		
//---------------------------------------------------------------------------

public InvoiceStub	getInvoiceStubAt (int p_Row)
    {
    InvoiceStub  l_InvoiceStub;
     
    if ((p_Row >= 0) && (p_Row < m_InvoiceStubs.size()))
        {
    	l_InvoiceStub = m_InvoiceStubs.elementAt (p_Row);
        return l_InvoiceStub;
        }
    else return null;
    }
	
//---------------------------------------------------------------------------

public void	setInvoiceStubAt (InvoiceStub p_InvoiceStub, int p_Row)
    {     
    if ((p_InvoiceStub != null) && (p_Row >= 0) && (p_Row < m_InvoiceStubs.size()))
        {
    	m_InvoiceStubs.setElementAt(p_InvoiceStub,p_Row);
        }
    this.fireTableRowsUpdated(p_Row, p_Row);
    }
	
//---------------------------------------------------------------------------

public void addInvoiceStub (InvoiceStub p_InvoiceStub)
    {
	int	l_Row;
	
	if (p_InvoiceStub != null)    
        {    
		m_InvoiceStubs.addElement (p_InvoiceStub);
         
        l_Row = m_InvoiceStubs.size() - 1;
        fireTableRowsInserted (l_Row,l_Row);
        }
    }
	
//---------------------------------------------------------------------------

public void removeInvoiceStub (InvoiceStub p_InvoiceStub)
	{
	int	l_Index;
	
	if (p_InvoiceStub != null)
		{
		l_Index = m_InvoiceStubs.indexOf(p_InvoiceStub);
		if (l_Index >= 0) this.removeInvoiceStubAt(l_Index);		
		}
	}

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

public void removeAllInvoiceStubs ()
	{
	int	l_LastRow;
	
	l_LastRow = m_InvoiceStubs.size() -1;

	m_InvoiceStubs.removeAllElements ();
	
	if (l_LastRow >= 0) fireTableRowsDeleted (0,l_LastRow);
	}

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

public void removeInvoiceStubAt (int p_Row)
    {
    if ((p_Row >= 0) && (p_Row < m_InvoiceStubs.size()))
        {
    	m_InvoiceStubs.removeElementAt(p_Row); 
    	fireTableRowsDeleted (p_Row,p_Row);
        }
    }

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

public int findInvoiceStub (Integer p_InvoiceId)
    {
//    int 		l_Row;
//    boolean		l_Found;
// 	InvoiceStub	l_InvoiceStub;
//    
// 	l_Found = false;
// 	
// 	if (p_InvoiceNumber == null) return -1;
// 	
// 	for (l_Row = 0; (l_Row < m_InvoiceStubs.size()) && (!l_Found); l_Row++)
//    		{
// 		l_InvoiceStub = m_InvoiceStubs.elementAt(l_Row);
//    		if (p_InvoiceNumber.equals(l_InvoiceStub.formatInvoiceNumber(Invoice.c_LongFormat))) l_Found = true;
//    		}
//    
//    if (l_Found) return l_Row;
//    		   else return (-1);
    return -1; 
    }

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

public boolean containsInvoiceStub (InvoiceStub p_InvoiceStub)
	{
	return m_InvoiceStubs.contains (p_InvoiceStub);
	}
	
//---------------------------------------------------------------------------

public void setInvoiceStubs (Collection <InvoiceStub> p_InvoiceStubs)
    {
 	if (p_InvoiceStubs == null) return;
        
    removeAllInvoiceStubs ();
 
    m_InvoiceStubs.addAll (0,p_InvoiceStubs);
     
    fireTableRowsInserted (0,p_InvoiceStubs.size());
    }

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

public void addInvoiceStubs (Collection <InvoiceStub> p_InvoiceStubs)
	{
	if (p_InvoiceStubs == null) return;
  
	m_InvoiceStubs.addAll (0,p_InvoiceStubs);
     
    fireTableRowsInserted (0,p_InvoiceStubs.size());	
	}

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

public Collection <InvoiceStub> getInvoiceStubs ()
    {
	Vector <InvoiceStub> l_InvoiceStubs;
	
	l_InvoiceStubs = new Vector <InvoiceStub> (m_InvoiceStubs);
	
	return l_InvoiceStubs;
    }    
        
//---------------------------------------------------------------------------

public Collection <InvoiceStub> getTickedInvoiceStubs ()
    {
	Collection <InvoiceStub> 	l_TickedInvoiceStubs;
	Iterator <InvoiceStub>		l_InvoiceStubIterator;
	InvoiceStub					l_InvoiceStub;
	
	l_TickedInvoiceStubs = new ArrayList <InvoiceStub> (); 
	
	l_InvoiceStubIterator = m_InvoiceStubs.iterator();
	while (l_InvoiceStubIterator.hasNext())
		{
		l_InvoiceStub = l_InvoiceStubIterator.next();
		if (l_InvoiceStub.getTicked()) l_TickedInvoiceStubs.add(l_InvoiceStub);
		}
	
	return l_TickedInvoiceStubs;
    }

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