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

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;

import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import lu.tudor.santec.gecamed.agenda.gui.AgendaAdminSettingsPlugin;
import lu.tudor.santec.gecamed.agenda.gui.AgendaModule;
import lu.tudor.santec.gecamed.core.gui.GECAMedAction;
import lu.tudor.santec.gecamed.core.gui.GECAMedColors;
import lu.tudor.santec.gecamed.core.gui.GECAMedIconNames;
import lu.tudor.santec.gecamed.core.gui.GECAMedLog;
import lu.tudor.santec.gecamed.core.gui.GECAMedModule;
import lu.tudor.santec.gecamed.core.gui.IconFetcher;
import lu.tudor.santec.gecamed.core.gui.MainFrame;
import lu.tudor.santec.gecamed.core.gui.PhysicianListener;
import lu.tudor.santec.gecamed.core.gui.RegistrationDesk;
import lu.tudor.santec.gecamed.core.gui.utils.GECAMedGuiUtils;
import lu.tudor.santec.gecamed.core.gui.utils.GeneralGECAMedTextMessageReciever;
import lu.tudor.santec.gecamed.core.gui.utils.GradientFactory;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.office.ejb.entity.beans.Physician;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.Patient;
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.waitingroom.ejb.entity.beans.Queue;
import lu.tudor.santec.gecamed.waitingroom.ejb.entity.beans.Reason;
import lu.tudor.santec.gecamed.waitingroom.ejb.entity.beans.Room;
import lu.tudor.santec.gecamed.waitingroom.ejb.session.beans.WaitingroomManagerBean;
import lu.tudor.santec.gecamed.waitingroom.ejb.session.interfaces.WaitingroomManager;
import lu.tudor.santec.gecamed.waitingroom.ejb.session.util.QueueUpdateEvent;
import lu.tudor.santec.gecamed.waitingroom.gui.physicianagenda.PhysicianAgendaDialog;
import lu.tudor.santec.gecamed.waitingroom.gui.widgets.QueueEditDialog;
import lu.tudor.santec.i18n.Translatrix;
import lu.tudor.santec.widgets.gui.ButtonFactory;

import org.apache.log4j.Logger;

import bizcal.common.Event;
import bizcal.util.DateUtil;

import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.Sizes;
import com.toedter.calendar.JCalendar;
import com.toedter.calendar.JDateChooser;
import com.toedter.calendar.JTextFieldDateEditor;

/**
 * @author martin.heinemann@tudor.lu
 * 25.01.2008
 * 14:02:30
 *
 *
 * @version
 * <br>$Log: WaitingroomModule.java,v $
 * <br>Revision 1.34  2014-02-13 17:34:28  ferring
 * <br>ConcurrentModificationException avoided and warning of FormLayout removed
 * <br>
 * <br>Revision 1.33  2013-08-21 12:52:09  troth
 * <br>Fix Bug: if the users switch between show all and one waitingroom there was send a message to all users to refresh the waitingrooms and that two time this is not needed.
 * <br>
 * <br>Revision 1.32  2011-10-28 15:11:02  troth
 * <br>fix Ticket #900: Recurrence Appointments are not show in the Waitingroom.
 * <br>
 * <br>Revision 1.31  2011-10-24 11:15:54  troth
 * <br>Ticket #899: add new enhancement - Configuration of the minimum width of a column waiting room.
 * <br>
 * <br>Revision 1.30  2011-09-20 13:12:17  troth
 * <br>fix some little bug's:
 * <br>1. add " " -item to the physician select box so that user able to select no physician.
 * <br>2. fix a null-pointer exception if a waiting room have no physician.
 * <br>
 * <br>Revision 1.29  2010-12-30 14:32:39  troth
 * <br>fixed problems with synchronization of Waitingroom and Agenda
 * <br>
 * <br>Revision 1.28  2010-12-20 15:42:05  troth
 * <br>GUI redesign of Waitingroom and the Waitingroom get his own usersettingpanel
 * <br>
 * <br>Revision 1.27  2010-12-03 10:18:07  troth
 * <br>Complete - # 649: Wartesaal nur f�r einen Arzt anzeigen
 * <br>http://santec.tudor.lu/trac/gecamed/ticket/649
 * <br>
 * <br>Revision 1.26  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.25  2010-05-12 09:00:15  hermen
 * <br>changed handling and fetching of room-updates.
 * <br>collectAppointments is now called each 5 min by server,
 * <br>rooms are updated by single entry, not by full reload as before.
 * <br>
 * <br>Revision 1.24  2010-04-30 13:08:42  hermen
 * <br>added site to waitingroom
 * <br>
 * <br>Revision 1.23  2010-03-19 12:01:06  hermen
 * <br>improved and unified iconfetching
 * <br>
 * <br>Revision 1.22  2010-03-18 17:09:36  hermen
 * <br>fixed updating of waitingroom
 * <br>fixed taking only appointments with attached patient to the waitingeroom
 * <br>
 * <br>Revision 1.21  2009-10-13 09:11:02  hermen
 * <br>Add/Delete/Edit Waitingroom are now in the admin-settings.
 * <br>Description of Waitingroom can be changed by user
 * <br>
 * <br>Revision 1.20  2009-10-12 09:18:00  hermen
 * <br>waitingroom mow scales to room anz and screensize
 * <br>
 * <br>Revision 1.19  2009-10-07 13:07:18  hermen
 * <br>added isVisit to waitingroom entry
 * <br>
 * <br>Revision 1.18  2009-10-06 14:16:13  hermen
 * <br>added isVisit to waitingroom entry
 * <br>
 * <br>Revision 1.17  2008-12-05 17:34:23  heinemann
 * <br>moved some basic classes to lu.tudor.santec.widgets
 * <br>
 * <br>Revision 1.16  2008-09-25 09:43:06  heinemann
 * <br>fixed copyrights
 * <br>
 * <br>Revision 1.15  2008-07-04 13:02:04  heinemann
 * <br>complete - # 159: Add notes to entries of the waitingroom
 * <br>http://santec.tudor.lu/trac/gecamed/ticket/159
 * <br>
 * <br>Revision 1.14  2008-06-17 09:41:46  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.13  2008-06-17 09:29:45  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.12  2008-05-28 12:07:53  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.11  2008-05-27 14:46:04  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.10  2008-05-26 14:23:33  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.9  2008-05-08 09:10:02  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.8  2008-05-07 14:40:35  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.7  2008-04-29 14:17:38  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.6  2008-02-27 14:23:06  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.5  2008-02-27 10:42:11  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.4  2008-02-27 09:14:39  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.3  2008-02-27 08:26:48  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.2  2008-02-25 15:49:47  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.1  2008-02-11 16:47:52  heinemann
 * <br>Initial checkin
 * <br>
 *   
 */
