/*****************************************************************************
 *                                                                           *
 *  Copyright (c) 2010 by SANTEC/TUDOR www.santec.tudor.lu                   *
 *                                                                           *
 *                                                                           *
 *  This library is free software; you can redistribute it and/or modify it  *
 *  under the terms of the GNU Lesser General Public License as published    *
 *  by the Free Software Foundation; either version 2 of the License, or     *
 *  (at your option) any later version.                                      *
 *                                                                           *
 *  This software 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 along with this library; if not, write to the Free Software      *
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA  *
 *                                                                           *
 *****************************************************************************/
package lu.tudor.santec.gecamed.agenda.gui.widgets;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import java.util.TreeSet;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.undo.UndoManager;

import lu.tudor.santec.gecamed.agenda.ejb.entity.beans.AgendaCalendar;
import lu.tudor.santec.gecamed.agenda.ejb.entity.beans.Appointment;
import lu.tudor.santec.gecamed.agenda.ejb.entity.beans.AppointmentType;
import lu.tudor.santec.gecamed.agenda.ejb.session.beans.AppointmentManagerBean;
import lu.tudor.santec.gecamed.agenda.ejb.session.interfaces.AppointmentManager;
import lu.tudor.santec.gecamed.agenda.gui.AgendaAdminSettingsPlugin;
import lu.tudor.santec.gecamed.agenda.gui.AgendaModule;
import lu.tudor.santec.gecamed.agenda.gui.widgets.appointmenttype.AppointmentTypeComboBoxRenderer;
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.utils.UndoTextArea;
import lu.tudor.santec.gecamed.core.gui.widgets.DateTimeChooser;
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.Patient;
import lu.tudor.santec.gecamed.patient.ejb.session.beans.PatientAdminBean;
import lu.tudor.santec.gecamed.patient.ejb.session.interfaces.PatientAdminInterface;
import lu.tudor.santec.gecamed.patient.gui.PatientCreateDialog;
import lu.tudor.santec.gecamed.patient.gui.PatientManagerIconNames;
import lu.tudor.santec.gecamed.patient.gui.PatientManagerModule;
import lu.tudor.santec.gecamed.patient.gui.patientlist.PatientSearchDialog;
import lu.tudor.santec.gecamed.usermanagement.ejb.session.beans.LoginBean;
import lu.tudor.santec.gecamed.usermanagement.ejb.session.interfaces.LoginInterface;
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.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

/**
 * Panel that extends abstract AppointmentEditPanel to edit the general information of
 * an Appointment like patient name, description, calendar, appointment type, start,end date
 * 
 * 
 * @author martin.heinemann@tudor.lu
 * 29.05.2007
 * 10:32:02
 *
 *
 * @version
 * <br>$Log: GeneralPanel.java,v $
 * <br>Revision 1.52  2013-12-27 18:08:44  donak
 * <br>Cleanup of imports
 * <br>
 * <br>Revision 1.51  2013-07-15 06:18:35  ferring
 * <br>logging changed
 * <br>
 * <br>Revision 1.50  2013-02-19 12:07:34  ferring
 * <br>GECAMedLists changed. Will now automatically load list of all beans
 * <br>
 * <br>Revision 1.49  2012-04-23 11:22:54  troth
 * <br>fix Ticket #977 Java Error beim �ndern eines Kalendereintrages.
 * <br>
 * <br>Revision 1.48  2012-04-12 15:29:57  troth
 * <br>Release new search dialog panel.
 * <br>
 * <br>Revision 1.47  2012-03-20 14:16:11  troth
 * <br>Fix two small bugs:
 * <br>1. Create and delete a calendar causes a null-pointer-exception because the  property-change-listener calls the action performed method of the gCalendarBox.
 * <br>2. If closing the CreateCalendarDialog over the window close button creates a calendar.
 * <br>
 * <br>Revision 1.46  2012-03-13 17:15:09  troth
 * <br>Add testversion of new PatientSearchDialog in first step only in the agenda GeneralPanel in the AppointmentDialog.
 * <br>
 * <br>Revision 1.45  2011-11-28 16:22:57  troth
 * <br>'system.out.println'-warring are now written in the agenda logger
 * <br>
 * <br>Revision 1.44  2011-11-07 15:35:24  troth
 * <br>Fix some GUI Bugs.
 * <br>
 * <br>Revision 1.43  2011-10-24 14:16:17  troth
 * <br>Code Cleanup
 * <br>
 * <br>Revision 1.42  2011-10-20 15:04:28  troth
 * <br>1. add new functions of ticket #879
 * <br>2. fix ticket #904
 * <br>3. new bizcal lib
 * <br>
 * <br>Revision 1.41  2011-10-05 15:28:13  troth
 * <br>Do some translations for Ticket #879.
 * <br>
 * <br>Revision 1.40  2011-10-05 10:55:25  troth
 * <br>Ticket #892 fix GUI Bug
 * <br>
 * <br>Revision 1.39  2011-10-04 12:13:32  troth
 * <br>fix Ticket #892 - Patient matricule and treatment type automatically added to agenda entry description
 * <br>
 * <br>Revision 1.38  2011-08-05 15:06:07  troth
 * <br>fix ticket #891
 * <br>
 * <br>Revision 1.37  2011-08-03 14:02:37  troth
 * <br>code clearup
 * <br>
 * <br>Revision 1.36  2011-08-02 15:57:47  troth
 * <br>Fix ticket #871
 * <br>
 * <br>Revision 1.35  2011-08-01 14:58:44  troth
 * <br>Fix tickets #874 #839.
 * <br>
 * <br>Revision 1.34  2011-05-09 14:30:20  troth
 * <br>Fix Ticket 839: "End after [X] occurrences" not taken into account
 * <br>http://santec.tudor.lu/trac/gecamed/ticket/839
 * <br>
 * <br>Revision 1.33  2011-05-06 09:36:16  troth
 * <br>Fix Bug: If the appointment end time is earlier or equal the start time the appointment are not draw in the agenda views. Now the end time get a auto increase of 5 min in this situation.
 * <br>
 * <br>Revision 1.32  2011-04-04 11:38:30  troth
 * <br>Redesign of the appointment create dialog and the right navi bar.
 * <br>
 * <br>Revision 1.31  2010-08-18 13:58:21  troth
 * <br>Add a small patient create dialog to Agenda-, Waitingroom- module | Incomplete - # 608: Agenda/Waitingroom
 * <br>http://santec.tudor.lu/trac/gecamed/ticket/608
 * <br>
 * <br>Revision 1.30  2010-04-21 09:41:59  hermen
 * <br>small bugfixes
 * <br>
 * <br>Revision 1.29  2008-10-21 12:28:27  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.28  2008-09-25 09:42:27  heinemann
 * <br>fixed copyrights
 * <br>
 * <br>Revision 1.27  2008-08-19 10:25:08  heinemann
 * <br>cleanup
 * <br>
 * <br>Revision 1.26  2008-07-04 13:38:58  heinemann
 * <br>fixed generic casting that the new eclipse does not want to accept.
 * <br>
 * <br>Revision 1.25  2008-06-24 13:18:48  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.24  2008-05-30 11:46:43  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.23  2008-01-18 16:09:05  heinemann
 * <br>code cleanup and java doc
 * <br>
 * <br>Revision 1.22  2007-11-20 08:58:54  hermen
 * <br>moved Managerfactory to core.utils and refactured code to use ManagerFactory instead of context.lookup
 * <br>
 * <br>Revision 1.1  2007/06/12 08:14:38  hermen
 * <br>split up NewAppointmentDialog and added HolidayPanel
 * <br>
 *
 */
