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

import java.awt.BorderLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Collection;

import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.xml.transform.TransformerException;

import lu.tudor.santec.gecamed.core.gui.GECAMedMessage;
import lu.tudor.santec.gecamed.core.gui.GECAMedMessageListener;
import lu.tudor.santec.gecamed.core.gui.MainFrame;
import lu.tudor.santec.gecamed.core.gui.RegistrationDesk;
import lu.tudor.santec.gecamed.core.gui.widgets.TIFFViewer;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.HospitalPrescriptionPage;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.Patient;
import lu.tudor.santec.gecamed.patient.ejb.entity.interfaces.HospitalisationElement;
import lu.tudor.santec.gecamed.patient.ejb.session.beans.HospitalisationBean;
import lu.tudor.santec.gecamed.patient.ejb.session.interfaces.HospitalisationBeanInterface;
import lu.tudor.santec.gecamed.patient.gui.PatientManagerModule;
import lu.tudor.santec.gecamed.patient.gui.PatientViewTab;
import lu.tudor.santec.gecamed.patient.gui.reports.RTFReportTranslator;
import lu.tudor.santec.gecamed.patient.gui.reports.ReportViewer;
import lu.tudor.santec.i18n.Translatrix;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

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



/**
 * JPanel to view the Hospitalisation History of a patient.
 * Used in the hospital environment only.
 * 
 *
 * @author Johannes Hermen johannes.hermen(at)tudor.lu
 *
 * @version
 * <br>$Log: PatientHospitalisationPanel.java,v $
 * <br>Revision 1.21  2013-12-27 18:09:24  donak
 * <br>Cleanup of imports
 * <br>
 * <br>Revision 1.20  2013-07-15 06:18:35  ferring
 * <br>logging changed
 * <br>
 * <br>Revision 1.19  2008-09-25 09:43:08  heinemann
 * <br>fixed copyrights
 * <br>
 * <br>Revision 1.18  2008-03-12 10:30:06  hermen
 * <br>changed PatientViewTab to abstract and added getName() method
 * <br>
 * <br>Revision 1.17  2008-01-24 09:39:18  hermen
 * <br>*** empty log message ***
 * <br>
 *
 */
public class PatientHospitalisationPanel extends PatientViewTab implements GECAMedMessageListener
{
    //~ Static fields/initializers =============================================

	public static final String NAME 		 = "HOSP_PANEL";
	
	/**
	 * Message to open a passage from the Hospitalisation View (newValue will be the passage id)
	 */
	public static final String PASSAGE_OPEN = "PASSAGE_OPEN"; 
	
	/**
	 * Message to say that a passage verified has been changed in the Hospitalisation View (newValue will be the passage id)
	 */
	public static final String PASSAGE_VERIFIED_CHANGED = "PASSAGE_VERIFIED_CHANGED"; 

	/**
	 * Message to say that a passage rx has been changed in the Hospitalisation View (newValue will be the passage id)
	 */
	public static final String PASSAGE_RX_CHANGED = "PASSAGE_RX_CHANGED";
	
	/** the logger Object for this class */
	private static Logger logger = Logger.getLogger(PatientHospitalisationPanel.class.getName());
    private static final long serialVersionUID = 1L;
    private static final String LINESPACE = "1dlu";
  
    //~ Instance fields ========================================================

    private Patient currentPatient;
	private JPanel tablePanel;
	private JTable table;
	private HospitalisationTableModel hospitalisationTableModel;
	private RTFReportTranslator reportTranslator;
	private ReportViewer viewer;
	private HospitalisationBeanInterface hospManager;
	private TIFFViewer prescriptionViewer;
	

