/*******************************************************************************
 * 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.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.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
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.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
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.gui.AgendaModule;
import lu.tudor.santec.gecamed.agenda.gui.widgets.appointmenttype.AppointmentTypeComboBoxRenderer;
import lu.tudor.santec.gecamed.core.gui.GECAMedLists;
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.usermanagement.ejb.session.beans.LoginBean;
import lu.tudor.santec.gecamed.usermanagement.ejb.session.interfaces.LoginInterface;
import lu.tudor.santec.i18n.Translatrix;

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 holiday information of
 * an Appointment like patient name, description, calendar, appointment type, start,end date
 * 
 * @author martin.heinemann@tudor.lu
 * 18.01.2008
 * 15:34:56
 *
 *
 * @version
 * <br>$Log: HolidayPanel.java,v $
 * <br>Revision 1.31  2013-12-27 18:09:04  donak
 * <br>Cleanup of imports
 * <br>
 * <br>Revision 1.30  2013-07-15 06:18:36  ferring
 * <br>logging changed
 * <br>
 * <br>Revision 1.29  2013-02-19 12:07:34  ferring
 * <br>GECAMedLists changed. Will now automatically load list of all beans
 * <br>
 * <br>Revision 1.28  2011-11-28 16:22:57  troth
 * <br>'system.out.println'-warring are now written in the agenda logger
 * <br>
 * <br>Revision 1.27  2011-11-07 15:35:24  troth
 * <br>Fix some GUI Bugs.
 * <br>
 * <br>Revision 1.26  2011-10-24 14:16:17  troth
 * <br>Code Cleanup
 * <br>
 * <br>Revision 1.25  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.24  2011-10-05 15:28:13  troth
 * <br>Do some translations for Ticket #879.
 * <br>
 * <br>Revision 1.23  2011-08-05 15:06:07  troth
 * <br>fix ticket #891
 * <br>
 * <br>Revision 1.22  2011-08-03 14:02:37  troth
 * <br>code clearup
 * <br>
 * <br>Revision 1.21  2011-08-02 15:57:47  troth
 * <br>Fix ticket #871
 * <br>
 * <br>Revision 1.20  2011-08-01 14:58:44  troth
 * <br>Fix tickets #874 #839.
 * <br>
 * <br>Revision 1.19  2011-05-10 16:50:52  troth
 * <br>code clean up
 * <br>
 * <br>Revision 1.18  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.17  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.16  2011-04-04 11:38:30  troth
 * <br>Redesign of the appointment create dialog and the right navi bar.
 * <br>
 * <br>Revision 1.15  2008-09-25 09:42:27  heinemann
 * <br>fixed copyrights
 * <br>
 * <br>Revision 1.14  2008-07-04 13:38:58  heinemann
 * <br>fixed generic casting that the new eclipse does not want to accept.
 * <br>
 * <br>Revision 1.13  2008-01-18 16:09:05  heinemann
 * <br>code cleanup and java doc
 * <br>
 *   
 */
public class HolidayPanel extends AppointmentEditPanel{

	private static final long serialVersionUID = 1L;
	
	private JLabel gNameLabel;
	
	private JTextField gNameTextField;
	
	private JLabel gDescriptionLabel;
	
	private UndoTextArea gDescriptionTextArea;
	
	private JScrollPane gDescriptionScroll;
	
	private JLabel gTypeLabel;
	
	private JComboBox gTypeBox;
	
	private JLabel gCalendarLabel;
	
	private JPanel gTypePanel;
	
	private JComboBox gCalendarBox;
	
	private JLabel gStartLabel;
	
	private DateTimeChooser gStartChooser;
	
	private JLabel gDurationLabel;
	
	private JComboBox gDurationBox;
	
	private JLabel gEndLabel;
	
	private DateTimeChooser gEndChooser;
	
	private JPanel gTimePanel;

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

	private final Integer[] intervals = new Integer[] {
			05,10,15,20,25,30,40,45,50
	};
	
	private JPanel privatePanel;
	
	private JCheckBox gPrivateBox;
	
	private JPanel createdByPanel;
	
	private JLabel createdLabel;
	
	private JPanel recurrencePanel;
	
	private JButton recurrenceButton;
	
	private AbstractAction recurrenceAction;
	
	private JLabel recurrenceStatusLabel;
	
	private RecurrenceOptionDialog recurrenceOptionDialog = RecurrenceOptionDialog.getInstance();

	private Appointment appointment;
	
	private DateFormat formater = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
	
	private Boolean blockStartChooserListener = false;
	
