/*****************************************************************************
 *                                                                           *
 *  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  *
 *                                                                           *
 *****************************************************************************/
/*
 * Author: Johannes Hermen Tudor/Santec
 * Mail: johannes.hermen@tudor.lu
 * Created: Mar 9, 2005
 *
 */
package lu.tudor.santec.gecamed.core.gui.widgets;

import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import javax.jms.JMSException;
import javax.jms.TextMessage;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.DefaultListCellRenderer;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JSeparator;
import javax.swing.border.Border;
import javax.swing.text.JTextComponent;

import lu.tudor.santec.gecamed.core.ejb.session.interfaces.MessageSenderInterface;
import lu.tudor.santec.gecamed.core.gui.GECAMedAction;
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.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.AutoCompletion;
import lu.tudor.santec.gecamed.office.ejb.entity.beans.Physician;
import lu.tudor.santec.gecamed.usermanagement.gui.settings.UserSettingsPlugin;
import lu.tudor.santec.i18n.Translatrix;

import org.apache.log4j.Logger;

import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.l2fprod.gui.border.LineBorder;
import com.lowagie.text.Font;
import com.netghost.perkup.AcceleratingSlider;
import com.netghost.perkup.DefaultNotification;
import com.netghost.perkup.DefaultNotificationHandler;
import com.netghost.perkup.Notifier;
import com.netghost.perkup.WindowSlider;
import com.netghost.perkup.swing.PopupWindow;


/**
 * this class builds a status bar, with a info and message label and a progressbar
 * and provides methods to set them. all messages are automaticaly deleted from the
 * statusbar after the specified time or when a new message arrives.
 *
 * This class is static.
 *
 * @author Johannes Hermen johannes.hermen@tudor.lu Tudor/Santec
 * @updated Martin Heinemann martin.heinemann@tudor.lu
 * 
 * @Version
 * <br>$Log: StatusBar.java,v $
 * <br>Revision 1.34  2013-08-05 08:22:01  ferring
 * <br>Physician keys not stored by translated name anymore
 * <br>
 * <br>Revision 1.33  2011-03-10 06:53:33  ferring
 * <br>bug fixed, where all global GECAMedAction had been shown in the patient module top bar, independent of they were specified to be a top button action or not.
 * <br>Now they are only shown, if they ought to be a top button action.
 * <br>
 * <br>Revision 1.32  2011-03-04 09:53:11  ferring
 * <br>Hotkeys for physicians added.
 * <br>It is now possible to make a hotkey consisting of key + modifiers.
 * <br>
 * <br>Revision 1.31  2010-10-05 13:42:43  troth
 * <br>Complete - # 560: Arztwechsel im Verschreibungs-Dialogfenster erm�glichen
 * <br>http://santec.tudor.lu/trac/gecamed/ticket/560
 * <br>
 * <br>Revision 1.30  2010-02-09 13:27:21  troth
 * <br>update method showGECAMedMessage which allows now to load usermessages from the data base usermanagement.message
 * <br>
 * <br>Revision 1.29  2009-01-22 10:32:31  hermen
 * <br>added and implemented right PERMISSION_CHANGE_PHYSICIAN which allows/disallows a user to change the current physician
 * <br>
 * <br>Revision 1.28  2008-12-15 14:06:12  hermen
 * <br>made physicianchooser bigger and reachable via f11
 * <br>
 * <br>Revision 1.27  2008-12-15 13:46:26  hermen
 * <br>made physician chooser bigger
 * <br>
 * <br>Revision 1.26  2008-11-18 11:07:05  hermen
 * <br>changed PhysicianChooser for Maisons médicales
 * <br>
 * <br>Revision 1.25  2008-09-25 09:43:06  heinemann
 * <br>fixed copyrights
 * <br>
 * <br>Revision 1.24  2008-08-21 15:45:12  heinemann
 * <br>removed the bogus behaviour when there is no office entry in the database. The fields on the print outs are now left blank. The user gets an information that the office address is missing.
 * <br>
 * <br>Revision 1.23  2008-05-29 13:34:47  hermen
 * <br>fixed physiciancombobox
 * <br>
 * <br>Revision 1.21  2008-01-15 09:29:38  hermen
 * <br>updated Javadoc and refactured code
 * <br>
 * <br>Revision 1.20  2007-12-06 14:46:44  hermen
 * <br>updated Javadoc and refactured code
 * <br>
 * 
 */
