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

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Date;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;

import org.apache.log4j.Logger;

import lu.tudor.santec.gecamed.core.gui.GECAMedIconNames;
import lu.tudor.santec.gecamed.core.gui.GECAMedModule;
import lu.tudor.santec.gecamed.core.gui.MainFrame;
import lu.tudor.santec.gecamed.core.gui.utils.GradientFactory;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
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.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.PhysicianAgendaTableRenderer;
import lu.tudor.santec.gecamed.waitingroom.gui.widgets.WaitingroomTablePopup;
import lu.tudor.santec.i18n.Translatrix;

import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

/**
 * @author martin.heinemann@tudor.lu
 * 30.04.2008
 * 09:07:24
 *
 *
 * @version
 * <br>$Log: Waitingroom.java,v $
 * <br>Revision 1.12  2011-10-28 15:11:02  troth
 * <br>fix Ticket #900: Recurrence Appointments are not show in the Waitingroom.
 * <br>
 * <br>Revision 1.11  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.10  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.9  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.8  2009-10-12 09:18:00  hermen
 * <br>waitingroom mow scales to room anz and screensize
 * <br>
 * <br>Revision 1.7  2009-10-12 09:02:15  hermen
 * <br>-fixed rendering issue with comments in waitingroom
 * <br>-made rooms a tick smaller to fir 1280px screens
 * <br>
 * <br>Revision 1.6  2009-10-07 13:07:18  hermen
 * <br>added isVisit to waitingroom entry
 * <br>
 * <br>Revision 1.5  2009-10-06 14:16:13  hermen
 * <br>added isVisit to waitingroom entry
 * <br>
 * <br>Revision 1.4  2008-09-25 09:43:06  heinemann
 * <br>fixed copyrights
 * <br>
 * <br>Revision 1.3  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.2  2008-05-08 09:10:02  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.1  2008-05-07 14:40:35  heinemann
 * <br>*** empty log message ***
 * <br>
 *   
 */
public class Waitingroom extends JPanel implements MouseListener{

	/**
	 * static logger for this class
	 */
	private static Logger logger = Logger.getLogger(Waitingroom.class.getName());
	
	
	private static final long serialVersionUID = 1L;
	
	public static final int MODE_SECRETARY = 1;
	public static final int MODE_PHYSICIAN = 2;

	public static final boolean SHOW_ISVISIT = true;
	
	
	private Room room;
	private JLabel nameLabel;
	private WaitingroomTableModel tableModel;
	private JTable table;
	private JScrollPane scrollPaine;

	private int mode;

	private JPanel gradientPanel;

	private CellConstraints cc;
//
//	private AbstractAction editRoomAction;
//
//	private AbstractAction deleteRoomAction;

	private JPopupMenu roomPop;

	private WaitingroomTablePopup popup;

	private AbstractAction setDescAction;

	private static WaitingroomEditDialog editDialog;
	
	private static WaitingroomEditDescriptionDialog editDescDialog;

	/**
	 * @param room the room to display
	 * @param mode the mode, secretary or doctor
	 * 
	 * mode secretary: when the check box is unticked, the patient is not present
	 * mode physician: when the check box is unticked, the patient is untreated
	 */
	public Waitingroom(WaitingroomModule module, Room room, int mode, Date day) {
		/* ================================================== */
		this.room = room;
		this.mode = mode;
		
		
		initComponent();
		this.popup = new WaitingroomTablePopup(this.table, module);
		initRoomPopup();
		loadData(null, day);
		/* ================================================== */
	}



	/**
	 * 
	 */
	private void initComponent() {
		/* ====================================================== */
		this.setLayout(new FormLayout(
									// cols
									//"110dlu:grow",
									"60dlu:grow",
									//rows
									"fill:20dlu,5dlu,fill:200dlu:grow"));
		this.cc = new CellConstraints();
		/* ------------------------------------------------------- */
		this.nameLabel = new JLabel();
		setRoomTitle();
		nameLabel.setHorizontalAlignment(SwingConstants.CENTER);
		/* ------------------------------------------------------- */
//		Color color = Color.ORANGE;
//		if (room.getColor() != null)
//			color = new Color(room.getColor());
//		this.gradientPanel = GradientFactory.makeGradient(nameLabel, color, true);
//		this.add(this.gradientPanel, cc.xy(1, 1));
		refreshRoomData();
		/* ------------------------------------------------------- */
		initTable();
		/* ------------------------------------------------------- */
		this.add(this.scrollPaine, cc.xy(1, 3));
		/* ------------------------------------------------------- */
		// init the edit dialog
		/* ------------------------------------------------------- */
		if (editDialog == null)
			editDialog = new WaitingroomEditDialog();
		/* ------------------------------------------------------- */
		if (editDescDialog == null)
			editDescDialog = new WaitingroomEditDescriptionDialog();
		/* ------------------------------------------------------- */
		// init mouselistener
		/* ------------------------------------------------------- */
		this.nameLabel.addMouseListener(this);
		/* ====================================================== */
	}

	
	/**
	 * Reads data from room object and refreshes the gui components
	 */
	private void refreshRoomData() {
		/* ================================================== */
	    	setRoomTitle();
		try {
			this.remove(this.gradientPanel);
		} catch (Exception e) {}
		/* ------------------------------------------------------- */
		Color color = Color.ORANGE;
		if (room.getColor() != null)
			color = new Color(room.getColor());
		/* ------------------------------------------------------- */
		this.gradientPanel = GradientFactory.makeGradient(nameLabel, color, true);
		this.add(this.gradientPanel, cc.xy(1, 1));
		/* ================================================== */
	}
	

