/*******************************************************************************
 * 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.patient.gui.administrative;

import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import lu.tudor.santec.gecamed.address.gui.widgets.AddressPanel;
import lu.tudor.santec.gecamed.core.gui.GECAMedModule;
import lu.tudor.santec.gecamed.core.gui.widgets.HeaderedPanel;
import lu.tudor.santec.gecamed.core.gui.widgets.LimitTextField;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.Patient;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.PatientAddress;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.PatientContact;
import lu.tudor.santec.gecamed.patient.gui.PatientManagerModule;
import lu.tudor.santec.gecamed.patient.gui.simpleview.OverviewPanel;
import lu.tudor.santec.gecamed.patient.utils.SettingConstants;
import lu.tudor.santec.i18n.Translatrix;
import lu.tudor.santec.widgets.gui.ButtonFactory;

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

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

/**
 * Panel to display and edit the patients contact person, such as
 * facturation address or third pary payer
 * 
 *
 * @author Johannes Hermen johannes.hermen(at)tudor.lu
 *
 * @version
 * <br>$Log: PatientContactInfo.java,v $
 * <br>Revision 1.41  2013-12-27 18:07:59  donak
 * <br>Cleanup of imports
 * <br>
 * <br>Revision 1.40  2013-07-15 06:18:34  ferring
 * <br>logging changed
 * <br>
 * <br>Revision 1.39  2011-08-24 11:37:29  ferring
 * <br>Deadlock while opening patient solved
 * <br>
 * <br>Revision 1.38  2010-10-19 14:37:14  troth
 * <br>rename class SimpleViewPanel in OverviewPanel
 * <br>
 * <br>Revision 1.37  2010-07-05 12:17:17  hermen
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.36  2010-03-12 14:13:17  hermen
 * <br>icon cleanup
 * <br>
 * <br>Revision 1.35  2009-05-29 13:51:21  hermen
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.34  2008-12-18 13:08:38  mack
 * <br>Fixed a bug causing guarantor name being erased when copying address from patient
 * <br>
 * <br>Revision 1.33  2008-12-05 17:34:23  heinemann
 * <br>moved some basic classes to lu.tudor.santec.widgets
 * <br>
 * <br>Revision 1.32  2008-09-25 09:43:06  heinemann
 * <br>fixed copyrights
 * <br>
 * <br>Revision 1.31  2008-08-21 15:45:12  heinemann
 * <br>removed the bogus behaviour when there is no office entry in the database. The fields on the print outs are now left blank. The user gets an information that the office address is missing.
 * <br>
 * <br>Revision 1.30  2008-08-04 07:53:41  hermen
 * <br>fixed deleting/saving of assure principal
 * <br>
 * <br>Revision 1.29  2008-06-30 08:16:45  hermen
 * <br>added address autocompletion by locality
 * <br>
 * <br>Revision 1.28  2008-06-04 12:54:01  hermen
 * <br>fixed copy patient address to assure address
 * <br>
 * <br>Revision 1.27  2008-05-09 13:22:58  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.26  2008-04-16 14:24:28  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.25  2008-01-21 14:03:27  hermen
 * <br>updated Javadoc and refactured code
 * <br>
 *
 */
public class PatientContactInfo extends HeaderedPanel implements KeyListener, ItemListener, PropertyChangeListener, IPatientDataPanel, ActionListener 
{
    //~ Static fields/initializers =============================================
	/** the logger Object for this class */
	private static Logger logger = Logger.getLogger(PatientContactInfo.class.getName());

    private static final long serialVersionUID = 1L;
    
    private boolean ADDRESS_FACTURATION = true;
    

    //~ Instance fields ========================================================

    private JTextField name;

	private boolean listenersActivated = false;
	
	private PatientAdminPanel patientEditPanel;
	
	private PatientContact currentContact;
	private AddressPanel addressPanel;

	private JButton copyButton;

	private boolean editable;


    //~ Constructors ===========================================================
    /**
     * builds a new PatientInfo to show/edit general Patient Data
     */
    public PatientContactInfo(PatientAdminPanel patientEditPanel)
    {
    	this.setOpaque(false);
        this.patientEditPanel = patientEditPanel;
        
        try {
        	ADDRESS_FACTURATION = (Boolean) PatientManagerModule.getInstance().administrativeElementsPlugin.getValue(SettingConstants.ADDRESS_FACTURATION);
		} catch (Exception e) {
		}
        
        this.buildPanel();
    }

    //~ Methods ================================================================
    