public class WaitingroomModule extends GECAMedModule implements ActionListener, PhysicianListener {


	/**
	 * static logger for this class
	 */
	private static Logger  		logger = Logger.getLogger(WaitingroomModule.class.getName());
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	public static final String WAITINGROOM_ICON		= "waitingroom_module.png";
	
	public static final String MOVE_2_WAITINGROOM 	= "move2waitingroom.png";
	public static final String ADD_EMERGERNCY   	= "addEmergency.png";
	public static final String WITH_APPOINTMENT 	= "with_appointment.png";
	public static final String CONSULTATION_ROOM 	= "consultation_room.png";
	public static final String WAITINGROOM 		 	= "waitingroom.png";
	public static final String TRASH			 	= "trash.png";
	public static final String TRASH_FULL 		 	= "trash_full.png";
	public static final String ADD_ROOM			 	= "addroom.png";
	public static final String SHOW_ALL_ROOMS		= "showAllRooms.png";
	public static final String SHOW_ONE_ROOM		= "showOneRoom.png";
	public static final String IMPORT_FROM_AGENDA	= "importfromagenda.png";
	
	
	public static final String VISIT_TRUE			= "visit_true.png";
	public static final String VISIT_FALSE			= "visit_false.png";
	public static final String PRESENT_TRUE			= "present_true.png";
	public static final String PRESENT_FALSE		= "present_false.png";
	public static final String TREATED_TRUE			= "treated_true.png";
	public static final String TREATED_FALSE		= "treated_false.png";
	
	
	/**
	 * The name of the module
	 */
	public static final String MODULE_NAME = "Waitingroom";

	public static final String WAITINGROOM_ADD 	  = "ADD";
	public static final String WAITINGROOM_REMOVE = "REMOVE";
	public static final String WAITINGROOM_UPDATE = "UPDATE";
	public static final String WAITINGROOM_RELOAD = "RELOAD";
	
	private static final ColumnSpec	ROOM_COLUMN_DEFAULT	= new ColumnSpec(ColumnSpec.FILL, Sizes.PREFERRED, ColumnSpec.DEFAULT_GROW);
	private static final ColumnSpec	ROOM_COLUMN_SPACE	= new ColumnSpec(Sizes.DLUX3);
	
//	public static GhostGlassPane ghostGlassPane = new GhostGlassPane();
	
	
	DateFormat df = GECAMedGuiUtils.getDateFormat(false);
	
	
	@SuppressWarnings("unused")
	private GeneralGECAMedTextMessageReciever topicListener;

	private PhysicianAgendaDialog physicianAgendaDialog;

	private CellConstraints cc;

	private JPanel searchPanel;

	private JButton clearButton;

	private JLabel searchLabel;

	private JTextField searchField;

	private JButton addEmergencyButton;

	private JPanel roomPanel;

	private JPanel roomCenterPanel;

	private List<Room> rooms;

	private HashMap<Integer, Waitingroom> waitingrooms;

	private JPanel mainPanel;

//	private Patient selectedPatient;

	private boolean blockDocumentListener = false;

	private FormLayout roomCenterPanelLayout;

	private JButton searchButton;

	private JScrollPane paine;

	private WaitingroomAdminSettingsPlugin adminSettings;

	protected boolean reloadIsRunning;

	private PatientCreateDialog patientCreateDialog;

	private JButton createPatientButton;
	
	private JToggleButton showWaitingRoomButton;

//	private DnDRegistry<Queue> dndRegistry;
	
	private static WaitingroomModule instance;
	