    //~ Constructors ===========================================================
    /**
     * builds a new PatientEditPanel to show/edit Patient Data
     * @param patientManagerModule 
     *
     * @param mainFrame a reference to the mainFrame of the Program to obtain all child-objects from
     */
    public PatientHospitalisationPanel() 
    {
    	this.setOpaque(false);
    	this.setTitle(Translatrix.getTranslationString("Hosp"));
    	this.setIcon(PatientManagerModule.getIcon(PatientManagerModule.HOSPITALISATION));
    	
    	this.prescriptionViewer = new TIFFViewer(MainFrame.getInstance(), "Prescription");
    	
    	this.viewer = new ReportViewer(MainFrame.getInstance());
    	this.reportTranslator = new RTFReportTranslator();
		try {
			this.reportTranslator.setXSLTemplate(RTFReportTranslator.XSL_FILE_STREAM);
		} catch (Exception e) {
			logger.log(Level.WARN, "initializing report translator failed", e);
		}
		
 		hospManager = (HospitalisationBeanInterface) ManagerFactory.getRemote(HospitalisationBean.class);
    	
 		// add listener for patient updates
 		RegistrationDesk.addGECAMedMessageListener(this);
 		
        // build the Panel
        this.buildPanel();
    }
    
	@Override
	public String getName() {
		return NAME;
	}

    //~ Methods ================================================================
    /**
     * returns the actual shown Patient
     *
     * @return the actual shown Patient
     */
    public Patient getPatient() {
        return this.currentPatient;
    }
    
    
	/* (non-Javadoc)
	 * @see lu.tudor.santec.gecamed.core.gui.GECAMedTab#enableTab()
	 */
	@Override
	public void enableTab() {
		/* ============================================= */
		super.enableTab();
		/* ============================================= */
	}
   

    /**
	 * update all shown values
	 */
    public void setPatient(Patient patient) {
    	long start = System.currentTimeMillis();
    	/* ------------------------------------------------------ */  	
    	this.hospitalisationTableModel.setPatient(patient);
    	/* ------------------------------------------------------ */
        this.setModified(false);
        logger.info("loading HOSPITALISATION Data for " + patient.toString() + " took: "+ (System.currentTimeMillis()-start) + "ms");
        
    }

    /**
     * adds the components to the panel
     */
    private void buildPanel() {
        initComponents();

        JPanel jp = new JPanel();
        
        // build the Layoute);
        FormLayout layout = new FormLayout("fill:pref:grow",  
                LINESPACE + ", fill:pref:grow, " + LINESPACE); 
        jp.setLayout(layout);
        CellConstraints cc = new CellConstraints();
        
        // add Panels
        jp.setOpaque(false);
               
        this.tablePanel = new JPanel(new BorderLayout());
        this.tablePanel.setOpaque(false);
        JScrollPane pane = new JScrollPane(this.table);
        pane.setOpaque(false);
        pane.getViewport().setOpaque(false);
        this.tablePanel.add(pane, BorderLayout.CENTER);
        jp.add(this.tablePanel, cc.xy(1,2));
        
        
        this.setLayout(new BorderLayout());
        this.add(jp, BorderLayout.CENTER);
        
        
    }

