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

/**
 *
 * @author  santec
 */


import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Set;
import java.util.Vector;

import javax.persistence.NoResultException;
import javax.swing.table.AbstractTableModel;

import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Act;
import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Invoice;
import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Rate;
import lu.tudor.santec.gecamed.billing.ejb.session.beans.InvoiceBean;
import lu.tudor.santec.gecamed.billing.ejb.session.beans.NomenclatureBean;
import lu.tudor.santec.gecamed.billing.ejb.session.interfaces.InvoiceInterface;
import lu.tudor.santec.gecamed.billing.ejb.session.interfaces.NomenclatureInterface;
import lu.tudor.santec.gecamed.billing.gui.BillingModule;
import lu.tudor.santec.gecamed.billing.utils.ActComparator;
import lu.tudor.santec.gecamed.core.gui.GECAMedModule;
import lu.tudor.santec.gecamed.core.utils.GECAMedUtils;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.HospitalisationClass;
import lu.tudor.santec.gecamed.patient.ejb.session.interfaces.IPatientPermissions;
import lu.tudor.santec.i18n.Translatrix;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

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

public class ActListModel extends AbstractTableModel
    {
 	private static final long serialVersionUID = 1L;
 	private static Logger m_Logger = Logger.getLogger (ActListModel.class.getName());
 	
    private Vector      			<Act> m_Acts;
    private Vector					<Integer> m_ColumnWidth = new Vector<Integer>();
    private Hashtable   			<String, Integer> m_ActLookUp;
    private double					m_Majoration;
    private boolean					m_Editable;
    private boolean					m_ShowPhysicianColumn;
    private boolean 				m_AllowedToChangeAmount;
    
    private String []				m_TableHeaders;
    private Integer[]				m_ViewToModel;
    private int []					m_ModelToView;

	private InvoiceInterface		m_InvoiceManager;
	private Invoice					m_Invoice;
    
    private NomenclatureInterface	m_NomenclatureInterface;
    
//***************************************************************************
//* Class Constants                                                         *
//***************************************************************************

    public static final String c_IndexHeader			= "ActListModel.Index";
    public static final String c_HospClassHeader		= "ActListModel.HospClassHeader";
    public static final String c_DateHeader 			= "ActListModel.DateHeader";
    public static final String c_ShowTimeHeader			= "ActListModel.ShowTimeHeader";
    public static final String c_TimeHeader				= "ActListModel.TimeHeader";
    public static final String c_PhysicianHeader		= "ActListModel.PhysicianHeader";
    public static final String c_CodeHeader		 		= "ActListModel.CodeHeader";
    public static final String c_SuffixHeader		 	= "ActListModel.SuffixHeader";
    public static final String c_AdditionalInfoHeader 	= "ActListModel.AdditionalInfoHeader";
    public static final String c_LabelHeader		 	= "ActListModel.LabelHeader";
    public static final String c_QuantityHeader 		= "ActListModel.QuantityHeader";
    public static final String c_AdjustmentHeader 		= "ActListModel.AdjustmentHeader";
    public static final String c_AmountHeader 			= "ActListModel.AmountHeader";
    public static final String c_UsernameHeader 		= "ActListModel.UsernameHeader";
    public static final String c_MedPrescCodeHeader		= "ActListModel.MedPrescCodeHeader";
    
    public static final int 	c_IndexColumn			= 0;
    public static final int 	c_HospClassColumn		= 1;
    public static final int 	c_DateColumn 			= 2;
    public static final int 	c_ShowColumn			= 3;
    public static final int 	c_TimeColumn			= 4;
    public static final int 	c_PhysicianColumn		= 5;
    public static final int 	c_CodeColumn		 	= 6;
    public static final int 	c_SuffixColumn		 	= 7;
    public static final int 	c_AdditionalInfoColumn	= 8;
    public static final int 	c_LabelColumn		 	= 9;
    public static final int 	c_QuantityColumn 		= 10;
    public static final int 	c_AdjustmentColumn 		= 11;
    public static final int 	c_AmountColumn 			= 12;
    public static final int 	c_MedPrescCodeColumn	= 13;  
    public static final int 	c_UsernameColumn 		= 14;
    
    public static final int 	c_IndexColumnWidth			= 5;
    public static final int 	c_HospClassColumnWidth		= 5;
    public static final int 	c_DateColumnWidth 			= 15;
    public static final int 	c_ShowColumnWidth			= 8;
    public static final int 	c_TimeColumnWidth			= 5;
    public static final int 	c_PhysicianColumnWidth		= 10;
    public static final int 	c_CodeColumnWidth		 	= 5;
    public static final int 	c_SuffixColumnWidth		 	= 5;
    public static final int 	c_AdditionalInfoColumnWidth	= 5;
    public static final int 	c_LabelColumnWidth		 	= 42;
    public static final int 	c_QuantityColumnWidth 		= 5;
    public static final int 	c_AdjustmentColumnWidth 	= 5;
    public static final int 	c_AmountColumnWidth 		= 10;
    public static final int 	c_UsernameColumnWidth 		= 10;
    public static final int 	c_MedPrescCodeColumnWidth	= 10;  
    
    public static final int		c_MaxColumns			= 15;
         
//***************************************************************************
//* Constructor(s)                                                          *
//***************************************************************************

public ActListModel (boolean p_ShowPhysicianColumn, boolean p_ShowInfoColumn, boolean p_ShowMedPrescColumn, boolean p_ShowUsernameColumn, boolean p_ShowAdjustColumn)
    {
    int	l_Index;
	
//	m_Acts	    			= new Vector <Act> ();
    m_Acts 					= new SortedActVector();
    m_Majoration 			= 1;
    m_Editable				= true;
    m_ShowPhysicianColumn 	= p_ShowPhysicianColumn;
    m_ActLookUp  			= new Hashtable <String, Integer> ();
    m_AllowedToChangeAmount = GECAMedModule.userHasPermission(IPatientPermissions.CHANGE_AMOUNT_OF_RATE);
    
    Vector<String> p_VTableHeaders = new Vector<String>();
    Vector<Integer> p_VViewToModel = new Vector<Integer>();
    
    // add columns and Headers
    p_VTableHeaders.add(c_IndexHeader);
    p_VViewToModel.add(c_IndexColumn);
    m_ColumnWidth.add(c_IndexColumnWidth);

    p_VTableHeaders.add(c_HospClassHeader);
    p_VViewToModel.add(c_HospClassColumn);
    m_ColumnWidth.add(c_HospClassColumnWidth);
    
    p_VTableHeaders.add(c_DateHeader);
    p_VViewToModel.add(c_DateColumn);
    m_ColumnWidth.add(c_DateColumnWidth);
    
    p_VTableHeaders.add(c_ShowTimeHeader);
    p_VViewToModel.add(c_ShowColumn);
    m_ColumnWidth.add(c_ShowColumnWidth);
    
    p_VTableHeaders.add(c_TimeHeader);
    p_VViewToModel.add(c_TimeColumn);
    m_ColumnWidth.add(c_TimeColumnWidth);

    if (p_ShowPhysicianColumn) {
    	p_VTableHeaders.add(c_PhysicianHeader);
    	p_VViewToModel.add(c_PhysicianColumn);    
    	m_ColumnWidth.add(c_PhysicianColumnWidth);    
    }

    p_VTableHeaders.add(c_CodeHeader);
    p_VViewToModel.add(c_CodeColumn);
    m_ColumnWidth.add(c_CodeColumnWidth);

    p_VTableHeaders.add(c_SuffixHeader);
    p_VViewToModel.add(c_SuffixColumn);
    m_ColumnWidth.add(c_SuffixColumnWidth);

    if (p_ShowInfoColumn) {
    	p_VTableHeaders.add(c_AdditionalInfoHeader);
    	p_VViewToModel.add(c_AdditionalInfoColumn);    	
    	m_ColumnWidth.add(c_AdditionalInfoColumnWidth);    	
    }
    
    p_VTableHeaders.add(c_LabelHeader);
    p_VViewToModel.add(c_LabelColumn);
    m_ColumnWidth.add(c_LabelColumnWidth);
    
    p_VTableHeaders.add(c_QuantityHeader);
    p_VViewToModel.add(c_QuantityColumn);
    m_ColumnWidth.add(c_QuantityColumnWidth);

    if (p_ShowAdjustColumn) {
	    p_VTableHeaders.add(c_AdjustmentHeader);
	    p_VViewToModel.add(c_AdjustmentColumn);
	    m_ColumnWidth.add(c_AdjustmentColumnWidth);
    }

    p_VTableHeaders.add(c_AmountHeader);
    p_VViewToModel.add(c_AmountColumn);
    m_ColumnWidth.add(c_AmountColumnWidth);

    if (p_ShowMedPrescColumn) {
    	p_VTableHeaders.add(c_MedPrescCodeHeader);
    	p_VViewToModel.add(c_MedPrescCodeColumn); 
    	m_ColumnWidth.add(c_MedPrescCodeColumnWidth); 
    }
    
    if (p_ShowUsernameColumn) {
    	p_VTableHeaders.add(c_UsernameHeader);
    	p_VViewToModel.add(c_UsernameColumn);    
    	m_ColumnWidth.add(c_UsernameColumnWidth);    
    }

    m_TableHeaders = p_VTableHeaders.toArray(new String[p_VTableHeaders.size()]);
    m_ViewToModel  = p_VViewToModel.toArray(new Integer[p_VViewToModel.size()]);
    
    m_ModelToView = new int [c_MaxColumns];
    
    for (l_Index = 0; l_Index < m_ViewToModel.length; l_Index++)
    	{
    	m_ModelToView [m_ViewToModel[l_Index]] = l_Index;
    	}
    }

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

private NomenclatureInterface getNomenclatureInterface ()
	{
	if (m_NomenclatureInterface != null) return m_NomenclatureInterface;
	
	try {
		m_NomenclatureInterface = (NomenclatureInterface) ManagerFactory.getRemote(NomenclatureBean.class);
		} 
	catch (Exception p_Exception) 
		{
		m_NomenclatureInterface = null;
		m_Logger.warn(p_Exception.getLocalizedMessage());
		}
	
	return m_NomenclatureInterface;
	}

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

private Rate lookupRate (String p_Code, boolean p_ExtractSuffix)
	{
	Rate					l_Rate;
	NomenclatureInterface	l_NomenclatureInterface;
	
	l_Rate		   	= null;
	l_NomenclatureInterface = this.getNomenclatureInterface();
	
	if (l_NomenclatureInterface != null)
		{
		try {
			l_Rate = l_NomenclatureInterface.getRateByCode (p_Code, null, p_ExtractSuffix);
			}
		catch (Exception p_Exception) 
			{
			if (p_Exception.getCause() instanceof NoResultException)
				 m_Logger.info ("Found no Rate for code " + p_Code);
			else m_Logger.warn(p_Exception.getLocalizedMessage());
			}
		}
	
	return l_Rate;
	}

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

private String getHospitalisationClass (Act p_Act)
	{
	String l_Class;
	Invoice l_Invoice;
	
	
	try
		{
		if (p_Act == null)
			return "";
		
		l_Class = p_Act.getHospitalisationClass();
		if (l_Class == null)
			{
			// be sure to have the correct invoice
			if (m_Invoice == null || 
					(m_Invoice.isPersistent()
							&& p_Act.getInvoiceId() != null
							&& !m_Invoice.getId().equals(p_Act.getInvoiceId())))
			{
				l_Invoice = getIncoiceManager().getInvoiceByID(p_Act.getInvoiceId());
				if (l_Invoice != null)
					m_Invoice = l_Invoice;
			}
			
			if (m_Invoice == null
					|| m_Invoice.getHospitalisationClass() == null
					|| m_Invoice.getHospitalisationClass().getAcronym() == null)
				l_Class = HospitalisationClass.c_Ambulant;
			else
				l_Class = m_Invoice.getHospitalisationClass().getAcronym().toUpperCase();
			}
		
		return l_Class;
		}
	catch (Exception e)
		{
		m_Logger.log(Level.ERROR, e.getMessage(), e);
		return "";
		}
	}

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

private InvoiceInterface getIncoiceManager ()
	{
	if (m_InvoiceManager == null)
		m_InvoiceManager = (InvoiceInterface) ManagerFactory.getRemote(InvoiceBean.class);
	
	return m_InvoiceManager;
	}


public void setInvoice (Invoice p_Invoice)
	{
	m_Invoice = p_Invoice;
	}


//public Invoice getInvoice ()
//{
//	return m_Invoice;
//}

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

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

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

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

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

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

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

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

public int getViewToModelColumn (int p_Column)
	{
	if (m_ViewToModel == null) return p_Column;
	
	if ((p_Column >= 0) && (p_Column < m_ViewToModel.length))
		{
		return m_ViewToModel [p_Column];
		}
	else return p_Column;
	}

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

public int getModelToViewColumn (int p_Column)
	{
	if (m_ModelToView == null) return p_Column;
	
	if ((p_Column >= 0) && (p_Column < m_ModelToView.length))
		{
		return m_ModelToView [p_Column];
		}
	else return p_Column;
	}

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

public Object getValueAt (int p_Row, int p_Column)
    {
    Act  l_Act;
    
    l_Act = new Act ();
    
    if ((p_Row >= 0) && (p_Row < m_Acts.size()))
        {
    		l_Act = m_Acts.elementAt (p_Row);
    		if (l_Act == null) l_Act = new Act ();
        }
	 
    p_Column = this.getViewToModelColumn (p_Column);
    
    switch (p_Column)
        {
        case  c_IndexColumn:	 		return Integer.valueOf(p_Row + 1);
        case  c_HospClassColumn: 		return getHospitalisationClass(l_Act);
        case  c_DateColumn: 	 		return l_Act.getPerformedDate();
        case  c_ShowColumn: 	 		return l_Act.getShowTime();       
        case  c_TimeColumn: 	 		return l_Act.getPerformedDate();
        case  c_PhysicianColumn: 		return (l_Act.getPhysicianId() != null)?l_Act.getPhysicianId():Integer.valueOf(0);
        case  c_CodeColumn: 	 		return l_Act.getCode();
        case  c_SuffixColumn: 	 		return (l_Act.getSuffixes() != null)?l_Act.getSuffixes():"";
        case  c_AdditionalInfoColumn:	return (l_Act.getAdditionalActInfo() != null)?l_Act.getAdditionalActInfo():"";
        case  c_LabelColumn: 	 		return l_Act.getLabel();
        case  c_QuantityColumn:  		return l_Act.getQuantity();
        case  c_AdjustmentColumn:		return (l_Act.getAdjustment() != null) ? l_Act.getAdjustment() : Act.DEFAULT_ADJUSTMENT;
        case  c_AmountColumn: 	 		return l_Act.monetize();
        case  c_MedPrescCodeColumn:		return (l_Act.getMedPrescCode() != null ? l_Act.getMedPrescCode() : "");
        case  c_UsernameColumn:  		return (l_Act.getUsername() != null ? l_Act.getUsername() : "");
//        case  c_AmountColumn: 	 return l_Act.getValue();
               
        default: return "";
        }
    }
        
//---------------------------------------------------------------------------

public void setValueAt (Object p_Value, int p_Row, int p_Column)
    {
	GregorianCalendar	l_OldDate;
	GregorianCalendar	l_NewDate;
	Rate 				l_Rate;
    Act					l_Act;
    String				l_Code;
    String				l_Suffix;
    Integer				l_Quantity;
    Integer				l_Adjustment;
    
	if (p_Row >= m_Acts.size() 
			|| p_Row < 0) 
		return;
    
    l_Act = (Act) m_Acts.elementAt (p_Row);
    if (l_Act == null) return;
    
    p_Column = this.getViewToModelColumn(p_Column);
    if (p_Value == null 
			&& p_Column != c_AmountColumn
			&& p_Column != c_MedPrescCodeColumn)
    	return;
    
    switch (p_Column)
		{
		case c_IndexColumn:
    		break;
    		
		case c_HospClassColumn:
			
			l_Act.setHospitalisationClass((String) p_Value, m_Invoice);
			m_Acts.setElementAt (l_Act, p_Row);
			break;
    		
		case  c_DateColumn: 
			
			l_OldDate = new GregorianCalendar();
			l_OldDate.setTime (l_Act.getPerformedDate());
				 
			l_NewDate = new GregorianCalendar();
			l_NewDate.setTime ((Date)p_Value);
			l_NewDate.set(Calendar.HOUR_OF_DAY,l_OldDate.get(Calendar.HOUR_OF_DAY));
			l_NewDate.set(Calendar.MINUTE,l_OldDate.get(Calendar.MINUTE));
			l_NewDate.set(Calendar.SECOND,0);
			l_NewDate.set(Calendar.MILLISECOND,0);
			
			// check for Actdate issues
			if (!BillingModule.getInstance().checkActDate(l_NewDate.getTime())) {
				return;
			}

			l_Act.setPerformedDate(l_NewDate.getTime());
			
			l_Code = l_Act.getCode();
			l_Quantity = l_Act.getQuantity();
			l_Adjustment = l_Act.getAdjustment();
			
//			l_Rate = this.lookupRate(l_Code, false);
//			if (l_Rate instanceof Rate)
//				{				
//				l_Rate.initializeAct (l_Act);
//				l_Act.setQuantity (l_Quantity);
//				}
			
			try {
				l_Act = getNomenclatureInterface().initializeAct(l_Code, l_Act);						
			} catch (Exception e) {
				m_Logger.error("Error initializing Act " + e.getMessage());
			}
			
			l_Act.setQuantity (l_Quantity);
			l_Act.setAdjustment(l_Adjustment);
			m_Acts.setElementAt (l_Act,p_Row);
			break;
		
		case  c_ShowColumn: 
			
			boolean l_ShowTime = ((Boolean)p_Value).booleanValue();
			
			if (l_Act.isShowTimeSet() == null && l_ShowTime)
			{
				Calendar cal = new GregorianCalendar();
				
				// round down on five minutes
				if (cal.get(Calendar.MINUTE) < 5)
					cal.set(Calendar.MINUTE, 	0);
				else 
					cal.set(Calendar.MINUTE, (cal.get(Calendar.MINUTE) / 5) * 5);
				cal.set(Calendar.SECOND, 		0);
				cal.set(Calendar.MILLISECOND, 	0);
				
				l_Act.setPerformedTime(cal);
			}
			
			l_Act.setShowTime(l_ShowTime);
			
			m_Acts.setElementAt (l_Act,p_Row);
			
			break;
		
		case  c_TimeColumn: 
			
			l_OldDate = new GregorianCalendar();
			l_OldDate.setTime (l_Act.getPerformedDate());
			l_NewDate = new GregorianCalendar();
			l_NewDate.setTime ((Date)p_Value);
			l_OldDate.set(Calendar.HOUR_OF_DAY,l_NewDate.get(Calendar.HOUR_OF_DAY));
			l_OldDate.set(Calendar.MINUTE,l_NewDate.get(Calendar.MINUTE));
			l_OldDate.set(Calendar.SECOND,0);
			l_OldDate.set(Calendar.MILLISECOND,0);
			l_Act.setPerformedDate(l_OldDate.getTime());
			l_Act.setShowTime(true);
			m_Acts.setElementAt (l_Act,p_Row);
			break;
		
		case c_PhysicianColumn:
			
			l_Act.setPhysicianId((Integer)p_Value);
			m_Acts.setElementAt (l_Act,p_Row);
			break;
		
		case  c_CodeColumn: 
			
			l_Code = (String) p_Value;
			
			if (l_Code.length() == 0) 
				{
				// TODO remove Act or not 
//				removeActAt(p_Row);
				}
			else
				{
				l_Rate = this.lookupRate(l_Code, true);
				if (l_Rate == null)
					{
//					removeActAt(p_Row);
					}
				else if (l_Rate instanceof Rate
						&& l_Act.getCode() != null 
						&& !l_Rate.getCode().toUpperCase().equals(
								l_Act.getCode().toUpperCase()))
					{
					try {
						l_Act = getNomenclatureInterface().initializeAct(l_Code, l_Act);						
					} catch (Exception e) {
						m_Logger.error("Error initializing Act", e);
					}
					
					l_Act.setQuantity(Integer.valueOf (1));
					m_Acts.setElementAt (l_Act,p_Row);
					l_Act.setFixAmount(null);
					
					if (l_Act.getCode() != null && l_Act.getCode().trim().length() > 0) {
						l_Suffix	= l_Code.substring(l_Act.getCode().length()).toUpperCase();
						if (!GECAMedUtils.isEmpty(l_Suffix))
							setValueAt(l_Suffix, p_Row, getModelToViewColumn(c_SuffixColumn));
					}						
					}
				}
			break;
				
		case  c_SuffixColumn: 
				 
			l_Act.setSuffixes((String)p_Value); 
			m_Acts.setElementAt (l_Act,p_Row);
			break;
		
		case  c_AdditionalInfoColumn: 
			
			l_Act.setAdditionalActInfo((String)p_Value);
			m_Acts.setElementAt (l_Act,p_Row);
			break;	
			
		case  c_LabelColumn: 
			
			l_Act.setLabel((String)p_Value);
			m_Acts.setElementAt (l_Act,p_Row);
			
			break;
		
		case  c_QuantityColumn: 
			
			try {
				l_Act.setQuantity ((Integer)p_Value);
				m_Acts.setElementAt (l_Act,p_Row);
				}
			catch (NumberFormatException p_Exception)	
				{
				}
			break;
		
		case  c_AdjustmentColumn:
			
			l_Act.setAdjustment((Integer)p_Value);
			m_Acts.setElementAt (l_Act,p_Row);
			break;	
			
		case  c_AmountColumn:
			
			l_Act.setValue((Double)p_Value);
			m_Acts.setElementAt (l_Act,p_Row);
			break;
			
		case  c_MedPrescCodeColumn:
			
			l_Act.setMedPrescCode((String)p_Value);
			m_Acts.setElementAt (l_Act,p_Row);
			break;
		}
    // set changed to ACT
    l_Act.setChanges(Act.CHANGED_USER);
    fireTableCellUpdated (p_Row,p_Column);
    }

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

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

//---------------------------------------------------------------------------
/**
 * queries the ability to be edited of the cell specified by p_Row and p_Column
 * @param p_Row specifies the row to be queried
 * @param p_Column specifies the column to be queried
 * @return <CODE>true</CODE> if the specified cell is editable, <CODE>false</CODE> otherwise
 */
//---------------------------------------------------------------------------

public boolean isCellEditable   (int p_Row, int p_Column)
    {
    if (m_Editable == false) return false;
	
   p_Column = this.getViewToModelColumn (p_Column);
     
    switch (p_Column)
        {
        case  c_IndexColumn:	 return false;
        case  c_HospClassColumn: return true;
        case  c_DateColumn: 	 return true;
        case  c_ShowColumn: 	 return true;    
        case  c_TimeColumn: 	 return true;
        case  c_PhysicianColumn: return true;
        case  c_AdditionalInfoColumn:return true;
        case  c_CodeColumn: 	 return true;
        case  c_SuffixColumn: 	 return true;
        case  c_LabelColumn: 	 return true;
        case  c_QuantityColumn:  return true;
        case  c_AdjustmentColumn:return m_AllowedToChangeAmount;
		case  c_AmountColumn: 	 return m_AllowedToChangeAmount;
		case  c_MedPrescCodeColumn:return true;
//		case  c_AmountColumn: 	 return false;
        
        default: return false;
        }
    }
    
//---------------------------------------------------------------------------

public Act	getActAt (int p_Row)
    {
    Act  l_Act;
     
    if ((p_Row >= 0) && (p_Row < m_Acts.size()))
        {
    	l_Act = m_Acts.elementAt (p_Row);
        return l_Act;
        }
    else return null;
    }
	
//---------------------------------------------------------------------------

public int addAct (Act p_Act)
{
	return addAct(p_Act, -1);
}


public int addAct (Act p_Act, int p_Row)
    {
	if (p_Act != null)
        {
		if (p_Act.getHospitalisationClass() == null) {
			p_Act.setHospitalisationClass(getHospitalisationClass(p_Act), m_Invoice);			
		}
		
		if (p_Row < 0 || p_Row > m_Acts.size())
			p_Row = m_Acts.size();
		
		m_Acts.add(p_Row, p_Act);
    	
		m_ActLookUp.put (p_Act.getCode(), Integer.valueOf (p_Row));        
    	fireTableRowsInserted (p_Row,p_Row);
    	
    	return p_Row;
        }
	else
		{
		return -1;
		}
    }
	
//---------------------------------------------------------------------------

public void removeAllActs ()
	{
	int	l_LastRow;
	
	l_LastRow = m_Acts.size() -1;
	
	m_Acts.removeAllElements ();
	m_ActLookUp.clear();
	
	if (l_LastRow >= 0) fireTableRowsDeleted (0,l_LastRow);
	}

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

public void removeActAt (int p_Row)
    {
    Act  l_Act;

    if ((p_Row >= 0) && (p_Row < m_Acts.size()))
        {
    		l_Act = m_Acts.elementAt (p_Row);
    		m_Acts.removeElementAt(p_Row);    
    		m_ActLookUp.remove (l_Act.getCode());       
    		fireTableRowsDeleted (p_Row,p_Row);
        }
    }

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

public int findAct (String p_Code)
    {
    Integer l_Row;
 	
    l_Row = m_ActLookUp.get (p_Code);
    
    if (l_Row != null)
        {
        return l_Row.intValue();
        }
    else return (-1);
    }

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

public void setMajoration (double p_Majoration)
	{
	if (p_Majoration != m_Majoration)
		{
		m_Majoration = p_Majoration;
		//this.fireTableDataChanged();
		}
	}

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

public void setEditable (boolean p_Editable)
	{
	m_Editable = p_Editable;
	}

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

public boolean isEditable ()
	{
	return m_Editable;
	}

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

public boolean physicianColumnShown ()
	{
	return m_ShowPhysicianColumn;
	}

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

public void setActs (Set <Act> p_Acts)
    {
    int				l_Row;
    Act				l_Act;
    Act []  		l_ActArray;
    ActComparator	l_Comparator;
    
    if (p_Acts == null) return;
        
    removeAllActs ();
    
	if (p_Acts.size() > 0)
		{
		l_ActArray = new Act[p_Acts.size()];
		l_ActArray = p_Acts.toArray(l_ActArray);
		
		l_Comparator = new ActComparator ();
		l_Comparator.addSortCriterion(ActComparator.c_PerformedDate, ActComparator.c_Ascending);
		l_Comparator.addSortCriterion(ActComparator.c_Id, ActComparator.c_Ascending);		
		Arrays.sort (l_ActArray,l_Comparator);
		   
		for (l_Row = 0; l_Row < p_Acts.size(); l_Row++)
		    {
			l_Act = l_ActArray [l_Row];	
			m_Acts.add(l_Act);
			m_ActLookUp.put (l_Act.getCode(), Integer.valueOf (l_Row));   
		    }
		}
		
    fireTableRowsInserted (0,m_Acts.size());
    }

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

public Set <Act> getActs ()
    {
	HashSet <Act> l_Acts;
	
	l_Acts = new HashSet <Act> (m_Acts);
	
	return l_Acts;
	}

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

public double getColumnWidth(int l_Index) {
	return m_ColumnWidth.get(l_Index);
}


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