public class GeneralPanel extends AppointmentEditPanel{

	private static final long serialVersionUID = 1L;
	
	/** the logger Object for this class */
	private static Logger logger = Logger.getLogger(GeneralPanel.class.getName());
	
	public static final String PATIENT_ID_CHANGED = "patientidchanged";
	
	public static final String DATE_INTERVAL_CHANGED = "date_interval_changed";
	
	public static final String AUTO_DESCRIPTION_MATR_STRING = "MATR: ";
	
	public static final String AUTO_DESCRIPTION_TYPE_STRING = "TYPE: ";
	
	public static final String AUTO_DESCRIPTION_ID_STRING = "ID:";
	
	/**
	 * Intervals for timeslots
	 */
	private final Integer[] intervals = new Integer[] {
			05,10,15,20,25,30,40,45,50
	};

	private JLabel gNameLabel;

	private JTextField gNameTextField;

	private JLabel gDescriptionLabel;
	
	private JLabel matriculeLabel;

	private JTextArea gDescriptionTextArea;

	private JScrollPane gDescriptionScroll;

	private JLabel gTypeLabel;

	private JComboBox gTypeBox;

	private JLabel gCalendarLabel;

	private JComboBox gCalendarBox;

	private JPanel gTypePanel;

	private JLabel gStartLabel;

	private DateTimeChooser gStartChooser;

	private JLabel gDurationLabel;

	private JComboBox gDurationBox;

	private JLabel gEndLabel;

	private DateTimeChooser gEndChooser;

	private JPanel gTimePanel;

	private AbstractAction cancelAction;

	private JButton gNameSearchButton;

	private JButton gCreatePatientButton;
	
	private AbstractAction searchPatientAction;
	
	private AbstractAction createPatientAction;

	protected Integer patientID;

	private Icon icon = AgendaModule.getMediumIcon(AgendaModule.ICON_NEW_APPOINTMENT);

	private JPanel privatePanel;

	private JCheckBox gPrivateBox;

	protected Patient lastPatient;

	private JPanel createdByPanel;

	private JLabel createdLabel;

	protected boolean enableNameDocumentListener = true;

	private boolean enableComboboxActionListener = true;

	private boolean blockTypeListeners = false;

	private DateFormat formater = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
		
	private JPanel recurrencePanel;
	
	private JButton recurrenceButton;
	
	private AbstractAction recurrenceAction;
	
	private JLabel recurrenceStatusLabel;
	
	private RecurrenceOptionDialog recurrenceOptionDialog = RecurrenceOptionDialog.getInstance();

	private Appointment appointment;
	
	private Boolean blockStartChooserListener = false;
	
	private Boolean blockEndChooserListener = false;
	
	private Boolean blockDurationBoxListner = false;
	
	private Boolean resumeShowed=false;
	
	private String descriptionText="";
	
	/**
	 * Needed beans
	 */
	private static PatientAdminInterface patientManager;
	
	/**
	 * Initialize all needed beans
	 */
	static
	{
		try{
			patientManager = (PatientAdminInterface) ManagerFactory.getRemote(PatientAdminBean.class);
		} catch (Exception e) {
			logger.log(Level.WARN, "Couldn't set appointment-, patient- and physician- Bean in AgendaModule for log appointment modification.", e);
		}
	}
	
	/**
	 *
	 */
	public GeneralPanel() {
	/* ================================================== */
		initComponents();
		initButtonActions();
		initDateChooserActions();
		initComboBoxes();
		initKeyListener();
		initDocumentListener();
	/* ================================================== */
	}