	// usersetting for waitingroom
	private WaitingroomSettingsPlugin waitingroomSettingsPlugin;

	private JLabel dateLabel;

	private JDateChooser dateChooser;

	protected Date day = new Date(); 
	
    private List<Reason> reasons = new ArrayList<Reason>();
	
	/**
	 * @param moduleName
	 * @param moduleIcon
	 * @param moduleColor
	 */
	public WaitingroomModule() {
		/* ================================================== */
		super(MODULE_NAME, getScaledIcon(WAITINGROOM_ICON, NORMALPIX), new Color(242, 236, 63));
		instance = this;
		
		Translatrix.addBundle("lu.tudor.santec.gecamed.waitingroom.gui.resources.Translatrix");
		
		this.adminSettings = new WaitingroomAdminSettingsPlugin();
		this.addAdminSettingsPlugin(this.adminSettings);
		this.waitingroomSettingsPlugin = new WaitingroomSettingsPlugin();
		this.addSettingsPlugin(this.waitingroomSettingsPlugin);
		
//		initDragNDrop();
		
		initComponent();
		initActions();
		initTopicListener();
		this.addPhysicianListener();
		/* ================================================== */
	}

	
	
	/* (non-Javadoc)
	 * @see lu.tudor.santec.gecamed.core.gui.GECAMedModule#initModule()
	 */
	@Override
	protected void initModule() {
		/* ====================================================== */
//		initTopicListener();
		loadRooms();
		
		this.physicianAgendaDialog = new PhysicianAgendaDialog();
		physicianAgendaDialog.physicianChanged(MainFrame.getCurrentPhysician());
		
        	new Thread() {
				public void run() {
        	    	if (reloadIsRunning)
        	    		return;
        	    	try {
        	    		reloadIsRunning = true;
        	    		boolean agendaImport = false;
        				try {
        					agendaImport = (Boolean) adminSettings.getValue(WaitingroomAdminSettingsPlugin.AUTO_IMPORT_ENABLED);
        				} catch (Exception e2) {}
        				if (agendaImport) {
        					getManager().collectAppointments4Waitingrooms((Locale)AgendaModule.getInstance().getAgendaAdminSettingsPlugin().getValue(AgendaAdminSettingsPlugin.CALENDAR_LOCALE), false);        					
        				}
        	    		reloadQueues(null);
					} catch (Exception e) {
						logger.error("Error fetching Waiting Room Entries");
					}
					reloadIsRunning = false;
					
        	    }
        	}.start();
		
		/* ====================================================== */
	}

	/**
	 * Get the instance of the Waitingroom module.
	 * @return the instance of the Waitingroom module.
	 */
	public static WaitingroomModule getInstance() {
		/* ================================================== */
		return instance;
		/* ================================================== */
	}
	
//	/**
//	 * Inits the drag n drop registry
//	 */
//	private void initDragNDrop() {
//		/* ================================================== */
//		this.dndRegistry = new DnDRegistry<Queue>(MainFrame.getInstance());
//		/* ================================================== */
//	}
//	
//	/**
//	 * Returns the dnd registry
//	 * @return
//	 */
//	public DnDRegistry<Queue> getDnDRegistry() {
//		/* ================================================== */
//		return this.dndRegistry;
//		/* ================================================== */
//	}
	
	/**
	 * Create the main panel
	 */
	private void initComponent() {
		/* ================================================== */
		this.mainPanel = new JPanel();
		mainPanel.setLayout(new FormLayout("2dlu," +
									  "fill:10dlu:grow," +
									  "2dlu",
									  // rows
									  "2dlu," +
									  //"fill:pref," +
									  //"3dlu," +
									  "fill:pref:grow," +
									  "2dlu"));

		/* ------------------------------------------------------- */
		this.cc = new CellConstraints();
		mainPanel.setBackground(GECAMedColors.c_GECAMedBackground);
		/* ------------------------------------------------------- */
		initSearchPanel();
		this.titlePanel.setHeaderComponent(this.searchPanel);
		initRoomPanel();
		/* ------------------------------------------------------- */
		this.paine = new JScrollPane(roomPanel);
		
		this.paine.setOpaque(false);
		this.paine.getViewport().setOpaque(false);
		this.paine.setBorder(null);
		this.paine.setViewportBorder(null);
		/* ------------------------------------------------------- */
		//mainPanel.add(searchPanel, cc.xy(2, 2));
		mainPanel.add(paine,   cc.xy(2, 2));
		/* ------------------------------------------------------- */
		this.setContentPanel(GradientFactory.makeGradient(mainPanel));
		
		this.reasons = getManager().getReasons();
		/* ================================================== */
	}
	