    /**
     * initialises the Components
     */
    private void initComponents()
    {
    	this.hospitalisationTableModel = new HospitalisationTableModel();
    	this.table = new JTable(hospitalisationTableModel);
    	
		table.getColumnModel().getColumn(0).setMaxWidth(70);
		table.getColumnModel().getColumn(0).setMinWidth(70);
		table.getColumnModel().getColumn(1).setMaxWidth(60);
		table.getColumnModel().getColumn(1).setMinWidth(60);
		table.getColumnModel().getColumn(2).setMaxWidth(30);
		table.getColumnModel().getColumn(3).setMaxWidth(30);
		
		HospitalisationTableRenderer renderer = new HospitalisationTableRenderer(hospitalisationTableModel);
		
		table.getColumnModel().getColumn(0).setCellRenderer(renderer);
		table.getColumnModel().getColumn(1).setCellRenderer(renderer);
		table.getColumnModel().getColumn(2).setCellRenderer(renderer);
		table.getColumnModel().getColumn(3).setCellRenderer(renderer);
		table.getColumnModel().getColumn(4).setCellRenderer(renderer);
		
		table.setShowGrid(false);
		table.setShowVerticalLines(true);
		
		
		table.addMouseListener(
				new MouseAdapter() {

					public void mouseClicked(MouseEvent e) {
						/* ============================================= */
						// get the current row
						int row = table.rowAtPoint(e.getPoint());
						int col = table.columnAtPoint(e.getPoint());
						final HospitalisationElement he = hospitalisationTableModel.getHospitalisationElement(row);

						if (he.getType() == HospitalisationElement.PASSAGE) {
							
							if (col == 2) {
								try {
									boolean verifiedState = !he.isVerified();
									hospManager.setPassageVerified(he.getId(), verifiedState);
									he.setVerified(verifiedState);
									hospitalisationTableModel.fireTableRowsUpdated(row, row);
									MainFrame.fireGECAMedMessage(new GECAMedMessage(PatientManagerModule.getInstance(), PASSAGE_VERIFIED_CHANGED, null, he.getId()));
								} catch (Exception e2) {
									logger.log(Level.WARN, "setting passage verified failed", e2);
								}
							} if (col == 3) {
								try {
									boolean rxState = !he.isRx();
									hospManager.setPassageRx(he.getId(), rxState);
									he.setRx(rxState);
									hospitalisationTableModel.fireTableRowsUpdated(row, row);
									MainFrame.fireGECAMedMessage(new GECAMedMessage(PatientManagerModule.getInstance(), PASSAGE_RX_CHANGED, null, he.getId()));
								} catch (Exception e2) {
									logger.log(Level.WARN, "setting passage RX failed", e2);
								}
							
							} else if (e.getClickCount() >=2){
								MainFrame.fireGECAMedMessage(new GECAMedMessage(PatientManagerModule.getInstance(), PASSAGE_OPEN, null, he.getId()));
							}
						} else if (he.getType() == HospitalisationElement.PRESCRIPTION && he.isVerified()) {
							if (e.getClickCount() >=2) {
								new Thread() {
									public void run() {
										try {
											MainFrame.getInstance().setWaitCursor(true);
											Collection<HospitalPrescriptionPage> pages = hospManager.getHospitalPrescriptionPages(he.getId());
											prescriptionViewer.showTIFFImage(pages);
										} catch (Exception ee) {
											logger.log(Level.WARN, "showing prescription failed", ee);
										}
										MainFrame.getInstance().setWaitCursor(false);
									}
								}.start();
							}
						} else if (he.getType() == HospitalisationElement.REPORT) {
							if (e.getClickCount() >=2) {
								new Thread() {
									public void run() {
										try {
											MainFrame.getInstance().setWaitCursor(true);
											byte[] reportData = hospManager.getHospitalReport(he.getId());
											showReport(reportData);
										} catch (Exception ee) {
											logger.log(Level.WARN, "showing report failed", ee);
										}
										MainFrame.getInstance().setWaitCursor(false);
									}
								}.start();
							}
						}
						/* ============================================= */
					}
				});
		
    	
    }
    
    
    private void showReport(byte[] b) {
		ByteArrayInputStream bin = new ByteArrayInputStream(b);
		ByteArrayOutputStream xmlOut = new ByteArrayOutputStream();
		reportTranslator.convert2XML(bin, xmlOut);
		ByteArrayOutputStream bous = new ByteArrayOutputStream();
		try {
			reportTranslator.convert2HTML(new ByteArrayInputStream(xmlOut.toByteArray()), bous);
		} catch (TransformerException e) {
			logger.log(Level.WARN, "transforming report failed", e);
		}
		viewer.showDocument(bous.toString());
	}
    
//  ---------------------------------------------------------------------------

    public void handleGECAMedMessage (GECAMedMessage p_Message)  {
    	Patient	l_Patient;
    	
    	if (p_Message.getModul() instanceof PatientManagerModule) {
    		if (p_Message.getMessage().equals(PatientManagerModule.PATIENT_UPDATED))
    			{
    				l_Patient = (Patient) p_Message.getNewValue();
    				setPatient(l_Patient);
    			}	
    	}
    }
    
}