	/**
	 * Updates the forms with the data from the appointment object
	 */
	public void setAppointment(Appointment appointment)
	{
		/* ================================================== */
		blockStartChooserListener = true;
		blockEndChooserListener = true;
		blockDurationBoxListner = true;
		/* ------------------------------------------------------- */
		enableNameDocumentListener = false;
		/* ------------------------------------------------------- */
		this.gNameTextField.setText((appointment.getSummary() != null ?
										appointment.getSummary()
										: ""));
		/* ------------------------------------------------------- */
		// cut the auto description
		String description = "";
		
		if(appointment.getDescription() != null)
			description = appointment.getDescription();
		
		if(appointment.getPatientId() != null)
		{
			if(description.contains(AUTO_DESCRIPTION_MATR_STRING))
			{
				// get matricule from description
				String matricule = description.substring(description.indexOf(" "), description.indexOf("\n"));
				// cut matricule
				description = description.substring(description.indexOf("\n") + 1, description.length());	
				// set ssn label
				this.matriculeLabel.setText(Translatrix.getTranslationString("calendar.newEvent.ssn") + ": " + matricule);
			}else this.matriculeLabel.setText("");
			if(description.contains(AUTO_DESCRIPTION_TYPE_STRING))
			{
				// cut type
				description = description.substring(description.indexOf("\n") + 1, description.length());
			}
			if(description.contains(AUTO_DESCRIPTION_ID_STRING))
			{
				// cut id
				description = description.substring(description.indexOf("\n") + 1, description.length());
			}
		}else{
			this.matriculeLabel.setText("");
		}
		this.gDescriptionTextArea.setText(description);
		/* ------------------------------------------------------- */
		this.enableComboboxActionListener = false;
		this.gCalendarBox.setSelectedItem(AgendaModule.getCalendarForId(appointment.getCalendarId()));
		refreshAppointmentTypes(false);
		this.enableComboboxActionListener = true;
		/* ------------------------------------------------------- */
		// the appointment does not have an AppointmentType, select the first
		// item in the combobox
		if (appointment.getTypeId() == null) {
			try {
				this.gTypeBox.setSelectedIndex(0);
			} catch (Exception e) {}
		}
		else
			this.gTypeBox.setSelectedItem(AgendaModule.getTypeForId(appointment.getTypeId()));
		/* ------------------------------------------------------- */
		this.gStartChooser.setDate(appointment.getStartDate());
		this.gEndChooser.setDate(appointment.getEndDate());
		/* ------------------------------------------------------- */
		this.gPrivateBox.setSelected(appointment.isPrivate());
		/* ------------------------------------------------------- */
		this.patientID = appointment.getPatientId();

		/* ------------------------------------------------------- */
		// user information
		LoginInterface loginManager = (LoginInterface) ManagerFactory.getRemote(LoginBean.class);
		String s = "<html><span style=\"font-weight:normal; font-size:8px;\">";
		if (appointment.getCreated() != null) {
			s += formater.format(appointment.getCreated())+"<br>";
		}
		if (appointment.getCreatedBy() != null) {
			try {
	            s += (loginManager.getUser(appointment.getCreatedBy()).toString());
	        } catch (Exception e1) {
	        	e1.printStackTrace();
	        }
		}
		enableNameDocumentListener = true;
		
		checkMarkPrivateAllowed();
		
		firePropertyChange(PATIENT_ID_CHANGED, "old", appointment.getPatientId());
		this.createdLabel.setText(s);
		this.createdLabel.validate();
		this.createdLabel.updateUI();
		this.appointment = (Appointment) appointment.clone();
		
		// calculate and set the duration
		calculateDuration();
		blockStartChooserListener = false;
		blockEndChooserListener = false;
		blockDurationBoxListner = false;
		/* ================================================== */
	}


	/**
	 * Fills the appointment with the data from the form fields
	 */
	public void getAppointment(Appointment appointment) {
		/* ================================================== */
		if (appointment == null)
			return;
//			this.appointment = new Appointment();
		/* ------------------------------------------------------- */
		// name
		appointment.setSummary(this.gNameTextField.getText());
		
		/* ------------------------------------------------------- */
		// type
		try {
			appointment.setTypeId(((AppointmentType) this.gTypeBox.getSelectedItem()).getId());
		} catch (Exception e) {
			logger.warn("Appointment does not have an ApointmentType!!  Loosing apoointment ....!");
		}
		/* ------------------------------------------------------- */
		// calendar
		try {
			appointment.setCalendarId(((AgendaCalendar) this.gCalendarBox.getSelectedItem()).getId());
		} catch (Exception e) {
			logger.warn("Appointment does not have a Calendar!!  Loosing apoointment ....!");
		}
		/* ------------------------------------------------------- */
		// start time
		appointment.setStartDate(this.gStartChooser.getDate());
		// end time
		// if start and end time are equal increase end time (5 min)
		long diffTime = this.gEndChooser.getDate().getTime() - this.gStartChooser.getDate().getTime();
		if(diffTime <= 0)
		{
			long fiveMin = 5 * 60 * 1000;
			Date newEndDate = new Date(this.gStartChooser.getDate().getTime() + fiveMin);	
			appointment.setEndDate(newEndDate);
		}else appointment.setEndDate(this.gEndChooser.getDate());
		// patient id
		appointment.setPatientId(this.patientID);
		// background
		appointment.setIsBackground(false);
		// private
		appointment.setPrivate(this.gPrivateBox.isSelected());
		// description
		Boolean autoDescriptionMatr = ((Boolean) AgendaModule.agendaAdminSettingsPlugin.getValue(AgendaAdminSettingsPlugin.AUTO_DESCRIPTION_MATR));
		Boolean autoDescriptionType = ((Boolean) AgendaModule.agendaAdminSettingsPlugin.getValue(AgendaAdminSettingsPlugin.AUTO_DESCRIPTION_TYPE));
		Boolean autoDescriptionID = ((Boolean) AgendaModule.agendaAdminSettingsPlugin.getValue(AgendaAdminSettingsPlugin.AUTO_DESCRIPTION_ID));
		
		// get the patient	
		Patient patient = null;
		try {
			if (appointment.getPatientId() != null) {
				patient = patientManager.getPatient(appointment.getPatientId());				
			}
		} catch (Exception e) {
			logger.log(Level.WARN, "Couldn't set patient for auto description of appointment.");					
		}
		
		
		
		
			descriptionText = "";
			
		// check if AUTO_DESCRIPTION_MATR is set
		if(autoDescriptionMatr && patient != null) {
			descriptionText = AUTO_DESCRIPTION_MATR_STRING + patient.getSocialSecurityNumber() + "\n";
		}
		
		

		// check if AUTO_DESCRIPTION_TYPE is set
		if(autoDescriptionType)
		{	
			// get the appointment type
			//				if (GECAMedLists.getArray(AppointmentType.class) == null) {
			//					AgendaModule.loadApointmentTypes();
			//				}
			List<AppointmentType> ap = GECAMedLists.getListReference(AppointmentType.class);
			for (AppointmentType appointmentType : ap) {
				if (appointmentType.getId().equals(appointment.getTypeId())) {
					descriptionText = descriptionText + AUTO_DESCRIPTION_TYPE_STRING + appointmentType.getName()  + "\n";
					break;
				}
			}
		}
		
	
		if(autoDescriptionID && patient != null) {
			descriptionText =  descriptionText + AUTO_DESCRIPTION_ID_STRING + patient.getId() + "\n";
		}

		
		descriptionText = descriptionText + this.gDescriptionTextArea.getText();
		appointment.setDescription(descriptionText);
	
		
		// recurrenceAction
		this.recurrenceOptionDialog.getAppointment(appointment);
		/* ================================================== */
	}
	
	
	public Date getStartDate() {
		/* ================================================== */
		return this.gStartChooser.getDate();
		/* ================================================== */
	}
	