	private Boolean blockEndChooserListener = false;
	
	private Boolean blockDurationBoxListner = false;
	
	/** the logger Object for this class */
	private static Logger logger = Logger.getLogger(HolidayPanel.class.getName());
	
	/**
	 * 
	 */
	public HolidayPanel() {
		initComponents();
		initButtonActions();
		initDateChooserActions();
		initComboBoxes();
	}

	/**
	 * 
	 */
	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
				"2dlu," +		// 9
				"fill:33dlu," +	// 10
				"5dlu," +		// 11
				"fill:pref," +  // 12
				"3dlu," +		// 13
				"fill:pref," +  // 14
				"3dlu," +		// 15
				"fill:pref," +  // 16
				"pref:grow," +	// 17
				"3dlu" 			// 18
				));
		this.setOpaque(false);
		// -------------------------------------------------------
		// explanation text
		// -------------------------------------------------------
		JTextArea explanationTextArea = new JTextArea(Translatrix.getTranslationString("Agenda.unavailable.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(""));
		
		// the old header text explanation
//		// -------------------------------------------------------
//		// header text explanation
//		// -------------------------------------------------------
//		JPanel headerPanel = new JPanel(new FormLayout("0dlu, fill:pref:grow, 0dlu" , "0dlu, fill:pref, 0dlu"));
//		headerPanel.setOpaque(false);
//		
//		JLabel lHeader = new JLabel("<html>"+Translatrix.getTranslationString("Agenda.editBlockPeriod.explanation"));
//		lHeader.setOpaque(true);
//		lHeader.setBackground(Color.WHITE);
//		lHeader.setBorder(BorderFactory.createTitledBorder(""));
//		
////		lHeader.setIcon(GECAMedModule.getIcon(GECAMedIconNames.INFO));
//		lHeader.setIcon(AgendaModule.getMediumIcon(AgendaModule.ICON_BLOCK_PERIOD));
//		
//		
//		lHeader.setVerticalTextPosition(SwingConstants.TOP);
//		lHeader.setHorizontalTextPosition(SwingConstants.RIGHT);
//		CellConstraints ccHeader = new CellConstraints();
//		headerPanel.add(lHeader, ccHeader.xy(2, 2));
		/* ------------------------------------------------------- */
		// name
		/* ------------------------------------------------------- */
		this.gNameLabel = new JLabel(Translatrix.getTranslationString("Agenda.unavailable.title")+":");
		//this.gNameLabel.setIcon(icon);
		this.gNameLabel.setHorizontalTextPosition(SwingConstants.RIGHT);

		this.gNameTextField = new JTextField(20);
		this.gNameTextField.setToolTipText(Translatrix.getTranslationString("calendar.newEvent.searchPatient"));
		/* ------------------------------------------------------- */

		/* ------------------------------------------------------- */
		// 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 type and calendar 
		/* ------------------------------------------------------- */
		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.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.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 reapt for this entry");
		this.recurrencePanel.add(this.recurrenceStatusLabel, BorderLayout.CENTER);
		
		/* ------------------------------------------------------- */
		// assemble absence panel
		/* ------------------------------------------------------- */
		//--- old
//		this.add(explanationTextArea, cc.xywh(2, 2, 5, 1));
//		
//		this.add(this.gNameLabel, cc.xy(2, 4));
//		this.add(this.gNameTextField , cc.xy(2, 6));
//
//		this.add(this.gDescriptionLabel , cc.xy(2, 8));
//		this.add(this.gDescriptionScroll , cc.xywh(2, 10, 1, 6));
//
//		this.add(this.gTypePanel , cc.xywh(6, 4, 1, 8));
//		this.add(this.gTimePanel , cc.xywh(6, 12, 1, 1));
//		this.add(this.privatePanel , cc.xywh(6, 14, 1, 1));
		//---
		this.add(explanationTextArea, cc.xywh(2, 2, 5, 1));
		
		this.add(this.gNameLabel, cc.xy(2, 4));
		this.add(this.gNameTextField , cc.xy(2, 6));

		this.add(this.gDescriptionLabel , cc.xy(2, 8));
		this.add(this.gDescriptionScroll , cc.xywh(2, 10, 1, 3));
		
		this.add(this.createdByPanel, cc.xy(2, 14));
		
		this.add(this.gTypePanel , cc.xywh(6, 4, 1, 8));
		this.add(this.gTimePanel , cc.xywh(6, 12, 1, 1));
		
		this.add(this.privatePanel , cc.xywh(6, 14, 1, 1));
		
		this.add(this.recurrencePanel, cc.xywh(2, 16, 5, 1));
		
		/* ================================================== */
	}
	
	
	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);
		
		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);
			}
		}
	}
	
	
	/**
	 * Updates the forms with the data from the appointment object
	 */
	public void setAppointment(Appointment appointment)
	{
		/* ================================================== */
		blockStartChooserListener = true;
		blockEndChooserListener = true;
		blockDurationBoxListner = true;
		/* ------------------------------------------------------- */
		this.gNameTextField.setText((appointment.getSummary() != null ?
										appointment.getSummary()
										: ""));
		/* ------------------------------------------------------- */
		this.gDescriptionTextArea.setText(((appointment.getDescription() != null ?
												appointment.getDescription()
												: "")));
		/* ------------------------------------------------------- */
		// 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.gTypeBox.setSelectedItem(AgendaModule.getTypeForId(appointment.getTypeId()));
		/* ------------------------------------------------------- */
		this.gCalendarBox.setSelectedItem(AgendaModule.getCalendarForId(appointment.getCalendarId()));
		/* ------------------------------------------------------- */
		this.gPrivateBox.setSelected(appointment.isPrivate());
		/* ------------------------------------------------------- */
		this.gStartChooser.setDate(appointment.getStartDate());
		this.gEndChooser.setDate(appointment.getEndDate());
		
		//-------------------------------------------------------
		// set create 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();
	        }
		}
		
		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;
		/* ================================================== */
	}

	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);

		// the calendars