public class StatusBar extends JPanel implements ActionListener, PhysicianListener
{
    //~ Static fields/initializers =============================================
	/** the logger Object for this class */
	private static Logger logger = Logger.getLogger(StatusBar.class.getName());
	
    private static final long serialVersionUID = 1L;

    /**
     * the value to set the statusbar to show the indeterminate-status
     */
    public static final int PROGRESS_INDETERMINATE = -1;


    /**
     * the default time to show the messages on the statusbar
     */
    public static final int SHOW_TEXT_TIME = 4000;
    public static final int SHOW_TEXT_TIME_INFINITY = -1;

    //~ Instance fields ========================================================
    private static final int I_SCALE = 64;
    public static final ImageIcon ICON_INFO = GECAMedModule.getScaledIcon(GECAMedIconNames.INFO, I_SCALE);
    public static final ImageIcon ICON_WARNING = GECAMedModule.getScaledIcon(GECAMedIconNames.WARNING, I_SCALE);
    public static final ImageIcon ICON_MESSAGE = GECAMedModule.getScaledIcon(GECAMedIconNames.MESSAGE, I_SCALE);
    public static final ImageIcon ICON_ERROR = GECAMedModule.getScaledIcon(GECAMedIconNames.ERROR, I_SCALE);
    public static final ImageIcon ICON_URGENT = GECAMedModule.getScaledIcon(GECAMedIconNames.URGENT, I_SCALE);

    private static final int CHOOSE_PHYSICIAN_KEY = KeyEvent.VK_F11;

    private Border selectedBorder = BorderFactory.createLineBorder(Color.BLUE, 2);
    
    private static StatusBar instance = new StatusBar();

    protected int messageThreadCount;
    private JLabel infoLabel;
    private MessageLabel messageLabel;
    private JLabel progressTextLabel;
    private JProgressBar progressBar;
    private String progressText;
    private String warningText;
    private int infoThreadCount;
    private int progressProcent;
    private int progressShowTime;
    private int statusThreadCount;
    private int warningShowTime;


	private AcceleratingSlider slider;

	private Notifier cornerAlerter;

	private GECAMedPopupWindow popup;

	private JComboBox<Physician> physicianBox;

	protected boolean listenerDisabled = false;

//	private ComboBoxModel physicianComboBoxModel;


    //~ Constructors ===========================================================
    /**
     * creates a new StatusBar object with a ProgressBar, an ErrorMessage Field etc..
     * and methods to set them.
     *
     * @param mainFrame a reference to the mainFrame of the Program to obtain all child-objects from
     */
    private StatusBar()
    {
        //        this.mainFrame = mainFrame;
        this.buildPanel();
        initToaster();
        addPhysicianListener();
    }

    /**
     * Returns the instance of the StatusBar
     *
     * @return
     */
    public static StatusBar getInstance() {
        return instance;
    }


    //~ Methods ================================================================
    /**
     * sets the messagelabel of the statusbar
     *
     * @param messageText the text to be shown
     * @param showTime the time how long this warning should be shown
     */
    public synchronized void setMessageText(String messageText, int showTime)
    {
        showToastMessage(ICON_MESSAGE, "Message", messageText);
    }

    /**
     * sets the messagelabel of the statusbar
     *
     * @param messageText the text to be sho
     */
    public synchronized void setMessageText(String messageText)
    {
        this.setMessageText(messageText, StatusBar.SHOW_TEXT_TIME);
    }