	public Date getEndDate() {
		/* ================================================== */
		return this.gEndChooser.getDate();
		/* ================================================== */
	}

	/**
	 * Init component
	 */
	private void initComponents() {
		/* ================================================== */
		CellConstraints cc = new CellConstraints();
		this.setLayout(new FormLayout(
				// cols
				"3dlu," +
				"fill:155dlu," + 	// left site
				"3dlu," +
				"fill:pref," + 		// seperator
				"3dlu," +
				"fill:pref," + 		// right site
				"3dlu",
				// rows
				"3dlu," +			// 1
				"fill:pref," +		// 2
				"3dlu," +			// 3
				"fill:pref," +		// 4
				"2dlu," +			// 5
				"fill:pref," +		// 6
				"5dlu," +			// 7
				"fill:pref," +		// 8
				"5dlu," +			// 9
				"fill:pref," +		// 10
				"2dlu," +			// 11
				"fill:33dlu," +		// 12
				"5dlu," +			// 13
				"fill:pref," +  	// 14
				"3dlu," +			// 15
				"fill:pref," +  	// 16
				"3dlu," +			// 17
				"fill:pref," +  	// 18
				"pref:grow," +		// 19
				"3dlu" 				// 20
				));
		this.setOpaque(false);
		
		// -------------------------------------------------------
		// explanation text
		// -------------------------------------------------------
		JTextArea explanationTextArea = new JTextArea(Translatrix.getTranslationString("Agenda.appointment.explanation"));
		explanationTextArea.setPreferredSize(new Dimension(200, 60));
		// set font of text field to bold
		explanationTextArea.setFont(new Font(explanationTextArea.getFont().getName(), Font.BOLD, explanationTextArea.getFont().getSize()));
		explanationTextArea.setWrapStyleWord(true);
		explanationTextArea.setEditable(false);
		explanationTextArea.setLineWrap(true);
		explanationTextArea.setOpaque(true);
		explanationTextArea.setBackground(Color.WHITE);
		explanationTextArea.setBorder(BorderFactory.createTitledBorder(""));
		
		/* ------------------------------------------------------- */
		// name
		/* ------------------------------------------------------- */
		this.gNameLabel = new JLabel(Translatrix.getTranslationString("calendar.core.name")+":");
		//this.gNameLabel.setIcon(AgendaModule.getMediumIcon(AgendaModule.PATIENT));
		this.gNameLabel.setHorizontalTextPosition(SwingConstants.RIGHT);
		// TODO autocompletion
		this.gNameTextField = new JTextField(20);
		this.gNameTextField.setToolTipText(Translatrix.getTranslationString("calendar.newEvent.searchPatient"));
		/* ------------------------------------------------------- */
		// TODO may be make the buttons smaller
		this.gNameSearchButton = ButtonFactory.createEffectButton(GECAMedModule.getMiniIcon(GECAMedIconNames.SEARCH));
		this.gCreatePatientButton = ButtonFactory.createEffectButton(PatientManagerModule.getMiniIcon(PatientManagerIconNames.PATIENT_NEW));
		// panel for textfield and search button
		JPanel searchPanel = new JPanel(new FormLayout(
				// cols
				"pref:grow," +	// searchField
				"fill:15dlu," +	// searchButton
				"fill:15dlu",	// createPatientButton
				// rows
				"pref:grow"
				));
		searchPanel.setOpaque(false);
		searchPanel.add(this.gNameTextField, cc.xy(1, 1));
		searchPanel.add(this.gNameSearchButton, cc.xy(2, 1));
		searchPanel.add(this.gCreatePatientButton, cc.xy(3, 1));
		
		/* ------------------------------------------------------- */
		// matricule
		/* ------------------------------------------------------- */
		this.matriculeLabel = new JLabel("");
		
		/* ------------------------------------------------------- */
		// description
		/* ------------------------------------------------------- */
		this.gDescriptionLabel = new JLabel(Translatrix.getTranslationString("calendar.core.description")+":");
		this.gDescriptionLabel.setIcon(AgendaModule.getMediumIcon(AgendaModule.PATIENT_FILE));
		this.gDescriptionLabel.setHorizontalTextPosition(SwingConstants.RIGHT);

		this.gDescriptionTextArea = new UndoTextArea(new UndoManager());
		this.gDescriptionTextArea.setLineWrap(true);
		this.gDescriptionTextArea.setWrapStyleWord(true);

		// scrollpane
		this.gDescriptionScroll = new JScrollPane(this.gDescriptionTextArea);
		/* ------------------------------------------------------- */

		/* ------------------------------------------------------- */
		// type
		/* ------------------------------------------------------- */
		this.gTypeLabel = new JLabel(Translatrix.getTranslationString("calendar.core.type")+":");
		this.gTypeLabel.setIcon(AgendaModule.getMiniIcon(AgendaModule.TYPE));
		this.gTypeLabel.setHorizontalTextPosition(SwingConstants.RIGHT);

		this.gTypeBox = new JComboBox();

		/* ------------------------------------------------------- */
		// calendar
		/* ------------------------------------------------------- */
		this.gCalendarLabel = new JLabel(Translatrix.getTranslationString("calendar")+":");
		this.gCalendarLabel.setIcon(AgendaModule.getMiniIcon(AgendaModule.ICON_AGENDA));
		this.gCalendarLabel.setHorizontalTextPosition(SwingConstants.RIGHT);

		this.gCalendarBox = new JComboBox();

		/* ------------------------------------------------------- */
		// panel
		/* ------------------------------------------------------- */
		this.gTypePanel = new JPanel(new FormLayout(
				// cols
				"3dlu, fill:pref:grow,3dlu",
				//rows
				"3dlu," +
				"fill:pref," +
				"2dlu," +
				"fill:pref," +
				"3dlu," +
				"fill:pref," +
				"2dlu," +
				"fill:pref," +
				"3dlu"));
		this.gTypePanel.add(this.gCalendarLabel, cc.xy(2, 2));
		this.gTypePanel.add(this.gCalendarBox, cc.xy(2, 4));

		this.gTypePanel.add(this.gTypeLabel, cc.xy(2, 6));
		this.gTypePanel.add(this.gTypeBox, cc.xy(2, 8));

		this.gTypePanel.setBorder(BorderFactory.createTitledBorder(Translatrix.getTranslationString("calendar")));
		this.gTypePanel.setOpaque(false);
		/* ------------------------------------------------------- */
		// time panel
		/* ------------------------------------------------------- */
		// start
		/* ------------------------------------------------------- */
		this.gStartLabel = new JLabel(Translatrix.getTranslationString("calendar.start")+":");
		this.gStartLabel.setIcon(AgendaModule.getMiniIcon(AgendaModule.TIME_START));
		this.gStartLabel.setHorizontalTextPosition(SwingConstants.RIGHT);
		this.gStartChooser = new DateTimeChooser("HH:mm", DateTimeChooser.DATE_TIME);
		this.gStartChooser.setDate(new Date());
		/* ------------------------------------------------------- */
		// duration
		/* ------------------------------------------------------- */
		this.gDurationLabel = new JLabel(Translatrix.getTranslationString("calendar.duration")+":");
		this.gDurationBox = new JComboBox();
		//this.gDurationBox.enableInputMethods(true);
		this.gDurationBox.setEditable(true);
		// a panel
		JPanel durationPanel = new JPanel(new BorderLayout());
		durationPanel.add(this.gDurationBox, BorderLayout.CENTER);
		JLabel durationMinLabel = new JLabel(" " + Translatrix.getTranslationString("calendar.newEvent.min"));
		durationMinLabel.setVerticalAlignment(SwingConstants.BOTTOM);

//		durationPanel.add(durationMinLabel, BorderLayout.EAST);

		durationPanel.setOpaque(false);
		/* ------------------------------------------------------- */
		// end
		/* ------------------------------------------------------- */
		this.gEndLabel = new JLabel(Translatrix.getTranslationString("calendar.end"));
		this.gEndLabel.setIcon(AgendaModule.getMiniIcon(AgendaModule.TIME_STOP));
		this.gEndLabel.setHorizontalTextPosition(SwingConstants.RIGHT);


		this.gEndChooser = new DateTimeChooser("HH:mm", DateTimeChooser.DATE_TIME);
		this.gEndChooser.setOpaque(false);
		/* ------------------------------------------------------- */
		// time panel
		/* ------------------------------------------------------- */
		this.gTimePanel = new JPanel(new FormLayout(
				// cols
				"3dlu," +
				"45dlu:grow," +
				"fill:pref," +
				"3dlu," +
				"fill:pref," +
				"3dlu",
				//rows
				"3dlu," +		// 1
				"fill:pref," +	// 2
				"2dlu," +		// 3
				"fill:pref," +	// 4
				"3dlu," +		// 5
				"fill:pref," +	// 6 duration
				"3dlu," +		// 7
				"fill:pref," +	// 8 separator
				"3dlu," +		// 9
				"fill:pref," +	// 10
				"3dlu," +		// 11
				"fill:pref," +	// 12
				"3dlu"));		// 13

		this.gTimePanel.setOpaque(false);
		this.gTimePanel.setBorder(BorderFactory.createTitledBorder(Translatrix.getTranslationString("calendar.newEvent.periode")));
		/* ------------------------------------------------------- */
		this.gTimePanel.add(this.gStartLabel, cc.xyw(2, 2, 2));
		this.gTimePanel.add(this.gStartChooser, cc.xyw(2, 4, 4));
		this.gTimePanel.add(this.gDurationLabel, cc.xy(3, 6));
		this.gTimePanel.add(durationPanel, cc.xy(5, 6));

		this.gTimePanel.add(new JSeparator(), cc.xyw(2, 8, 4));

		this.gTimePanel.add(this.gEndLabel, cc.xyw(2, 10, 2));
		this.gTimePanel.add(this.gEndChooser, cc.xyw(2, 12, 4));
		/* ------------------------------------------------------- */


		// =====================================================
		// private panel
		// =====================================================
		this.privatePanel = new JPanel(new BorderLayout());
		this.privatePanel.setBorder(BorderFactory.createTitledBorder(Translatrix.getTranslationString("calendar.newEvent.private")));

		this.privatePanel.setOpaque(false);

		this.gPrivateBox = new JCheckBox(Translatrix.getTranslationString("calendar.newEvent.setPrivate"), false);
		this.gPrivateBox.setOpaque(false);
		this.gPrivateBox.setEnabled(false);
		
		this.gPrivateBox.setVerticalTextPosition(SwingConstants.TOP);

		this.privatePanel.add(this.gPrivateBox, BorderLayout.WEST);
		
		// ======================================================
		// created by panel
		// ======================================================
		this.createdByPanel = new JPanel(new BorderLayout());
		
		this.createdByPanel.setBorder(BorderFactory.createTitledBorder(Translatrix.getTranslationString("calendar.newEvent.create")));
		this.createdByPanel.setOpaque(false);
		
		this.createdLabel = new JLabel();
		this.createdByPanel.add(this.createdLabel, BorderLayout.WEST);
		
		// ======================================================
		// recurrence panel
		// ======================================================
		
		this.recurrencePanel = new JPanel(new BorderLayout());
		this.recurrencePanel.setBorder(BorderFactory.createTitledBorder(""));
		this.recurrencePanel.setOpaque(false);
		
		this.recurrenceButton = new JButton("recurrence");
		this.recurrencePanel.add(this.recurrenceButton, BorderLayout.WEST);
		
		this.recurrenceStatusLabel = new JLabel(" " + "no recurrence for this appointment");
		this.recurrencePanel.add(this.recurrenceStatusLabel, BorderLayout.CENTER);
		
		/* ------------------------------------------------------- */
		// assemble general panel
		/* ------------------------------------------------------- */

		this.add(explanationTextArea, cc.xywh(2, 2, 5, 1));
		
		this.add(this.gNameLabel, cc.xy(2, 4));
		this.add(searchPanel , cc.xy(2, 6));

		this.add(this.matriculeLabel , cc.xy(2, 8));
		this.add(this.gDescriptionLabel , cc.xy(2, 10));
		
		this.add(this.gDescriptionScroll , cc.xywh(2, 12, 1, 3));
		
		this.add(this.createdByPanel, cc.xy(2, 16));
		
		this.add(this.gTypePanel , cc.xywh(6, 4, 1, 9)); 
		this.add(this.gTimePanel , cc.xywh(6, 14, 1, 1));
		
		this.add(this.privatePanel , cc.xywh(6, 16, 1, 1));
		
		this.add(this.recurrencePanel, cc.xywh(2, 18, 5, 1));
		
		/* ================================================== */
	}
	
	
	/**
	 * Inits the documentlistener for the patient name textfield
	 */
	private void initDocumentListener() {
		/* ================================================== */
		this.gNameTextField.getDocument().addDocumentListener(new DocumentListener() {

			public void changedUpdate(DocumentEvent e) {
				/* ====================================================== */
				checkPatientValidity();
				/* ====================================================== */
			}

			public void insertUpdate(DocumentEvent e) {
				/* ====================================================== */
				checkPatientValidity();
				/* ====================================================== */
			}

			public void removeUpdate(DocumentEvent e) {
				/* ====================================================== */
				checkPatientValidity();
				/* ====================================================== */
			}
			
		});
		/* ================================================== */
	}

	
	/**
	 * Checks if the name of the patient matches the name in the textfield
	 * if not, the id will be erased
	 */
	private void checkPatientValidity() {
		/* ================================================== */
		if (!enableNameDocumentListener)
			return;
		try {
			String s = "";
			if (lastPatient.getMaidenName() != null && !"".equals(lastPatient.getMaidenName()))
				s = lastPatient.getMaidenName();
			else
				if (lastPatient.getSurName() != null)
					s = lastPatient.getSurName();
			/* ------------------------------------------------------- */
			if (lastPatient.getFirstName() != null)
				s = s + " " + lastPatient.getFirstName();
			/* ------------------------------------------------------- */
			if (!s.equals(gNameTextField.getText())) {
				this.patientID = null;
//				lastPatient = null;
			}
				firePropertyChange(PATIENT_ID_CHANGED, null, "eins");
		} catch (Exception e) {
		}
		/* ================================================== */
	}
	