//		if (GECAMedLists.getArray(AgendaCalendar.class) == null) {
//			// try to obtain the calendars
//			AgendaModule.loadCalendars();
//		} else
			refreshCalendars();

//		 ============================================================
		// load the appointment types
		// into GECAMedList an 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();
				}
				/* ====================================================== */
			}

		}, AppointmentType.class);

//		if (GECAMedLists.getArray(AppointmentType.class) == null)
//			AgendaModule.loadApointmentTypes();
//		else
			refreshAppointmentTypes();

		// =======================================================
		// 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) {
				/* ================================================== */
				/* ------------------------------------------------------- */
				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();
				}
				/* ================================================== */
			}
		});
		/* ================================================== */
	}

	/**
	 * 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;
		// -------------------------------------------------------
	}

	/**
	 * init action listener for start date chooser and end date chooser
	 */
	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());
				}
				/* ====================================================== */
			}
		});
	}

	/**
	 * Fills the appointment with the data from the form fields
	 */
	public void getAppointment(Appointment appointment) {
		/* ================================================== */
//		if (this.appointment == null)
//			this.appointment = new Appointment();
		/* ------------------------------------------------------- */
		// name
		appointment.setSummary(this.gNameTextField.getText());
		// description
		appointment.setDescription(this.gDescriptionTextArea.getText());
		// type
		appointment.setTypeId(((AppointmentType) this.gTypeBox.getSelectedItem()).getId());
		// calendar
		appointment.setCalendarId(((AgendaCalendar) this.gCalendarBox.getSelectedItem()).getId());
		// start
		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(null);
		// background
		appointment.setIsBackground(true);
		// private
		appointment.setPrivate(this.gPrivateBox.isSelected());
		// recurrenceAction
		this.recurrenceOptionDialog.getAppointment(appointment);
		/* ================================================== */
	}

	/**
	 * Refresh appointment types
	 */
	private void refreshAppointmentTypes() {
		/* ================================================== */
		// get appointment types from GECAMedLists
		
		List<AppointmentType> types = GECAMedLists.getListReference(AppointmentType.class);
		/* ------------------------------------------------------- */
		this.gTypeBox.removeAllItems();

		if (types != null && types.size() > 0) {
			/* ------------------------------------------------------- */
			for (AppointmentType obj : types)
				if (AppointmentType.BACKGROUND.equals(((AppointmentType)obj).getAppointmentTypeClass()))
					gTypeBox.addItem(obj);
			/* ------------------------------------------------------- */
		}
		/* ================================================== */
	}


	public Icon getIcon() {
		/* ================================================== */
		return this.icon;
		/* ================================================== */
	}
	
	
	private void initButtonActions()
	{
		// ===================================================
		// 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);
				appointment = recurrenceOptionDialog.getAppointment();
				AppointmentCreateDialog.getInstance().recurrenceButtonAction(appointment);
			}
		};
				
		this.recurrenceButton.setToolTipText(Translatrix.getTranslationString("calendar.recurrence"));
		this.recurrenceButton.setAction(this.recurrenceAction);
		// ===================================================
	}

	@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");
		}
	}
}