	/**
	 * inits the panel containing the search field and the buttons
	 */
	private void initSearchPanel() {
		this.searchPanel = new JPanel(new FormLayout("3dlu," +
													 "fill:pref," +  // Date
													 "2dlu," +
													 "fill:36px," +  // Datechooser
													 "3dlu," +
													 "fill:pref," +  // clear button
													 "2dlu," +
													 "fill:pref," +  // label
													 "3dlu," +
													 "fill:pref:grow," +  // textfield
													 "3dlu," +
													 "fill:pref," +  // searchbutton
													 "3dlu," +
													 "fill:pref," +  // createpatientbutton
													 "fill:pref",
													 // rows
													 "2dlu," +
													 "fill:pref," +
													 "2dlu"));
		
		searchPanel.setOpaque(false);
		
		
		this.dateLabel = new JLabel("["+Translatrix.getTranslationString("waitingroom.today")+"]");
		this.dateLabel.setFont(new Font("Helvetica", Font.BOLD, 20));
		this.dateChooser = new JDateChooser();
		
		// remove Date Editor Field
		JTextFieldDateEditor editor = (JTextFieldDateEditor) dateChooser.getDateEditor();
		editor.setEditable(false);
		editor.setVisible(false);
		this.dateChooser.remove(editor);
		this.dateChooser.setOpaque(false);
		
		// listen for Date change
		this.dateChooser.addPropertyChangeListener("date", new PropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent evt) {
				Date d = dateChooser.getDate();
				if (d == null) {
					d = new Date();
				}
				day = d;
				
				if (DateUtil.isSameDay(new Date(), day)) {
					dateLabel.setText("["+Translatrix.getTranslationString("waitingroom.today")+"]");
				} else {
					dateLabel.setText("["+df.format(day)+"]");					
				}
				
				reload(false);
				
			}
		});

		searchPanel.add(dateLabel, cc.xy(2, 2));
		searchPanel.add(dateChooser, cc.xy(4, 2));
		
		this.searchLabel = new JLabel(Translatrix.getTranslationString("waitingroom.search")+":");
		
		// create the search field
		this.searchField = new JTextField(25);
		this.searchField.addActionListener(this);