	private void initButtonActions() {
		/* ================================================== */
		
		// ===================================================
		// S E A R C H Action
		// ===================================================
		this.searchPatientAction = new AbstractAction("", GECAMedModule.getMediumIcon(GECAMedIconNames.SEARCH)) {
			
			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e) {
				/* ====================================================== */
				
				String patName = gNameTextField.getText();
				if (patName != null) {
					patName = patName.replaceAll("\\W", " ");
				}
				lastPatient = PatientSearchDialog.searchPatient(patName);
				if (lastPatient == null)
					return;
				
				patientID = lastPatient.getId();
				matriculeLabel.setText(Translatrix.getTranslationString("calendar.newEvent.ssn") + ": " + lastPatient.getSocialSecurityNumber());	
				AppointmentCreateDialog.getInstance().pack();
				enableNameDocumentListener = false;
				gNameTextField.setText(lastPatient.toShortString());
				enableNameDocumentListener = true;
				// inform base dialog
				GeneralPanel.this.firePropertyChange(PATIENT_ID_CHANGED, "old", patientID);
				/* ====================================================== */
			}

		};
		this.gNameSearchButton.setToolTipText(Translatrix.getTranslationString("calendar.newEvent.searchPatient"));
		this.gNameSearchButton.setAction(this.searchPatientAction);
		// ===================================================