	private void setRoomTitle() {
	    	String roomTitle = room.getName();
	    	if (room.getDescription() != null && room.getDescription().length() > 0) {
	    	    roomTitle += " [" + room.getDescription() + "]";
	    	}
		nameLabel.setText(roomTitle);
	}



	/**
	 * Init the JTable
	 */
	private void initTable() {
		/* ====================================================== */
		this.tableModel = new WaitingroomTableModel(this.mode, SHOW_ISVISIT);
		this.table = new JTable(tableModel);
		
		this.scrollPaine = new JScrollPane(table);
		scrollPaine.getViewport().setBackground(Color.WHITE);
		/* ------------------------------------------------------- */
		
		/* ------------------------------------------------------- */
		PhysicianAgendaTableRenderer renderer = new PhysicianAgendaTableRenderer(this.mode, this.tableModel);
		table.setDefaultRenderer(Object.class, renderer);
		table.setShowHorizontalLines(false);
		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		/* ------------------------------------------------------- */
		table.getTableHeader().setReorderingAllowed(false);
		
		table.getColumnModel().getColumn(0).setMinWidth(52);
		table.getColumnModel().getColumn(0).setMaxWidth(52);
		
		table.getColumnModel().getColumn(2).setCellRenderer(renderer);
		table.getColumnModel().getColumn(2).setMinWidth(20);
		table.getColumnModel().getColumn(2).setMaxWidth(20);
		
		if (SHOW_ISVISIT) {
		    table.getColumnModel().getColumn(3).setCellRenderer(renderer);
		    table.getColumnModel().getColumn(3).setMinWidth(20);
		    table.getColumnModel().getColumn(3).setMaxWidth(20);		    
		}
		
		/* ------------------------------------------------------- */
		table.setTableHeader(null);
		table.setRowHeight(20);
		/* ------------------------------------------------------- */
		
		initTableListener();
		/* ====================================================== */
	}
	
	/**
	 * 
	 */
	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
					/* ------------------------------------------------------- */
					tableModel.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) {
					/* ------------------------------------------------------- */
					int row = table.rowAtPoint(e.getPoint());
					int col = table.columnAtPoint(e.getPoint());
					// get the value for that cell
					Object obj = tableModel.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());
					/* ------------------------------------------------------- */
				}
				/* ====================================================== */
			}
			
			
			
			
		});
		/* ================================================== */
	}
	
		
	/**
	 * Popup for rightclick on header
	 */
	private void initRoomPopup() {
		/* ================================================== */
		this.roomPop = new JPopupMenu();
		
		this.setDescAction = new AbstractAction(
			Translatrix.getTranslationString("waitingroom.setDesc"), 
			GECAMedModule.getMediumIcon(GECAMedIconNames.EDIT)) {

				private static final long serialVersionUID = 1L;

				public void actionPerformed(ActionEvent e) {
					/* ====================================================== */
				    	showSetDescDialog();
					/* ====================================================== */
				}
		};
		
		
		this.roomPop.add(this.setDescAction);
	}
	
	
	/**
	 * Marks the selected patient as treated and opens the file
	 */
	public void openSelected() {
		/* ================================================== */
		int row = table.getSelectedRow();
//		tableModel.setTreated(row);
//		/* ------------------------------------------------------- */
//		this.setVisible(false);
		Queue q = tableModel.getQueue(row);
		PatientManagerModule.getInstance().loadPatient(q.getPatientId());
		/* ================================================== */
	}
	
	
	
	/**
	 * 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, Date day) {
		/* ================================================== */
		try {
		    if (update == null) // full reload
		    {
		    	WaitingroomManager manager = (WaitingroomManager) ManagerFactory.getRemote(WaitingroomManagerBean.class);
		    	List<Queue> queues = manager.getQueues4Day(room.getId(), day);
		    	tableModel.setData(queues);
		    } else {
		    	tableModel.updateModel(update);			
		    }
		} catch (Exception e) {
			logger.warn("Error loading Data ", e);
		}
		/* ================================================== */
	}
	
	/**
	 * Show the editDescription dialog and save the result
	 */
	private void showSetDescDialog() {
		/* ================================================== */
	    	editDescDialog.showDialog(room);
		if (editDescDialog.getRoom() != null) {
			saveRoom(editDescDialog.getRoom());
		}
		/* ================================================== */
	}
	
	/**
	 * @param room
	 */
	private void saveRoom(Room room) {
		try {
			WaitingroomManager manager = (WaitingroomManager) ManagerFactory.getRemote(WaitingroomManagerBean.class);
			logger.info("Saving Waitingroom " + room);
			this.room = manager.saveRoom(room, MainFrame.getClientId());
		} catch (Exception e) {
			logger.error("Error savong Waitingroom: " + room, e);
		}
	}

	public void mouseClicked(MouseEvent e) {}
	public void mouseEntered(MouseEvent e) {}
	public void mouseExited(MouseEvent e) {}
	
	
	public void mousePressed(MouseEvent e) {
		if (this.nameLabel.equals(e.getSource())) { 
				if (e.isPopupTrigger()) {
					this.roomPop.show(this, e.getX(), e.getY());
				} 
		}
	}

	public void mouseReleased(MouseEvent e) {
		if (e.isPopupTrigger()) {
			this.roomPop.show(this, e.getX(), e.getY());
		}
	}
	
	public Room getRoom() {
		return this.room;
	}
	
	public Queue getQueueById(Integer id) {
		return this.tableModel.getQueueByID(id);
	}
	
	
	public void editQueue(Queue q) {
		this.tableModel.editQueue(q);
	}
	
	
}