    /**
     * sets the progressbar and the progresslabel of the statusbar.
     *
     * @param progressText the text to be set.
     * @param progressProcent the procent value to set the progressbar to (0-100)
     * @param showTime the time to show the text and the progressbar
     */
    public synchronized void setProgress(String progressText, int progressProcent,
        int showTime)
    {
        this.progressText = progressText;
        this.progressProcent = progressProcent;
        this.progressShowTime = showTime;

        if (progressProcent == 100) {
        	this.showToastMessage(ICON_INFO, "Info", progressText);
        }

        Thread t = new Thread() {
                public void run()
                {
                    statusThreadCount++;
                    progressTextLabel.setText(StatusBar.this.progressText);
                    if (StatusBar.this.progressProcent < 0) {
                        progressBar.setIndeterminate(true);
                    } else {
                        progressBar.setIndeterminate(false);
                        progressBar.setValue(StatusBar.this.progressProcent);
                    }
                    try {
                        Thread.sleep(progressShowTime);
                    } catch (InterruptedException e) {
                    }
                    if (statusThreadCount == 1) {
                        progressBar.setIndeterminate(false);
                        progressBar.setValue(0);
                        progressTextLabel.setText("");
                    }
                    statusThreadCount--;
                }
            };
        t.start();
    }

    /**
     * sets the progressbar and the progresslabel of the statusbar.
     *
     * @param progressText the text to be set.
     * @param progressProcent the procent value to set the progressbar to (0-100)
     */
    public synchronized void setProgress(String progressText, int progressProcent)
    {
        this.setProgress(progressText, progressProcent, StatusBar.SHOW_TEXT_TIME);
    }

    /**
     * sets the warninglabel of the statusbar
     *
     * @param warningText the text to be shown
     * @param showTime the time how long this warning should be shown
     */
    public synchronized void setWarningText(String warningText, int showTime)
    {
        this.warningText = warningText;
        this.warningShowTime = showTime;
        
        /* ------------------------------------------------------- */
        // set a permanent message
        /* ------------------------------------------------------- */
        if (warningShowTime == SHOW_TEXT_TIME_INFINITY) {
        	/* ------------------------------------------------------- */
        	infoLabel.setText(StatusBar.this.warningText);
        	this.showToastMessage(ICON_WARNING, "Warning", warningText);
        	return;
        	/* ------------------------------------------------------- */
        }
        /* ------------------------------------------------------- */
        // if the show time is set
        /* ------------------------------------------------------- */
        this.showToastMessage(ICON_WARNING, "Warning", warningText);

        Thread t = new Thread() {
                public void run()
                {
                    infoThreadCount++;
                    infoLabel.setText(StatusBar.this.warningText);
                    try {
                        Thread.sleep(warningShowTime);
                    } catch (InterruptedException e) {
                    }
                    if (infoThreadCount == 1) {
                        infoLabel.setText("");
                    }
                    infoThreadCount--;
                }
            };
        t.start();
    }

    /**
     * sets the warninglabel of the statusbar
     *
     * @param warningText the text to be shown
     */
    public synchronized void setWarningText(String warningText)
    {
        this.setWarningText(warningText, StatusBar.SHOW_TEXT_TIME);
    }