		// ===================================================
		// Create Patient Action
		// ===================================================
		this.createPatientAction = new AbstractAction("", PatientManagerModule.getMediumIcon(PatientManagerIconNames.PATIENT_NEW)) {

			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e) {
				// open create patient dialog 
				PatientCreateDialog patientCreateDialog = new PatientCreateDialog(Translatrix.getTranslationString("pm.newPatient"), true, true);
				
				// create Hashmap with initial Patientdata from Appointment Description
				HashMap<String, String> initialPatData = getInitialPatientData(appointment);
				
				// get selected patient
				lastPatient = patientCreateDialog.showDialog(initialPatData);	
				
				if (lastPatient == null)
					return;

				patientID = lastPatient.getId();
				enableNameDocumentListener = false;

				gNameTextField.setText(lastPatient.toShortString());
				enableNameDocumentListener = true;
				// inform base dialog
				GeneralPanel.this.firePropertyChange(PATIENT_ID_CHANGED, "old", patientID);

			}

		};
		
		this.gCreatePatientButton.setToolTipText(Translatrix.getTranslationString("pm.newPatient"));
		this.gCreatePatientButton.setAction(this.createPatientAction);
		// ===================================================
		
		// ===================================================
		// recurrence Action
		// ===================================================
		this.recurrenceAction = new AbstractAction(Translatrix.getTranslationString("calendar.recurrence")) {

			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e) {
				
				// save content from the fields in this panel
				getAppointment(appointment);
				// open recurrence dialog
				recurrenceOptionDialog.showDialog(appointment);
				// get content from the fields of the recurrence dialog 
				appointment = recurrenceOptionDialog.getAppointment();
				AppointmentCreateDialog.getInstance().recurrenceButtonAction(appointment);
			}
		};
		
		this.recurrenceButton.setToolTipText(Translatrix.getTranslationString("calendar.recurrence"));
		this.recurrenceButton.setAction(this.recurrenceAction);
		// ===================================================
		
		// ===================================================
		// define dialog wide key mappings
		// ===================================================
		KeyStroke strokeEsc = KeyStroke.getKeyStroke("ESCAPE");

		this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
					.put(strokeEsc, "continue");
		this.getActionMap().put("continue", cancelAction);


