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

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;

import org.apache.log4j.Logger;

import lu.tudor.santec.gecamed.core.gui.GECAMedColors;
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.widgets.GECAMedBaseDialog;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.office.ejb.entity.beans.Physician;
import lu.tudor.santec.gecamed.patient.gui.PatientManagerModule;
import lu.tudor.santec.gecamed.waitingroom.ejb.entity.beans.Queue;
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.Waitingroom;
import lu.tudor.santec.gecamed.waitingroom.gui.WaitingroomModule;
import lu.tudor.santec.gecamed.waitingroom.gui.WaitingroomTableModel;
import lu.tudor.santec.gecamed.waitingroom.gui.widgets.WaitingroomTablePopup;
import lu.tudor.santec.i18n.Translatrix;
import bizcal.util.DateUtil;

/**
 * @author martin.heinemann@tudor.lu
 * 28.04.2008
 * 15:23:11
 *
 *
 * @version
 * <br>$Log: PhysicianAgendaDialog.java,v $
 * <br>Revision 1.8  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.7  2009-10-06 14:16:13  hermen
 * <br>added isVisit to waitingroom entry
 * <br>
 * <br>Revision 1.6  2009-05-15 08:37:34  hermen
 * <br>fixed NPE on firstrun (  no Physician )
 * <br>
 * <br>Revision 1.5  2008-09-25 09:43:07  heinemann
 * <br>fixed copyrights
 * <br>
 * <br>Revision 1.4  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.3  2008-05-08 09:10:02  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.2  2008-05-07 14:40:57  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.1  2008-04-29 14:17:38  heinemann
 * <br>*** empty log message ***
 * <br>
 *   
 */
public class PhysicianAgendaDialog extends GECAMedBaseDialog implements PhysicianListener{

	/**
	 * static logger for this class
	 */
	private static Logger logger = Logger.getLogger(PhysicianAgendaDialog.class.getName());
	
	
	private static final long serialVersionUID = 1L;
//	private PhysicianAgendaTableModel tableModel;
	private Physician currentPhysician;
	private JTable table;
	private JPanel panel;
	
	private DateFormat dateFormater = DateFormat.getDateInstance(DateFormat.SHORT);
	private DateFormat timeFormater = DateFormat.getTimeInstance(DateFormat.SHORT);
	private Timer clockTimer;
	private JPanel headerPanel;
	private JLabel dateLabel;
	private JLabel timeLabel;
	private KeyStroke strokeF12;
	private WaitingroomTableModel wModel;
	private WaitingroomTablePopup popup;
	
	/**
	 * @param title
	 */
	private PhysicianAgendaDialog(String title) {
		/* ================================================== */
		super(title, true, false);
		/* ================================================== */
	}
	public PhysicianAgendaDialog() {
		/* ================================================== */
		this("test");
		
		this.enableCancelKeyMapping(true);
		this.enableOkKeyMapping(true);
		initF12Keymapping();
		this.showHeader(true);
		this.setHeaderTitle("<html>"+dateFormater.format(new Date()));
		
		
		initComponent();
		// add physician listener
		initPhysicianListener();
		
		/* ------------------------------------------------------- */
		
		physicianChanged(MainFrame.getCurrentPhysician());
		
		/* ================================================== */
	}
	