    /**
     * adds the components to the panel
     */
    private void buildPanel() {
    	/* ================================================== */
	
    	String borderString = "";
    	if (ADDRESS_FACTURATION) {
    		borderString = Translatrix.getTranslationString(
    				"pm.address_facturation");
    	} else {
    		borderString = Translatrix.getTranslationString(
    				"pm.main_insurant");
    	}
    	this.setHeader(borderString);
//    	this.setHeaderIcon(PatientManagerModule.getMediumIcon(PatientManagerModule.BILLING_ALT));
    	this.enableAlpha(true);
        initComponents();
        
        CellConstraints cc = new CellConstraints();
        
        this.setLayout(new FormLayout(// cols
        							  "3dlu," +
        							  "right:pref," +
        							  "5dlu," +
        							  "fill:100dlu:grow," +
        							  "right:pref," +
        							  "3dlu",
        							  
        							  // rows
        							  "3dlu," +
        							  "fill:pref," +     // name
        							  "center:5dlu," + // separator
        							  "3dlu," +
        							  "15dlu," +         // empty line
        							  "3dlu," +
        							  "15dlu," +         // line for copy button
        							  "3dlu," +
        							  "fill:pref:grow," +     // adress
        							  "3dlu"));
        /* ------------------------------------------------------- */
        JLabel nameLabel = OverviewPanel.createLabel("pm.contact.name");
        /* ------------------------------------------------------- */
        this.copyButton = ButtonFactory.createEffectButton(GECAMedModule.getSmallIcon(GECAMedModule.COPY));
        copyButton.addActionListener(this);
        copyButton.setToolTipText(Translatrix.getTranslationString("pm.administrativeDataCopy"));
        /* ------------------------------------------------------- */
        // place the components
        /* ------------------------------------------------------- */
        this.add(nameLabel, cc.xy(2, 2));
        this.add(this.name, cc.xy(4, 2));
        this.add(new JSeparator(), cc.xyw(2, 3, 3));
        /* ------------------------------------------------------- */
        this.add(addressPanel, cc.xywh(2, 5, 3, 5));
        this.add(copyButton, cc.xy(5, 7));
        
        /* ------------------------------------------------------- */
        /* ================================================== */
    }

    /**
     * initializes the Components
     */
    private void initComponents()
    {
		this.name = new LimitTextField(70);
		this.name.addKeyListener(this);
		this.name.getDocument().addDocumentListener(new DocumentListener() 
		{
			public void removeUpdate(DocumentEvent e) {
				enableComponents();
			}
			public void insertUpdate(DocumentEvent e) {
				enableComponents();
			}
			public void changedUpdate(DocumentEvent e) {
			}
		});
    	
    	this.addressPanel = new AddressPanel(true);
    	this.addressPanel.addPropertyChangeListener(this);
    }

	/* (non-Javadoc)
	 * @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent)
	 */
	public void keyTyped(KeyEvent e) {
		this.patientEditPanel.setModified(true);
	}
	public void keyPressed(KeyEvent e) {
	}
	public void keyReleased(KeyEvent e) {
	}

	/* (non-Javadoc)
	 * @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent)
	 */
	public void itemStateChanged(ItemEvent e) {
		if (listenersActivated ) {
			this.patientEditPanel.setModified(true);
		}
	}
	
	/**
	 * returns the patient contact
	 * @param contact
	 */
	private void getcontact(PatientContact contact)
    {
			contact.setName(this.name.getText());
			
			contact.setZip(this.addressPanel.getZip());
	
			contact.setLocalityId(this.addressPanel.getLocalityID());
			
			contact.setLocality(this.addressPanel.getTfLocality());
	        
			contact.setStreetName(this.addressPanel.getStreetName());
			
			contact.setStreetNumber(this.addressPanel.getStreetNumber());
			
			contact.setCountry(this.addressPanel.getCountry());
			
	        if (contact.getDate() == null) {
	        	contact.setDate(new Date());
	        }
    }

	/**
	 * fills the fields of the panel with data from the passed PatientAddress
	 * object.
	 *
	 * @param contact the PatientAddress object to load the values from
	 */
	private void setContact(final PatientContact contact)
	{
		listenersActivated = false;
		
		/* **************************************** */
		// TODO: Deadlock problem: PatientContactInfo
		/* **************************************** */
		/* Problem was: Sometimes, while the PatientContactInfo is 
		 * initialised before the PatientAdminInfoPanel (admin -> 
		 * global settings -> patient panels) a deadlock appears while 
		 * trying to set the text of the JTextField name.
		 * By transferring this task to the event queue, the deadlock
		 * seems to be solved.
		 * Use invokeLater, because invokeAndWait did cause problems.
		 */
		try	{
			EventQueue.invokeLater(new Runnable()
			{
				public void run()
				{
					name.setText(contact.getName());
				}
			});
		} catch (Exception e) {
			logger.log(Level.ERROR, e.getMessage(), e);
		}
		/* **************************************** */
		
		this.addressPanel.setZip(contact.getZip());
		
		this.addressPanel.setLocalityID(contact.getLocalityId());	
		if (contact.getLocalityId() == null) {
			this.addressPanel.setLocality(contact.getLocality());	
		}
		
		this.addressPanel.setStreet(contact.getStreetName(), contact.getStreetNumber());
		
		this.addressPanel.setCountry(contact.getCountry());
		
		listenersActivated = true;
	}
	