//		KeyStroke strokeEnter = KeyStroke.getKeyStroke("ENTER");
//
//		((JPanel) this.getContentPane()).getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
//					.put(strokeEnter, "ok");
//		((JPanel) this.getContentPane()).getActionMap().put("ok", okAction);
		// ===================================================
	}


	protected HashMap<String, String> getInitialPatientData(Appointment app) {
		HashMap<String, String> initialPatInfo = app.getDescriptionValues();
		try {
			String sum = gNameTextField.getText();
			String[] names = sum.split(",");
			if (names.length == 2) {
				initialPatInfo.put(Patient.FIELD_LASTNAME, names[0]);
				initialPatInfo.put(Patient.FIELD_FIRSTNAME, names[1]);
			} else {
				names = sum.split(" ");
				if (names.length == 2) {
					initialPatInfo.put(Patient.FIELD_FIRSTNAME, names[0]);
					initialPatInfo.put(Patient.FIELD_LASTNAME, names[1]);
				} else {
					initialPatInfo.put(Patient.FIELD_LASTNAME, sum);					
				}
			}
		} catch (Exception e2) {
			logger.warn("Error parsing initial Patinfo", e2);
		}
		return initialPatInfo;
	}

	/**
	 * init key listener
	 */
	private void initKeyListener() {
		/* ================================================== */
		// key listener on gNameTextField for searching in the patient list
		KeyAdapter searchAdapter = new KeyAdapter() {

			@Override
			public void keyPressed(KeyEvent e) {
				/* ====================================================== */
				if((e.isControlDown()) && (e.getKeyCode() == KeyEvent.VK_SPACE)) {
					GeneralPanel.this.searchPatientAction.actionPerformed(null);
				}
				/* ====================================================== */
			}

		};
		this.gNameTextField.addKeyListener(searchAdapter);
		this.gNameSearchButton.addKeyListener(searchAdapter);
		/* ================================================== */
	}


	/**
	 *
	 */
	private void refreshCalendars() {
		/* ================================================== */
		// get calendars from GECAMedLists
		@SuppressWarnings("unchecked")
		TreeSet<AgendaCalendar> orderedCalendars = new TreeSet<AgendaCalendar>(
				(Comparator<AgendaCalendar>)GECAMedUtils.getComparator(AgendaCalendar.class));
		List<AgendaCalendar> cals = GECAMedLists.getListReference(AgendaCalendar.class);
		orderedCalendars.addAll(cals);
		
		/* ------------------------------------------------------- */
		enableComboboxActionListener = false;
		gCalendarBox.removeAllItems();

		if (orderedCalendars.size() > 0)
		{
			for (AgendaCalendar aCal : orderedCalendars)
			{
				// add calendar if it is not a background calendar
				if (!aCal.isBackground())
					gCalendarBox.addItem(aCal);
			}
		}
		enableComboboxActionListener = true;
		/* ================================================== */
	}

	/**
	 * Refresh appointment types
	 */
	private void refreshAppointmentTypes(boolean blockListener) {
		/* ================================================== */
//		// get appointment types from GECAMedLists
//		ArrayList<AppointmentType> types = new ArrayList<AppointmentType>(
//				(Collection<? extends AppointmentType>)
//				  Arrays.asList(GECAMedLists.getList(AppointmentType.class)));
//		/* ------------------------------------------------------- */
		this.blockTypeListeners = blockListener;
		
		this.gTypeBox.removeAllItems();
		
		/* ------------------------------------------------------- */
		// get the list of appointments for the calendar
		AgendaCalendar selectedCalendar = (AgendaCalendar) gCalendarBox.getSelectedItem();
		/* ------------------------------------------------------- */
		if (selectedCalendar == null)
			return;
		/* ------------------------------------------------------- */
		try {
			/* ------------------------------------------------------- */
			AppointmentManager aManager = (AppointmentManager)
				ManagerFactory.getRemote(AppointmentManagerBean.class);
			
			Collection<AppointmentType> result = aManager.getAppointmentTypesByID(
													AppointmentType.GENERAL,
													selectedCalendar.getId(),
													false);
			
			if (result != null) {
				/* ------------------------------------------------------- */
				for (AppointmentType t : result)
						gTypeBox.addItem(t);
				/* ------------------------------------------------------- */
			}
			/* ------------------------------------------------------- */
		} catch (Exception e) {
			e.printStackTrace();
		}
		this.blockTypeListeners = false;
		/* ================================================== */
	}

	/**
	 * Compute the new time interval set the new start- and endtime and the duration.
	 * 
	 * @param startTimeChange true the start time have change, false the end time have change. 
	 */
	private void computeTimeInterval(boolean startTimeChange)
	{
		// -------------------------------------------------------
		String sel = (String) gDurationBox.getSelectedItem();

		if ("".equals(sel))
			return;

		// -------------------------------------------------------
		int i = 0;
		try {
			i = Integer.parseInt(sel.split(" ")[0]);
		} catch (Exception e) {
			logger.log(Level.WARN, "No number in field entered.", e);
		}
		
		if(startTimeChange)
		{
			
			// create new end date
			Calendar calEnd =  new GregorianCalendar();
			try {
				calEnd.setTime(gStartChooser.getDate());					
			} catch (Exception e) {
				e.printStackTrace();
			}

			// add duration
			calEnd.set(Calendar.MINUTE, calEnd.get(Calendar.MINUTE) + i);

			gEndChooser.setDate(calEnd.getTime());
		}else{
			
			// create new start date
			Calendar calStart =  new GregorianCalendar();
			try {
				calStart.setTime(gEndChooser.getDate());					
			} catch (Exception e) {
				e.printStackTrace();
			}

			// add duration
			calStart.set(Calendar.MINUTE, calStart.get(Calendar.MINUTE) - i);

			gStartChooser.setDate(calStart.getTime());
		}
		// format the string in the Duration Box
		this.gDurationBox.setSelectedItem(i + " min");
		return;
		// -------------------------------------------------------
	}


	/**
	 * fill comboboxes
	 */
	private void initComboBoxes() {
		/* ================================================== */

		this.gCalendarBox.setRenderer(new CalendarComboBoxRenderer());

		GECAMedLists.addPropertyChangeListener(new PropertyChangeListener() {

			public void propertyChange(PropertyChangeEvent evt) {
				/* ====================================================== */
				if (evt.getPropertyName().equals(AgendaCalendar.class.getSimpleName())) {
					/* ------------------------------------------------------- */
					refreshCalendars();
					/* ------------------------------------------------------- */
				}
			}
		}, AgendaCalendar.class);
		
		/* ------------------------------------------------------- */
		// listener for calendar box
		this.gCalendarBox.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				/* ====================================================== */
				if (enableComboboxActionListener) {
					refreshAppointmentTypes(true);
					checkMarkPrivateAllowed();
				}
				/* ====================================================== */
			}
			
		});
		/* ------------------------------------------------------- */
		// the calendars