    /**
     * adds the components to the panel
     */
    @SuppressWarnings("unchecked")
	private void buildPanel()
	{
		// initialize components
		initComponents();
		// build Layout
		FormLayout layout = new FormLayout("2dlu, fill:100dlu, 2dlu, pref, 2dlu, fill:120dlu, 2dlu, pref, 2dlu, fill:pref:grow, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu,fill:120dlu,2dlu",
				"2dlu, fill:15dlu, 2dlu");
		CellConstraints cc = new CellConstraints();
		this.setLayout(layout);
		this.add(this.infoLabel, cc.xy(2, 2));
		this.add(new JSeparator(JSeparator.VERTICAL), cc.xy(4, 2));
		this.add(this.messageLabel, cc.xy(6, 2));
		this.add(new JSeparator(JSeparator.VERTICAL), cc.xy(8, 2));
		this.add(this.progressTextLabel, cc.xy(10, 2));
		this.add(new JSeparator(JSeparator.VERTICAL), cc.xy(12, 2));
		this.add(this.progressBar, cc.xy(14, 2));
		
		List<Physician> phys = GECAMedLists.getListReference(Physician.class);
		Collections.sort(phys);
		
		ReloadListener reloadListener = new ReloadListener()
		{
			public void prepareReload () {}
			
			public void reloaded ()
			{
				try	{
					listenerDisabled = true;
					if (MainFrame.getCurrentPhysician() != null) {
						physicianBox.setSelectedItem(MainFrame.getCurrentPhysician());
					} else if (physicianBox.getSelectedIndex() >= 0){
						MainFrame.setCurrentPhysician((Physician) physicianBox.getSelectedItem());
					} else {
						physicianBox.setSelectedIndex(0);
						MainFrame.setCurrentPhysician((Physician) physicianBox.getSelectedItem());
					}
				} catch (Exception e) {
					logger.error("Error while trying to update physician box", e);
				} finally {
					listenerDisabled = false;
				}
				Physician p = (Physician) physicianBox.getSelectedItem();
				physicianBox.setBackground(p == null || p.getColor() == null ? Color.WHITE : new Color(p.getColor()));
			}
		};
		
		JLabel physicianIconLabel = new JLabel(IconFetcher.getMediumIcon(GECAMedModule.class, GECAMedModule.PHYSICIAN));
		physicianIconLabel.setOpaque(false);
		this.add(physicianIconLabel, cc.xy(16, 2));
		
		physicianBox = new JComboBox<Physician>(new PhysicianListModel(reloadListener));
		physicianBox.setFont(physicianBox.getFont().deriveFont(Font.BOLD, 16));
		physicianBox.setOpaque(true);
		Set<Physician> physicians = MainFrame.getCurrentUser().getPhysicians();
		if (physicians != null && physicians.size() > 0)
		{
			Physician currentPhysician = physicians.iterator().next();
			MainFrame.setCurrentPhysician(currentPhysician);
		}
		reloadListener.reloaded();
		
		this.add(physicianBox, cc.xy(18, 2));
		
//		if (phys.size() > 5)
//			AutoCompletion.enable(physicianBox);
		
        if (phys.size() > 5) {
        	AutoCompletion.enable(physicianBox);
        	try {
        		((JTextComponent)physicianBox.getEditor().getEditorComponent()).setOpaque(false);        	
        	} catch (Exception e) {}
        }		
		
		physicianBox.addActionListener(this);
		physicianBox.setToolTipText(Translatrix.getTranslationString("main.selectCurrentPhysician"));
		
		physicianBox.setRenderer(new DefaultListCellRenderer()
		{
			private static final long	serialVersionUID	= 1L;
			@Override
			public Component getListCellRendererComponent (JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
			{
				
				JLabel c = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected,cellHasFocus);
				c.setOpaque(true);
				try
				{
					if (isSelected)	{
						c.setBackground(new Color(((Physician) value).getColor()).brighter());
						c.setBorder(selectedBorder);
					} else {
						c.setBackground(new Color(((Physician) value).getColor()));
						c.setBorder(null);
					}
				}
				catch (Exception e) {
					c.setBackground(new JLabel().getBackground());
				}
				return c;
			}
		});
		
		
		if (!GECAMedModule.userHasPermission(MainFrame.PERMISSIONS_CORE, MainFrame.PERMISSION_CHANGE_PHYSICIAN)) {
			this.physicianBox.setEnabled(false);
		}
		
		// set the initial physician
		// if the current user has a link to a physician, select it
		if (phys != null)
		{
			for (Physician p : phys)
			{
				/* ------------------------------------------------------ */
				if (MainFrame.getCurrentUser().getId().equals(p.getUserId()))
				{
					// select the physician in the combobox
					physicianBox.setSelectedItem(p);
					break;
				}
				/* ------------------------------------------------------ */
			}
		}
		// write the physician to the mainframe
		// MainFrame.setCurrentPhysician((Physician) physicianBox.getSelectedItem());
		actionPerformed(null);
		
		// action to show the searchpanel
		AbstractAction choosePhysicianAction = new GECAMedAction(
				null, "main.selectCurrentPhysician", GECAMedModule.getIcon(GECAMedIconNames.PHYSICIAN), 0, false, true, false) {
			private static final long	serialVersionUID	= 1L;
			
			public void actionPerformed (ActionEvent e)	{
				physicianBox.requestFocus();
				physicianBox.showPopup();
			}
		};
		
		// register the global hotkeys
		RegistrationDesk.registerHotKey(CHOOSE_PHYSICIAN_KEY, choosePhysicianAction);
		
		// hotkeys for all physician
		int hotkey = KeyEvent.VK_0;
		
		for (final Physician physician : phys)
		{	
			GECAMedAction choosePhysician = new GECAMedAction(null, GECAMedAction.getHotKeyName(physician), null, 0, false, false, false, hotkey, KeyEvent.CTRL_MASK) {
				private static final long	serialVersionUID	= 1L;
				public void actionPerformed (ActionEvent e)	{
					MainFrame.setCurrentPhysician(physician);
				}
			};
			choosePhysician.putValue(GECAMedAction.NOT_EDITABLE, "TRUE");
			choosePhysician.setTranslation(GECAMedAction.PHYSICIAN_TRANSLATION, physician.getName());
			RegistrationDesk.registerHotKey(hotkey++, KeyEvent.CTRL_MASK, choosePhysician);
			
			// stop after 9 physicians
			if (hotkey == KeyEvent.VK_9 + 1) {
				break;
			}
				
		}
	}