//		this.searchField.getDocument().addDocumentListener(this);
		
		// create clear search field button
		this.clearButton = ButtonFactory.createEffectButton(GECAMedModule.getMediumIcon(GECAMedIconNames.EDIT_CLEAR_LTR));
		clearButton.addActionListener(this);
				
		// create the search button
		this.searchButton = ButtonFactory.createEffectButton(GECAMedModule.getMediumIcon(GECAMedIconNames.SEARCH));
		this.searchButton.setToolTipText(Translatrix.getTranslationString("waitingroom.search"));
		this.searchButton.addActionListener(this);
		
		// create the new patient button
		this.createPatientButton = ButtonFactory.createEffectButton(PatientManagerModule.getMediumIcon(PatientManagerIconNames.PATIENT_NEW));
		this.createPatientButton.setToolTipText(Translatrix.getTranslationString("pm.newPatient"));
		this.createPatientButton.addActionListener(this);

		// create the add emergency button
		this.addEmergencyButton = new JButton(getAnchorScaledIcon(ADD_EMERGERNCY, 48));
		this.addEmergencyButton.setToolTipText(Translatrix.getTranslationString("waitingroom.addEmergency"));
		this.addEmergencyButton.addActionListener(this);

		// assemble the panel
		searchPanel.add(clearButton, cc.xy(6, 2));
		searchPanel.add(searchLabel, cc.xy(8, 2));
		searchPanel.add(searchField, cc.xy(10, 2));
		searchPanel.add(searchButton, cc.xy(12, 2));
		searchPanel.add(createPatientButton, cc.xy(14, 2));
	}

	/**
	 * inits the panel for the rooms
	 */
	private void initRoomPanel() {
		/* ================================================== */
		this.roomPanel = new JPanel(new BorderLayout());
//		this.roomCenterPanel = new JPanel(new GridLayout(1, 0));
		this.roomCenterPanel = new JPanel();
		
		this.roomCenterPanelLayout = new FormLayout("pref:grow", "pref:grow,fill:10dlu,pref:grow");
		roomCenterPanel.setLayout(roomCenterPanelLayout);
//		this.gbl      = new GridBagLayout();
//		this.gbc = new GridBagConstraints();
//
//		gbc.anchor             = GridBagConstraints.CENTER;
//		roomCenterPanel.setLayout(gbl);
		/* ------------------------------------------------------- */
		
		
		this.roomPanel.add(roomCenterPanel, BorderLayout.CENTER);
		/* ------------------------------------------------------- */
		roomPanel.setOpaque(false);
		roomCenterPanel.setOpaque(false);
		/* ------------------------------------------------------- */
		
		/* ================================================== */
	}
	
	
	/**
	 * Loads the rooms from the database and creates the guis.
	 * Not the queues. These are loaded by the guis.
	 */
	private void loadRooms() {
		/* ================================================== */
		String icon = "";
		
		if ((Boolean) waitingroomSettingsPlugin.getValue(WaitingroomSettingsPlugin.SHOW_ALL_WAITINGROOMS_ENABLED))
		{
			icon = SHOW_ONE_ROOM;
			showWaitingRoomButton.setToolTipText(Translatrix.getTranslationString("waitingroom.showOneWaitingroomText"));
		}else{
			icon = SHOW_ALL_ROOMS;
			showWaitingRoomButton.setToolTipText(Translatrix.getTranslationString("waitingroom.showAllWaitingroomText"));
		}
		showWaitingRoomButton.setIcon(getMediumIcon(icon));
		
		try {
			/* --------------------------------------------- */
			// get all rooms from the database, sorted by order
			/* ------------------------------------------------------- */
		    
		    	List<Room> allRooms = null;
			
		    	if  (MainFrame.getCurrentSiteId() != null) {
		    	    
		    	    allRooms = getManager().getAllRooms(MainFrame.getCurrentSiteId());
		    	} else {
		    	    
		    	    allRooms = getManager().getAllRooms();
		    	}
		    			    
		    
			/* ------------------------------------------------------- */
			// do nothing for no rooms
			/* ------------------------------------------------------- */
			if (allRooms == null || allRooms.size() < 0)
				return;
			/* ------------------------------------------------------- */
			this.rooms = allRooms;
			/* ------------------------------------------------------- */
			// create the guis
			/* ------------------------------------------------------- */
			this.waitingrooms = new LinkedHashMap<Integer, Waitingroom>();
			
			for (Room r : rooms) {
				/* ------------------------------------------------------- */
				if ((Boolean) waitingroomSettingsPlugin.getValue(WaitingroomSettingsPlugin.SHOW_ALL_WAITINGROOMS_ENABLED))
				{
					Waitingroom waitingroom = new Waitingroom(this, r, Waitingroom.MODE_SECRETARY, getDay());
					waitingrooms.put(r.getId(), waitingroom);
				} else {
					// room must not have a physician
					if(r.getPhysicianId()!= null)
					{
						if(r.getPhysicianId().equals(PatientManagerModule.getCurrentPhysician().getId()))
						{
							Waitingroom waitingroom = new Waitingroom(this, r, Waitingroom.MODE_SECRETARY, getDay());
							waitingrooms.put(r.getId(), waitingroom);
						}
					}
				}
				/* ------------------------------------------------------- */
			}
			
			/* ------------------------------------------------------- */
			this.roomCenterPanel.removeAll();
			this.roomCenterPanelLayout = new FormLayout("3dlu", "5dlu,fill:pref:grow,5dlu");
			roomCenterPanel.setLayout(roomCenterPanelLayout);
			
			
			for (Waitingroom w : waitingrooms.values()) {
				/* ------------------------------------------------------- */
//				gbl.setConstraints(w, gbc);
				// set min size of a waitingroom column
				int minSizeWidth = ((Integer) adminSettings.getValue(WaitingroomAdminSettingsPlugin.WR_MIN_SIZE));
				w.setPreferredSize(new Dimension(minSizeWidth, w.getPreferredSize().height));
				/* ------------------------------------------------------- */
				roomCenterPanelLayout.appendColumn(ROOM_COLUMN_DEFAULT);
				roomCenterPanelLayout.appendColumn(ROOM_COLUMN_SPACE);
				int col = roomCenterPanelLayout.getColumnCount() - 1;
				/* ------------------------------------------------------- */
				roomCenterPanel.add(w, cc.xy(col, 2));
				/* ------------------------------------------------------- */
			}
			/* --------------------------------------------- */

			QueueEditDialog.setRooms(this.rooms);
			QueueEditDialog.setReasons(this.reasons);
		} catch (Exception e) {
			/* --------------------------------------------- */
			logger.error("Error fetching Waiting Rooms");
			/* --------------------------------------------- */
		}
		paine.validate();
		paine.updateUI();
		
		/* ================================================== */
	}
	
	
	/**
	 * @param room
	 */
	protected void saveRoom(Room room) {
		/* ================================================== */
		try {
			/* --------------------------------------------- */
			room.setIsWaitingroom(true);
			
			WaitingroomManager manager = (WaitingroomManager) ManagerFactory.getRemote(WaitingroomManagerBean.class);
			logger.info("changed Waitingroom " + room);
			manager.saveRoom(room, MainFrame.getClientId());
			/* --------------------------------------------- */
		} catch (Exception e) {
			/* --------------------------------------------- */
			logger.error("Error saving Waiting Room");
			/* --------------------------------------------- */
		}
		/* ================================================== */
	}
	
	/**
	 * reloads the queues
	 */
	public void reloadQueues (QueueUpdateEvent update)
	{
		/* ================================================== */
		long start = System.currentTimeMillis();
		
		Date day = getDay();
		
		Integer roomId = null;
		if (update != null)
			roomId = update.getRoomId();
		
		LinkedList<Waitingroom> rooms2Update = new LinkedList<Waitingroom>();
		for (Waitingroom w : this.waitingrooms.values())
		{
			if (roomId == null || roomId.equals(w.getRoom().getId()))
				rooms2Update.add(w); 
		}
		
		for (Waitingroom w : rooms2Update) {
			w.loadData(update, day);			
		}
		
		this.physicianAgendaDialog.loadData(update);
		
		long took = (System.currentTimeMillis() - start);
		
		if (update != null)	{
			logger.info("Waitingroom Update: " + update.toString() + " took:" + took);
		} else {
			logger.info("Waitingroom Update: " + " FULL RELOAD ALL ROOMS for "+df.format(day)+" took:" + took);
			GECAMedLog.user(WaitingroomModule.MODULE_NAME, WAITINGROOM_UPDATE, "FULL RELOAD ALL ROOMS for"+df.format(day) , took);
		}
		
		/* ================================================== */
	}
	
	private Date getDay() {
		return day;
	}



	/**
	 * Inits the listener for the JMS topic to update
	 * the calendars if there are changes on a loaded calendar
	 * by another user
	 */
	private void initTopicListener() {
		/* ================================================== */
	this.topicListener = new GeneralGECAMedTextMessageReciever(
			WaitingroomManager.TOPIC_NAME, new MessageListener() {

		    public void onMessage(Message msg) {
			if (msg instanceof ObjectMessage) {
			    ObjectMessage om = (ObjectMessage) msg;
			    try {
					if (om.getObject() instanceof QueueUpdateEvent) {
					    final QueueUpdateEvent update = (QueueUpdateEvent) om.getObject();
						SwingUtilities.invokeLater(new Runnable() {
							public void run() {
								reloadQueues(update);
							}
						});
					} else if (om.getObject() instanceof String && WaitingroomManager.TOPIC_CMD_ROOM_UPDATE.equals(om.getObject())) {
						loadRooms();
						mainPanel.validate();
						mainPanel.updateUI();
					}
			    } catch (Exception e) {
			    	logger.warn("Error handling Waitingroom Update Message", e);
			    }
			}
		    }

		});
		/* ================================================== */
	}
	
	
	
	/**
	 * init the module actions
	 */
	private void initActions() {
		/* ================================================== */
		// Show rooms header button
		String icon = "";
		if ((Boolean) waitingroomSettingsPlugin.getValue(WaitingroomSettingsPlugin.SHOW_ALL_WAITINGROOMS_ENABLED))
			icon = SHOW_ONE_ROOM;
		else
			icon = SHOW_ALL_ROOMS;
		
		showWaitingRoomButton = new JToggleButton(getMediumIcon(icon));
		
		showWaitingRoomButton.addActionListener(new ActionListener() {
			
			public void actionPerformed(ActionEvent e) {
				// set button icon
				if ((Boolean) waitingroomSettingsPlugin.getValue(WaitingroomSettingsPlugin.SHOW_ALL_WAITINGROOMS_ENABLED))
				{
					showWaitingRoomButton.setIcon(getMediumIcon(SHOW_ALL_ROOMS));
					showWaitingRoomButton.setToolTipText(Translatrix.getTranslationString("waitingroom.showAllWaitingroomText"));
				}else{
					showWaitingRoomButton.setIcon(getMediumIcon(SHOW_ONE_ROOM));
					showWaitingRoomButton.setToolTipText(Translatrix.getTranslationString("waitingroom.showOneWaitingroomText"));
				}
				
				// set user setting
				waitingroomSettingsPlugin.setValueAndSave(WaitingroomSettingsPlugin.SHOW_ALL_WAITINGROOMS_ENABLED, !(Boolean) waitingroomSettingsPlugin.getValue(WaitingroomSettingsPlugin.SHOW_ALL_WAITINGROOMS_ENABLED));
				
				// refresh waitingroom - do not send a message to all users
				loadRooms();
				mainPanel.validate();
				mainPanel.updateUI();
				
			}
		});
		// button style
		showWaitingRoomButton.setToolTipText(Translatrix.getTranslationString("waitingroom.showAllWaitingroomsText"));
		showWaitingRoomButton.setMargin(new java.awt.Insets(0, 0, 0, 0));
		
		showWaitingRoomButton.setFocusable(false);
		
		showWaitingRoomButton.setContentAreaFilled(false);
		showWaitingRoomButton.setBorderPainted(false);
		
		showWaitingRoomButton.addMouseListener(new MouseAdapter() {

			@Override
			public void mouseEntered(MouseEvent e) {
				/* ====================================================== */
				showWaitingRoomButton.setBorderPainted(true);
				showWaitingRoomButton.setContentAreaFilled(true);
				/* ====================================================== */
			}
			@Override
			public void mouseExited(MouseEvent e) {
				/* ====================================================== */
				showWaitingRoomButton.setBorderPainted(false);
				showWaitingRoomButton.setContentAreaFilled(false);
				/* ====================================================== */
			}
		});
		addTopButton(showWaitingRoomButton);
				
		// Reload header button // TODO
		new GECAMedAction(this, "waitingroom.reload",
				GECAMedModule.getMediumIcon(GECAMedModule.RELOAD), KeyEvent.VK_F5, true,
				true, false, KeyEvent.VK_F5) {
			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e) {
				boolean agendaImport = false;
				try {
					agendaImport = (Boolean) adminSettings.getValue(WaitingroomAdminSettingsPlugin.AUTO_IMPORT_ENABLED);
				} catch (Exception e2) {}

				reload(agendaImport);					

			}
		}.add();
		
		new GECAMedAction(this, "waitingroom.importfromagenda",
				getMediumIcon(IMPORT_FROM_AGENDA), null, true,
				true, false) {
			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e) {
				reload(true);
			}
		}.add();
		
		AbstractAction showDialogAction = new GECAMedAction(this, "waitingroom.show_physician.agenda",
				null, KeyEvent.VK_F12, false,
				false, false, KeyEvent.VK_F12) {
			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e) {
				/* ------------------------------------------------------- */
				physicianAgendaDialog.showDialog();
				/* ------------------------------------------------------- */
			}
		};
		/* ------------------------------------------------------- */
		// register global action
		/* ------------------------------------------------------- */
		RegistrationDesk.registerHotKey(KeyEvent.VK_F12, showDialogAction);
		/* ================================================== */
	}
	
	
	
	
	public void reload(final boolean importFromCal) {
		new Thread() {
    	    public void run() {
    	    	if (reloadIsRunning)
    	    		return;
    	    	try {
//    	    		long start = System.currentTimeMillis();
    	    		reloadIsRunning = true;
    	    		if (importFromCal) {
    	    			getManager().collectAppointments4Waitingrooms((Locale)AgendaModule.getInstance().getAgendaAdminSettingsPlugin().getValue(AgendaAdminSettingsPlugin.CALENDAR_LOCALE), false);    	    			
    	    		}
//    	    		long took = (System.currentTimeMillis()-start);
//    	    		GECAMedLog.user(MODULE_NAME, WAITINGROOM_RELOAD, "collectAppointments4Waitingrooms()", took);
    	    		reloadQueues(null);
				} catch (Exception e2) {
					logger.warn("Error reloading Waitingrooms");
				}
				reloadIsRunning = false;
    	    }
    	}.start();
	}



	/**
	 * @return Returns the session bean instance of the WaitingroomManager
	 */
	private WaitingroomManager getManager() {
		/* ================================================== */
		return (WaitingroomManager) ManagerFactory.getRemote(WaitingroomManagerBean.class);
		/* ================================================== */
	}
	
	public void actionPerformed(ActionEvent e) {
		/* ====================================================== */
		if (this.clearButton.equals(e.getSource())) {
			/* ------------------------------------------------------- */
			// clear the searchfield and request focus
			/* ------------------------------------------------------- */
			this.searchField.setText("");
			this.searchField.requestFocusInWindow();
			/* ------------------------------------------------------- */
		} else
			if (this.searchField.equals(e.getSource()) || searchButton.equals(e.getSource())) {
				/* ------------------------------------------------------- */				
				Patient selectedPatient = PatientSearchDialog.searchPatient(searchField.getText());
				if (selectedPatient == null)
					return;
//				try {
//					this.searchField.setText(selectedPatient.toString());
//				} catch (Exception e1) {
//				}  

				move2Waitingroom(selectedPatient);
				this.searchField.setText("");
			} else
				if (this.createPatientButton.equals(e.getSource())) {
					// open create patient dialog 
					this.patientCreateDialog = new PatientCreateDialog(Translatrix.getTranslationString("pm.newPatient"), true, true);
					// get selected patient
					Patient selectedPatient = patientCreateDialog.showDialog();	
					// set selected patient to selected waitingroom
					this.move2Waitingroom(selectedPatient);
				}
	}	
	
	