//		if (GECAMedLists.getArray(AgendaCalendar.class) == null) {
//			// try to obtain the calendars
//			AgendaModule.loadCalendars();
//		} else
			refreshCalendars();

		// ============================================================
		// load the appointment types
		// into GECAMedList and in the combobox
		// ============================================================

		this.gTypeBox.setRenderer(new AppointmentTypeComboBoxRenderer());

		GECAMedLists.addPropertyChangeListener(new PropertyChangeListener() {

			public void propertyChange(PropertyChangeEvent evt) {
				/* ====================================================== */
				if (evt.getPropertyName().equals(AppointmentType.class.getSimpleName())) {
					refreshAppointmentTypes(false);
				}
				/* ====================================================== */
			}

		}, AppointmentType.class);
		/* ------------------------------------------------------- */
//		if (GECAMedLists.getArray(AppointmentType.class) == null)
//			AgendaModule.loadApointmentTypes();
//		else
			refreshAppointmentTypes(false);
		// =======================================================
		// fill duration combobox
		// =======================================================
		gDurationBox.addItem("");
		for (Integer i : intervals)
			this.gDurationBox.addItem(i+" min");


		// =======================================================
		// action when duration combobox is used
		// add the time periode to the start date
		// =======================================================
		this.gDurationBox.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{	
				if(blockDurationBoxListner) return;
				/* ====================================================== */
				blockStartChooserListener = true;
				blockEndChooserListener = true;
				computeTimeInterval(true);
				blockStartChooserListener = false;
				blockEndChooserListener = false;
				/* ====================================================== */
			}
		});
		
		this.gTypeBox.addActionListener(new ActionListener() {
			
			public void actionPerformed(ActionEvent e) {
				/* ================================================== */
				if (blockTypeListeners)
					return;
				/* ------------------------------------------------------- */
				try {
					AppointmentType ap = (AppointmentType) gTypeBox.getSelectedItem();
					if (ap != null && ap.getDuration() != null) {
						boolean itemFound = false;
						for (int i = 0; i < gDurationBox.getItemCount(); i++) {
							if (gDurationBox.getItemAt(i).equals(ap.getDuration() + " min")) {
								itemFound = true;
								break;
							}
						}
						if (! itemFound)
							gDurationBox.addItem(ap.getDuration() + " min");
						gDurationBox.setSelectedItem(ap.getDuration() + " min");
					}	
				} catch (Exception ee) {
					ee.printStackTrace();
				}
				/* ================================================== */
			}
		});
		

		/* ================================================== */
	}
	
	protected void checkMarkPrivateAllowed() {
	    try {
		AgendaCalendar selectedCal = (AgendaCalendar) this.gCalendarBox.getSelectedItem();

		if (GECAMedModule.getCurrentPhysician().getId().equals(selectedCal.getPhysicianId())) {
		    gPrivateBox.setEnabled(true);
		    privatePanel.setEnabled(false);
		} else {
		    gPrivateBox.setEnabled(false);
		    privatePanel.setEnabled(true);
		}
	    } catch (Exception e) {
		gPrivateBox.setEnabled(false);
		privatePanel.setEnabled(false);
		e.printStackTrace();
	    }
	}

	private void initDateChooserActions()
	{
		this.gStartChooser.addPropertyChangeListener(new PropertyChangeListener()
		{
			public void propertyChange(PropertyChangeEvent evt)
			{	
				if(blockStartChooserListener) return;
				/* ====================================================== */
				if (DateTimeChooser.TIME_CHANGED.equals(evt.getPropertyName()))
				{
					blockEndChooserListener = true;
					blockDurationBoxListner = true;
					computeTimeInterval(true);
					blockEndChooserListener = false;
					blockDurationBoxListner = false;
					//firePropertyChange(DATE_INTERVAL_CHANGED, "old", gStartChooser.getDate());	
				}
				/* ====================================================== */
			}
		});
		
		this.gEndChooser.addPropertyChangeListener(new PropertyChangeListener()
		{
			public void propertyChange(PropertyChangeEvent evt)
			{
				if(blockEndChooserListener) return;
				/* ====================================================== */
				if (DateTimeChooser.TIME_CHANGED.equals(evt.getPropertyName()))
				{
					blockStartChooserListener = true;
					blockDurationBoxListner = true;
					computeTimeInterval(false);
					blockStartChooserListener = false;
					blockDurationBoxListner = false;
					//firePropertyChange(DATE_INTERVAL_CHANGED, "old", gEndChooser.getDate());
				}
				/* ====================================================== */
			}
		});
	}

	public Icon getIcon()
	{
		// ==================================================
		return this.icon;
		// ==================================================
	}


	/**
	 * @return
	 */
	protected Integer getPatientId()
	{
		// ==================================================
		return this.patientID;
		// ==================================================
	}

	@Override
	public void setRecurrenceStatus(String string) {
		this.recurrenceStatusLabel.setText(string);
	}
	
	/**
	 * If end and start date of a appointment is set the method calculate and set the duration.
	 */
	private void calculateDuration()
	{
		
		// if end and start date is set calculate the duration
		if (appointment.getStartDate()!= null && appointment.getEndDate() != null)
		{
			Calendar calStart = new GregorianCalendar();
			calStart.setTime(appointment.getStartDate());
						
			Calendar calEnd = new GregorianCalendar();
			calEnd.setTime(appointment.getEndDate());
			
			long timediff = calEnd.getTimeInMillis() - calStart.getTimeInMillis();
			// set the calculate duration to the gDurationBox
			gDurationBox.setSelectedItem((int) (timediff / 60000) + " min");
		}
	}
}