    /**
     * Inits the toaster
     */
    private void initToaster() {
    	slider = new AcceleratingSlider();
    	// ------------------
    	cornerAlerter = new Notifier();


        DefaultNotificationHandler handler = new DefaultNotificationHandler();

        popup = new GECAMedPopupWindow();
        handler.setPopup(popup);

        handler.getWindowController().setPresenter(slider);
        cornerAlerter.setHandler(handler);
        // --------------
        // change to corner

    }

    class GECAMedPopupWindow extends PopupWindow {

		private static final long serialVersionUID = 1L;
		private JLabel label;
		private String desc;
		private String msg;
		private Icon icon;

		public GECAMedPopupWindow() {
    		this.label = new JLabel();
    		this.label.setOpaque(true);
    		this.label.setBackground(Color.WHITE);
    		this.label.setVerticalAlignment(JLabel.TOP);
    		this.label.setBorder(new LineBorder(Color.GREEN));
    		this.add(this.label);
    	}

		@Override
		public void setDescription(String desc) {
			/* ============================================= */
			this.desc = desc.replaceAll("\\n", "<br>");
			this.updateLabel();
			/* ============================================= */
		}

		@Override
		public void setIcon(Icon icon) {
			/* ============================================= */
			this.icon = icon;
			this.label.setIcon(icon);
			/* ============================================= */
		}

		@Override
		public void setMessage(String msg) {
			/* ============================================= */
			this.msg = msg.replaceAll("\\n", "<br>");
			this.updateLabel();
			/* ============================================= */
		}

		private void updateLabel() {
			label.setText("<html><h2>" + msg + "</h2><p>" + desc + "&nbsp;&nbsp;</p>");
			this.pack();
		}

		@Override
		public String getDescription() {
			/* ============================================= */
			return desc;
			/* ============================================= */
		}

		@Override
		public Icon getIcon() {
			/* ============================================= */
			return icon;
			/* ============================================= */
		}