//	public void changedUpdate(DocumentEvent e) {
//		/* ====================================================== */
//		if (!blockDocumentListener)
//			this.selectedPatient = null;
//		/* ====================================================== */
//	}
//	public void insertUpdate(DocumentEvent e) {
//		/* ====================================================== */
//		if (!blockDocumentListener)
//			this.selectedPatient = null;
//		/* ====================================================== */
//	}
//	public void removeUpdate(DocumentEvent e) {
//		/* ====================================================== */
//		if (!blockDocumentListener)
//			this.selectedPatient = null;
//		/* ====================================================== */
//	}
	
	
	/**
	 * Moves a patient to a waiting room. This creates a new queue
	 * entry in the Queue table.
	 * If there is more than one waitingroom, the user is prompted
	 * to select the desired room. 
	 * 
	 * @param patientId
	 * @return
	 */
	public boolean move2Waitingroom(Patient patient) {
		/* ================================================== */
		if (patient == null || !patient.isPersistent())
			return false;
		/* ------------------------------------------------------- */
		// check the amount of rooms
		/* ------------------------------------------------------- */
		Date dayNTime = getDay();
		Calendar c = new GregorianCalendar();
		c.setTime(dayNTime);
		
		Calendar nowTime = new GregorianCalendar();
		nowTime.setTime(new Date());
		
		c.set(Calendar.HOUR_OF_DAY, nowTime.get(Calendar.HOUR_OF_DAY));
		c.set(Calendar.MINUTE, 		nowTime.get(Calendar.MINUTE));
		c.set(Calendar.SECOND, 		nowTime.get(Calendar.SECOND));
		
		Queue q = new Queue();
		q.setRoomId(null);
		q.setStartDate(c.getTime());
		q.setDescription("MATR:" + patient.getSocialSecurityNumber() + " ID:"+patient.getId());
		q.setKilometers(0);
		q.setIsVisit(false);
		q.setReason(null);
		q.setPatientId(patient.getId());
		q.setPatientName(patient.toShortString());
		q.setIsPresent(true);
		
		if (this.rooms.size() > 1) {
			/* ------------------------------------------------------- */
			QueueEditDialog sd = new QueueEditDialog();	
			q = sd.showDialog(q);

			/* ------------------------------------------------------- */
		} else {
			if (rooms.size() == 1) {
				q.setRoomId(rooms.get(0).getId());
			}
		}
		
		if (q == null || q.getRoomId() == null) {
			return false;
		}
		
		/* ------------------------------------------------------- */
		// push the id to the session bean
		/* ------------------------------------------------------- */
		try {
			/* ------------------------------------------------------- */
			long start = System.currentTimeMillis();
			q = getManager().createQueue(q, MainFrame.getClientId());
			if (q == null) {
				logger.error("Not adding Patient to Waitingroom, Already in");
				return false;
			}
			try {
				long took = (System.currentTimeMillis()-start);
			    GECAMedLog.user(
			    		WaitingroomModule.MODULE_NAME,
			    		WAITINGROOM_ADD,
			    		"Patient " + patient.toShortString() + " added to Waitingroom " + q.getRoomId() + " took " + took + "ms", 
			    		took);
			} catch (Exception e) {
				logger.error("Error moving Patient to Waitingroom", e);
			}
			return true;
			/* ------------------------------------------------------- */
		} catch (Exception e) {
			/* ------------------------------------------------------- */
			logger.error("Error moving Patient to Waitingroom", e);
			return false;
			/* ------------------------------------------------------- */
		}
		/* ================================================== */
	}
		
	/* ########################################################################################
	 * Icon methods
	 */
	public static ImageIcon getIcon (String p_IconName) { 
		/* ================================================== */
		return IconFetcher.getIcon(WaitingroomModule.class, p_IconName);
		/* ================================================== */
	}

	
	public static ImageIcon getAnchorScaledIcon(String p_IconName, int size) { 
		/* ================================================== */
		ImageIcon image = getIcon(p_IconName);
		
		
		/* ------------------------------------------------------- */
		int w = image.getIconWidth(); 
        int h = image.getIconHeight(); 
        double f = 0; 
        if (w < h) { 
            f = (double) h / (double) w; 
            w = (int) (size / f); 
            h = size; 
        } else { 
            f = (double) w / (double) h; 
            w = size; 
            h = (int) (size / f); 
        }
        /* ------------------------------------------------------- */
	return new ImageIcon(getIcon(p_IconName).getImage().getScaledInstance(
			w, h, Image.SCALE_SMOOTH));
	/* ================================================== */
	}
	

	public static ImageIcon getScaledIcon(String p_IconName, int size) 
		{
		return new ImageIcon(getIcon(p_IconName).getImage().getScaledInstance(
				size, size, Image.SCALE_SMOOTH));
		}

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

		public static ImageIcon getMiniIcon(String p_IconName) {
		    return IconFetcher.getMiniIcon(WaitingroomModule.class, p_IconName);
		}

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

		public static ImageIcon getSmallIcon(String p_IconName) {
		    return IconFetcher.getSmallIcon(WaitingroomModule.class, p_IconName);
		}

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

		public static ImageIcon getMediumIcon(String p_IconName) {
		    return IconFetcher.getMediumIcon(WaitingroomModule.class, p_IconName);
		}