	/**
	 * 
	 */
	private void initF12Keymapping() {
		/* ====================================================== */
		// Enter will close the dialog and confirm something
		/* ------------------------------------------------------- */
		this.strokeF12 = KeyStroke.getKeyStroke("F12");
		/* ------------------------------------------------------- */
		// add keymapping
		((JPanel) this.getContentPane()).getInputMap(
				JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
				.put(this.strokeF12, "F12");
		((JPanel) this.getContentPane()).getActionMap().put("F12", super.okAction);
		/* ====================================================== */
	}
	
	/**
	 * 
	 */
	private void initComponent() {
		/* ================================================== */
		initHeader();
//		this.tableModel = new PhysicianAgendaTableModel();
		
		this.wModel = new WaitingroomTableModel(Waitingroom.MODE_PHYSICIAN, false);
		
//		this.table = new JTable(tableModel);
		this.table = new JTable(wModel);
		
		JScrollPane paine = new JScrollPane(table);
		paine.getViewport().setBackground(GECAMedColors.c_GECAMedBackground);
		/* ------------------------------------------------------- */
		this.panel = new JPanel(new BorderLayout());
		panel.setOpaque(false);
		panel.add(paine, BorderLayout.CENTER);
		/* ------------------------------------------------------- */
		panel.add(new JLabel(" "), BorderLayout.WEST);
		panel.add(new JLabel(" "), BorderLayout.EAST);
		/* ------------------------------------------------------- */
		this.addMainPanel(panel);
		this.getContentPane().setBackground(GECAMedColors.c_GECAMedBackground);
		
		/* ------------------------------------------------------- */
		PhysicianAgendaTableRenderer renderer = new PhysicianAgendaTableRenderer(Waitingroom.MODE_PHYSICIAN, this.wModel);
		table.setDefaultRenderer(Object.class, renderer);
		table.setShowHorizontalLines(false);
		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		/* ------------------------------------------------------- */
		table.getTableHeader().setReorderingAllowed(false);
		table.getColumnModel().getColumn(2).setCellRenderer(renderer);
		
		table.getColumnModel().getColumn(0).setMinWidth(52);
		table.getColumnModel().getColumn(0).setMaxWidth(52);
		
		table.getColumnModel().getColumn(2).setMinWidth(20);
		table.getColumnModel().getColumn(2).setMaxWidth(20);
		
//		table.getColumnModel().getColumn(3).setMinWidth(20);
//		table.getColumnModel().getColumn(3).setMaxWidth(20);
		
		
		/* ------------------------------------------------------- */
		table.setTableHeader(null);
		table.setRowHeight(20);
		/* ------------------------------------------------------- */
		this.addComponentListener(new ComponentAdapter() {

			/* (non-Javadoc)
			 * @see java.awt.event.ComponentAdapter#componentHidden(java.awt.event.ComponentEvent)
			 */
			@Override
			public void componentHidden(ComponentEvent e) {
				/* ====================================================== */
				stopTimeTimer();
				/* ====================================================== */
			}

			/* (non-Javadoc)
			 * @see java.awt.event.ComponentAdapter#componentShown(java.awt.event.ComponentEvent)
			 */
			@Override
			public void componentShown(ComponentEvent e) {
				/* ====================================================== */
				startTimeTimer();
				/* ====================================================== */
			}
			
		});
		initTableListener();
		this.popup = new WaitingroomTablePopup(this.table, null);
		/* ================================================== */
	}
	
	private void initPhysicianListener() {
		/* ================================================== */
		RegistrationDesk.addPhysicianListener(this);
		/* ================================================== */
	}
	
	
	private void initTableListener() {
		/* ================================================== */
		this.table.addKeyListener(new KeyAdapter() {

			/* (non-Javadoc)
			 * @see java.awt.event.KeyAdapter#keyPressed(java.awt.event.KeyEvent)
			 */
			@Override
			public void keyPressed(KeyEvent e) {
				/* ====================================================== */
				if (KeyEvent.VK_ENTER == e.getKeyCode()) {
					/* ------------------------------------------------------- */
					// mark as treated and open the file
					/* ------------------------------------------------------- */
					openSelected();
				}
				if (KeyEvent.VK_SPACE == e.getKeyCode()) {
					/* ------------------------------------------------------- */
					// toggle selected treated
					/* ------------------------------------------------------- */
					wModel.toggleTreated(table.getSelectedRow());
					/* ------------------------------------------------------- */
				}
					
				/* ====================================================== */
			}
		});
		/* ------------------------------------------------------- */
		this.table.addMouseListener(new MouseAdapter() {

			/* (non-Javadoc)
			 * @see java.awt.event.MouseAdapter#mousePressed(java.awt.event.MouseEvent)
			 */
			@Override
			public void mousePressed(MouseEvent e) {
				/* ====================================================== */
				if (e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton(e)) {
					/* ------------------------------------------------------- */
					int row = table.rowAtPoint(e.getPoint());
					int col = table.columnAtPoint(e.getPoint());
					/* ------------------------------------------------------- */
					// get the value for that cell
					/* ------------------------------------------------------- */
					Object obj = wModel.getValueAt(row, col);
					if (col != 1 || !(obj instanceof String))
							openSelected();
					/* ------------------------------------------------------- */
				}
				/* ------------------------------------------------------- */
				if (e.isPopupTrigger()) {
					/* ------------------------------------------------------- */
					// select the row
					/* ------------------------------------------------------- */
					int row = table.rowAtPoint(e.getPoint());
					table.getSelectionModel().setSelectionInterval(row, row);
					/* ------------------------------------------------------- */
					// show popup
					/* ------------------------------------------------------- */
					popup.adjustPopup();
					popup.getPop().show(table, e.getX(), e.getY());
					/* ------------------------------------------------------- */
				}
				/* ====================================================== */
			}

			/* (non-Javadoc)
			 * @see java.awt.event.MouseAdapter#mouseReleased(java.awt.event.MouseEvent)
			 */
			@Override
			public void mouseReleased(MouseEvent e) {
				/* ====================================================== */
				if (e.isPopupTrigger()) {
					/* ------------------------------------------------------- */
					// select the row
					/* ------------------------------------------------------- */
					int row = table.rowAtPoint(e.getPoint());
					table.getSelectionModel().setSelectionInterval(row, row);
					/* ------------------------------------------------------- */
					// show popup
					/* ------------------------------------------------------- */
					popup.adjustPopup();
					popup.getPop().show(table, e.getX(), e.getY());
					/* ------------------------------------------------------- */
				}
				/* ====================================================== */
			}
		});
		/* ================================================== */
	}
	
	
	/**
	 * Marks the selected patient as treated and opens the file
	 */
	public void openSelected() {
		/* ================================================== */
		int row = table.getSelectedRow();
		wModel.setTreated(row);
		/* ------------------------------------------------------- */
		this.setVisible(false);
		Queue q = wModel.getQueue(row);
		PatientManagerModule.getInstance().loadPatient(q.getPatientId());
		/* ================================================== */
	}
	
	
	public void physicianChanged(Physician physician) {
		/* ====================================================== */
		this.currentPhysician = physician;
		loadData(null);
		/* ====================================================== */
	}
	
	
	/**
	 * if update is null, a full reload of the room from the DB will be triggered, 
	 * if update is not null, only the update will be applied to the room.
	 * 
	 * @param update
	 */
	public void loadData(QueueUpdateEvent update) {
		/* ================================================== */
		try {
		    if (update == null) // full reload
		    {
		    	WaitingroomManager manager = (WaitingroomManager) ManagerFactory.getRemote(WaitingroomManagerBean.class);
				List<Queue> queues = manager.getQueues4Today4Physician(currentPhysician.getId());
		    	wModel.setData(queues);
		    } else if (update.getEntry() != null && update.getEntry().getPhysicianId() != null){
		    	try {
		    		if (currentPhysician.getId().equals(update.getEntry().getPhysicianId())) {
		    			wModel.updateModel(update);						    			    		
		    		}					
				} catch (Exception e) {
					logger.error("Error updating waitingroom Queue", e);
				}
		    }
		} catch (Exception e) {
			/* --------------------------------------------- */
	    	if (currentPhysician != null)
	    	    logger.warn("Error loading Data ", e);
		/* --------------------------------------------- */
		}
		/* ================================================== */
	}
	
	
	/**
	 * 
	 */
	public void showDialog() {
		/* ====================================================== */
		this.loadData(null);
		this.setTitle(Translatrix.getTranslationString("waitingroom") + " - " + this.currentPhysician.toString());
		
		this.setSize(500, 450);
		MainFrame.showDialogCentered(this);
		/* ====================================================== */
	}
	
	
	/**
	 * 
	 */
	private void initHeader() {
		/* ================================================== */
		this.headerPanel = new JPanel(new BorderLayout());
		headerPanel.setBackground(Color.WHITE);
		/* ------------------------------------------------------- */
		this.dateLabel = new JLabel();
		dateLabel.setIcon(WaitingroomModule.getMediumIcon(WaitingroomModule.WITH_APPOINTMENT));
		this.timeLabel = new JLabel();
		timeLabel.setIcon(WaitingroomModule.getMediumIcon(WaitingroomModule.WAITINGROOM_ICON));
		
		headerPanel.add(dateLabel, BorderLayout.WEST);
		headerPanel.add(timeLabel, BorderLayout.EAST);
		/* ------------------------------------------------------- */
		Date date = new Date();
		dateLabel.setText(dateFormater.format(date));
		timeLabel.setText(timeFormater.format(date));
		/* ------------------------------------------------------- */
		headerPanel.add(new JLabel(" "), BorderLayout.SOUTH);
//		headerPanel.add(new JLabel(" "), BorderLayout.NORTH);
		this.setHeaderComponent(headerPanel);
		/* ================================================== */
	}
	
	
	/**
	 * Creates a timer task that updates the clock in the header
	 */
	private void startTimeTimer() {
		/* ================================================== */
		try {
			clockTimer.cancel();
		} catch (Exception ex) {}
		
		this.clockTimer = new Timer();
		clockTimer.schedule(new TimerTask() {
								@Override
								public void run() {
									/* ====================================================== */
									Date date = new Date();
									dateLabel.setText(dateFormater.format(date));
									timeLabel.setText(timeFormater.format(date)+"  ");
									startTimeTimer();
									/* ====================================================== */
								}
							}, DateUtil.MILLIS_MINUTE);
		
		/* ================================================== */
	}
	
	private void stopTimeTimer() {
		/* ================================================== */
		try {
			clockTimer.cancel();
		} catch (Exception ex) {}
		/* ================================================== */
	}
}