		@Override
		public String getMessage() {
			/* ============================================= */
			return msg;
			/* ============================================= */
		}

		@Override
		public void setVisible(boolean b) {
			/* ============================================= */
			super.setVisible(b);
			/* ============================================= */
		}

    }



    /**
     * Shows a piece of toast
     *
     * @param icon
     * @param msg
     */
    private synchronized void showToastMessage(Icon icon, String msg, String description) {
    	/* ================================================== */
    	if (! (Boolean)MainFrame.getInstance().userSettings.getValue(UserSettingsPlugin.TOASTER_ENABLED))
    		return;
    	slider.setCorner(WindowSlider.SOUTH_EAST);
        // ensure to display the toaster on the same screen as the main application
        slider.setGraphicsConfiguration(MainFrame.getInstance().getGraphicsConfiguration());
        cornerAlerter.alert(new DefaultNotification(this, msg, description + "\n", icon));
        try {
			description = "<html>" + description.replaceAll("\n", "<br>");
		} catch (Exception e) {
			// TODO: handle exception
		}
        MainFrame.getInstance().showMessage(description, 5000);
        /* ================================================== */
    }



    /**
     * initializes the Components
     */
    private void initComponents()
    {
        this.infoLabel = new JLabel();
        this.infoLabel.setForeground(Color.RED);
        this.messageLabel = new MessageLabel();
        this.progressTextLabel = new JLabel();
        this.progressTextLabel.setHorizontalAlignment(JLabel.RIGHT);
        this.progressBar = new JProgressBar();
        this.progressBar.setStringPainted(false);
        this.progressBar.setMinimum(0);
        this.progressBar.setMaximum(100);
    }

	/**
	 * ActionListener for the physician combobox
	 */
	public void actionPerformed (ActionEvent e)
	{
		/* ============================================= */
		// set the selected physician to the mainframe
		if (!listenerDisabled)
		{
			Physician phy = (Physician) physicianBox.getSelectedItem();
			MainFrame.setCurrentPhysician(phy);
		}
		/* ============================================= */
	}
	 
	public synchronized void showGECAMedMessage(TextMessage tm) {
		try {
			if (tm.getStringProperty(MessageSenderInterface.SENDER) == null) {
				setMessageText(tm.getText(), 10000);
			} else {
				String rec = tm.getStringProperty(MessageSenderInterface.RECEIVER);
				if (rec != null && 
						(rec.equals(MessageSenderInterface.ALL_USERS) || 
								rec.equals(MainFrame.getCurrentUser().getLogin()))) {
					if (tm.getBooleanProperty(MessageSenderInterface.IMPORTANT)) {
						JOptionPane.showMessageDialog(MainFrame.getInstance(),
							    tm.getText(), 
							    "Message from User: " + tm.getStringProperty(MessageSenderInterface.SENDER),
							    JOptionPane.INFORMATION_MESSAGE);
					} else {
						setMessageText("Message from User: " + tm.getStringProperty(MessageSenderInterface.SENDER) 
								+ "\r\n" +tm.getText(), 10000);
					}
					// load messages from database repaint messageTable in Dialog
					messageLabel.repaintMessageTable();
				}
			}
		} catch (JMSException e) {
			e.printStackTrace();
		}
	}
	
	private void addPhysicianListener() {
		RegistrationDesk.addPhysicianListener(this);
	}
	
	
	public void physicianChanged(Physician physician) {
		listenerDisabled = true;
		physicianBox.setSelectedItem(physician);
		
		try {
			physicianBox.setBackground(new Color(physician.getColor()));			
		} catch (Exception e) {
			physicianBox.setBackground(Color.WHITE);
		}
    	try {
    		((JTextComponent)physicianBox.getEditor().getEditorComponent()).setText(""+physician);       	
    	} catch (Exception e) {
    		logger.info("Error setting Physician to box",e);
    	}
		physicianBox.validate();
		listenerDisabled = false;
	}
	
}