//	---------------------------------------------------------------------------
			
		public static ImageIcon getBigIcon(String p_IconName) {
		    return IconFetcher.getBigIcon(WaitingroomModule.class, p_IconName);
		}
//		---------------------------------------------------------------------------
		public static ImageIcon getNormalIcon(String p_IconName) {
			return IconFetcher.getScaledIcon(WaitingroomModule.class, p_IconName, NORMALPIX);
		}

		@Override
		protected void preparetoShowup() {
		}

	public void physicianChanged(Physician physician)
	{
		// if only waitingroom for current physician is shown...reload on physician change
		if (!(Boolean) waitingroomSettingsPlugin.getValue(WaitingroomSettingsPlugin.SHOW_ALL_WAITINGROOMS_ENABLED)) {
			try {
				loadRooms();
				mainPanel.validate();
				mainPanel.updateUI();
			} catch (Exception e1) {
				logger.error("Error reloading room", e1);
			}
		}
	}
		
	private void addPhysicianListener()
	{
		RegistrationDesk.addPhysicianListener(this);
	}
	
	public void setShowRoomButton()
	{
		String icon = "";
		if ((Boolean) waitingroomSettingsPlugin.getValue(WaitingroomSettingsPlugin.SHOW_ALL_WAITINGROOMS_ENABLED))
			icon = SHOW_ONE_ROOM;
		else
			icon = SHOW_ALL_ROOMS;
		
		showWaitingRoomButton.setIcon(getMediumIcon(icon));
	}
	
	private Queue getQueue(Integer id) {
		Queue q = null;
		for (Waitingroom r : waitingrooms.values()) {
			q = r.getQueueById(id);
			if (q != null) return q;
		}
		return q;
	}
	
	public static void editQueue(Integer queueId) {
		try {
			WaitingroomModule m = getInstance();
			if (m == null) return;
			
			Queue q = m.getQueue(queueId);
			if (q != null) {
				MainFrame.getInstance().selectModule(MODULE_NAME);
				
				m.waitingrooms.get(q.getRoomId()).editQueue(q);
			}			
		} catch (Exception e) {
			logger.warn("Error editing Queue with ID: " + queueId, e);
		}
	}
}