	/* (non-Javadoc)
	 * @see lu.tudor.santec.gecamed.patient.gui.administrative.IPatientDataPanel#setPatient(lu.tudor.santec.gecamed.patient.ejb.entity.beans.Patient, boolean)
	 */
	public void setPatient(Patient patient, boolean editable) {
		this.editable = editable;
		try {
			this.currentContact = (PatientContact) patient.getContacts().toArray()[0];
		} catch (Exception e) {
			this.currentContact = new PatientContact();
			this.currentContact.setType("main_insurant");
		}
		this.setContact(this.currentContact);
		this.enableComponents();
//		this.setEditable(editable);
	}
	
//	/**
//	 * enables/disables editing of the panel
//	 * @param editable
//	 */
//	private void setEditable(boolean editable) {
//		this.name.setEditable(editable);
//		this.copyButton.setEnabled(editable);
//		this.addressPanel.setEditable(editable);
//	}

	/* (non-Javadoc)
	 * @see lu.tudor.santec.gecamed.patient.gui.administrative.IPatientDataPanel#getPatient(lu.tudor.santec.gecamed.patient.ejb.entity.beans.Patient)
	 */
	public void getPatient(Patient patient) {
		Set<PatientContact> al = patient.getContacts();
		
		
		
		if (al == null) {
			al = new HashSet<PatientContact>();
		} else {
			/* ------------------------------------------------------- */
			// delete all contacts
			al.clear();
			/* ------------------------------------------------------- */
		}
		this.getcontact(this.currentContact);
		this.currentContact.setPatientId(patient.getId());
		
//		// IF CONTACT IS ALLREADY SAVED, REMOVE TO ADD HIM LATER
//		if (this.currentContact.getId() != null) {
//			al.remove(this.currentContact);
//		} 
		
		// IF NAME IS NOT EMPTY, ADD
		if (! this.name.getText().trim().equals("")) {
			al.add(this.currentContact);
		}
		patient.setContacts(al);
	}
	
	/* (non-Javadoc)
	 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
	 */
	public void propertyChange(PropertyChangeEvent evt) {
		if (listenersActivated && evt.getPropertyName().equals(AddressPanel.UNSAVED_CHANGES)) {
			if (listenersActivated ) { 
				this.patientEditPanel.setModified(true);
			}
		}
	}
	
	public List<Component> getComponentsForFocus() {
		/* ====================================================== */
		List<Component> list = new ArrayList<Component>();
		/* ------------------------------------------------------- */
		list.add(name);
		list.addAll(addressPanel.getComponentsForFocus());
		/* ------------------------------------------------------- */
		return list;
		/* ====================================================== */
	}

	public void actionPerformed(ActionEvent e) {
		/* ====================================================== */
		if (this.copyButton.equals(e.getSource())) {
			/* ------------------------------------------------------- */
			// copy the address from the patient to this fields
			/* ------------------------------------------------------- */
			this.currentContact = new PatientContact();
			this.currentContact.setType("main_insurant");
			/* ------------------------------------------------------- */
			PatientAddress adr = this.patientEditPanel.getPatientAddress();
			if (adr != null) {
				/* ------------------------------------------------------- */
				this.currentContact.setName(this.name.getText());
				this.currentContact.setZip(adr.getZip());
				this.currentContact.setLocality(adr.getLocality());
				this.currentContact.setLocalityId(adr.getLocalityId());
				
				this.currentContact.setStreetName(adr.getStreetName());
				this.currentContact.setStreetNumber(adr.getStreetNumber());
				
				this.currentContact.setCountry(adr.getCountry());
				
				/* ------------------------------------------------------- */
			}
			
			this.setContact(this.currentContact);
			this.patientEditPanel.setModified(true);
			this.name.requestFocusInWindow();
			/* ------------------------------------------------------- */
		}
		/* ====================================================== */
	}
	
	public boolean isFilledOK() {
	    return true;
	}
	
	
	private void enableComponents() {
	 // IF NAME IS NOT EMPTY, ADD
	    this.name.setEditable(editable);
	    if (! this.name.getText().trim().equals("") && editable) {
		this.copyButton.setEnabled(true);
		this.addressPanel.setEditable(true);		    
	    } else {
		this.copyButton.setEnabled(false);
		this.addressPanel.setEditable(false);	
	    }
	}
	
}
