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

import ij.plugin.DICOM;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;

import javax.swing.ImageIcon;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import lu.tudor.santec.gecamed.cara.ejb.entity.beans.CaraImage;
import lu.tudor.santec.gecamed.cara.ejb.entity.beans.MedicalInfo;
import lu.tudor.santec.gecamed.cara.ejb.entity.beans.Study;
import lu.tudor.santec.gecamed.cara.ejb.session.beans.CaraManagerBean;
import lu.tudor.santec.gecamed.cara.ejb.session.interfaces.CaraManagerInterface;
import lu.tudor.santec.gecamed.core.gui.GECAMedAction;
import lu.tudor.santec.gecamed.core.gui.GECAMedFonts;
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.utils.GECAMedTitledBorder;
import lu.tudor.santec.gecamed.core.gui.utils.LineColorCellRenderer;
import lu.tudor.santec.gecamed.core.gui.utils.TableSorter;
import lu.tudor.santec.gecamed.core.gui.widgets.NamedComponentVariable;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.Patient;
import lu.tudor.santec.gecamed.patient.gui.PatientManagerModule;
import lu.tudor.santec.gecamed.patient.gui.PatientViewTab;
import lu.tudor.santec.i18n.Translatrix;

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


/**
 * @author Johannes Hermen
 */
public class PatientCaraPanel extends PatientViewTab 
{
    //~ Static fields/initializers =============================================

	public static final String NAME = "CARA_PANEL";
	
	public static final String ICON_CARA = "cara.png";
	public static final String ICON_DICOM = "dicom.png";
	public static final String ICON_DICOM_EMPTY = "dicom_empty.png";
	public static final String ICON_TEXT = "text.png";
	public static final String ICON_STUDY_DONE = "done.png";
	public static final String ICON_STUDY_PLANED = "planned.png";

    private static final long serialVersionUID = 1L;
    private static final String LINESPACE = "1dlu"; 
	
    //~ Instance fields ========================================================

    private Patient currentPatient;
	private JPanel generalPanel;
	private JPanel tablePanel;
	private JTable table;
	private JPanel detailsPanel;
	private JEditorPane allergyBox;
	private JEditorPane drugBox;
	private JEditorPane implantsBox;
	private JScrollPane allergyScroller;
	private JScrollPane drugScroller;
	private JScrollPane implantsScroller;
	private CaraTableModel caraTableModel;
	private CaraManagerInterface manager;
	private DetailsPanel details;
	private TableSorter tableSorter;
	private DicomImageDialog dicomFileDialog;
	private CaraReportViewer caraReportViewer;
	protected boolean notRunning = true;
	private Patient patient;
	protected boolean isRunning;
	private GECAMedAction reload;

    //~ 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 PatientCaraPanel()
    {
    	
    	Translatrix.addBundle("lu.tudor.santec.gecamed.cara.gui.resources.WidgetResources");
    	
    	dicomFileDialog = new DicomImageDialog(MainFrame.getInstance());
    	caraReportViewer = new CaraReportViewer();
    	
 		manager = (CaraManagerInterface) ManagerFactory.getRemote(CaraManagerBean.class);
    	
    	this.setOpaque(false);
    	
    	this.setTitle(Translatrix.getTranslationString("cara.cara"));
    	this.setIcon(getIcon(ICON_CARA));
        // build the Panel
        this.buildPanel();
        
        reload = getActionReload();
        reload.add();
        
        reloadCara();
    }

    //~ 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();
		/* ============================================= */
	}
   
	
	public void setPatient(Patient patient) {
		setPatient(patient, true);
	}

    /**
	 * update all shown values
	 */
    public void setPatient(Patient patient, boolean force) {
//    	long start = System.currentTimeMillis();
    	/* ------------------------------------------------------ */
    	this.patient = patient;
    	this.caraTableModel.setPatient(patient, force);
        try {
			MedicalInfo mi = manager.getMedicalInfo(patient.getId());
			this.allergyBox.setText(mi.getAllergies());
			this.drugBox.setText(mi.getDrugContraindictions());
			this.implantsBox.setText(mi.getImplants());
		} catch (Exception e) {
			this.allergyBox.setText("");
			this.drugBox.setText("");
			this.implantsBox.setText("");
//			logger.info("No CARA data for patient " + patient.toShortString() + " found!");
		}
    	/* ------------------------------------------------------ */
    	this.setModified(false);
//        logger.info("loading Cara MedicalInfo for " + patient.toString() + " took: "+ (System.currentTimeMillis()-start) + "ms");
        
    }

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

//        JPanel jp = new JPanel();
//        jp.setBorder(new GECAMedTitledBorder(Translatrix.getTranslationString("cara.cara")));
        this.setBorder(new GECAMedTitledBorder(Translatrix.getTranslationString("cara.cara")));
        
        // build the Layoute);
        FormLayout layout = new FormLayout("fill:50dlu:grow",  
                "fill:40dlu, " + LINESPACE + ", fill:60dlu:grow, " + LINESPACE + ", fill:pref"); 
//        jp.setLayout(layout);
        this.setLayout(layout);
        CellConstraints cc = new CellConstraints();
        
        // add Panels
//        jp.setOpaque(false);
        this.setOpaque(false);
        
        this.generalPanel = new JPanel(new GridLayout(1,0));
        this.generalPanel.setOpaque(false);
        this.generalPanel.add(new NamedComponentVariable(Translatrix.getTranslationString("cara.allergies"),
				allergyScroller, null));
        this.generalPanel.add(new NamedComponentVariable(Translatrix.getTranslationString("cara.drugscontraindictions"),
				drugScroller, null));
        this.generalPanel.add(new NamedComponentVariable(Translatrix.getTranslationString("cara.implants"),
				implantsScroller, null));
//        jp.add(this.generalPanel, cc.xy(1,1));
        this.add(this.generalPanel, cc.xy(1,1));
        
        this.tablePanel = new JPanel(new BorderLayout());
        this.tablePanel.setOpaque(false);
        this.tablePanel.setBorder(new GECAMedTitledBorder(Translatrix.getTranslationString("cara.studies")));
        JScrollPane pane = new JScrollPane(this.table);
        pane.setBackground(Color.WHITE);
//        pane.setOpaque(false);
        pane.getViewport().setOpaque(false);
        this.tablePanel.add(pane, BorderLayout.CENTER);
//        jp.add(this.tablePanel, cc.xy(1,3));
        this.add(this.tablePanel, cc.xy(1,3));
        
        this.detailsPanel = new JPanel(new GridLayout());
        this.detailsPanel.setOpaque(false);
        this.detailsPanel.setBorder(new GECAMedTitledBorder(Translatrix.getTranslationString("cara.details")));
//        JScrollPane jsp = new JScrollPane(details);
//        jsp.setOpaque(false);
//        jsp.getViewport().setOpaque(false);
        this.detailsPanel.add(details);
//        jp.add(this.detailsPanel, cc.xy(1,5));
        this.add(this.detailsPanel, cc.xy(1,5));
        
//        this.setLayout(new BorderLayout());
//        this.add(jp, BorderLayout.CENTER);
       
    }

    /**
     * initialises the Components
     */
    private void initComponents()
    {
    	
    	this.caraTableModel = new CaraTableModel();
    	
    	this.tableSorter = new TableSorter(this.caraTableModel);
    	this.table = new JTable(this.tableSorter);
    	this.tableSorter.setTableHeader(this.table.getTableHeader());
    	
    	this.table.setOpaque(false);
    	this.table.setPreferredSize(new Dimension(200,200));
    	this.table.getTableHeader().setReorderingAllowed(false);

    	LineColorCellRenderer renderer = new LineColorCellRenderer();
    	
    	// Modality
		table.getColumnModel().getColumn(0).setMaxWidth(40);
		table.getColumnModel().getColumn(0).setMinWidth(40);
		table.getColumnModel().getColumn(0).setCellRenderer(new StatusRenderer());

		// Date
		table.getColumnModel().getColumn(1).setMaxWidth(130);
		table.getColumnModel().getColumn(1).setMinWidth(130);
		table.getColumnModel().getColumn(1).setCellRenderer(renderer);
		
		// State
		table.getColumnModel().getColumn(2).setMaxWidth(60);
		table.getColumnModel().getColumn(2).setMinWidth(60);
		table.getColumnModel().getColumn(2).setCellRenderer(renderer);
		
		// Desc.
		table.getColumnModel().getColumn(3).setCellRenderer(renderer);
		
		// Radiologist
		table.getColumnModel().getColumn(4).setMaxWidth(150);
		table.getColumnModel().getColumn(4).setMinWidth(150);
		table.getColumnModel().getColumn(4).setCellRenderer(renderer);
		
		// Hosp
		table.getColumnModel().getColumn(5).setMaxWidth(50);
		table.getColumnModel().getColumn(5).setMinWidth(50);
		table.getColumnModel().getColumn(5).setCellRenderer(renderer);
		
		// Images
		table.getColumnModel().getColumn(6).setMaxWidth(30);
		table.getColumnModel().getColumn(6).setMinWidth(30);
		table.getColumnModel().getColumn(6).setCellRenderer(new HasDicomRenderer());
		
		// TXT
		table.getColumnModel().getColumn(7).setMaxWidth(30);
		table.getColumnModel().getColumn(7).setMinWidth(30);
		table.getColumnModel().getColumn(7).setCellRenderer(new HasTextRenderer());
    	
		
		table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
			public void valueChanged(ListSelectionEvent e) {
				if (! e.getValueIsAdjusting()) {
					table.scrollRectToVisible(table.getCellRect(table.getSelectedRow(),0,true));
					Study study = caraTableModel.getStudy(
							tableSorter.modelIndex(table.getSelectedRow()));
					details.setStudy(study);
				}
			}
		});
		
		table.addMouseListener(
				new MouseAdapter() {

					public void mouseClicked(MouseEvent e) {
						/* ============================================= */
						// get the current row
						int row = tableSorter.modelIndex(table.rowAtPoint(e.getPoint()));
						int col = table.columnAtPoint(e.getPoint());
						
						final Study study = caraTableModel.getStudy(row);
						if (col == 6 && study.getDicomIDs() != null && e.getClickCount()>=2) {
							openImage(study.getDicomIDs());
						} else if (notRunning && col == 7 && study.getReport() != null && e.getClickCount()>=2) {
							
							new Thread() {
								public void run() {
									try {
										notRunning = false;
										MainFrame.getInstance().setWaitCursor(true);
										caraReportViewer.showDocument(study.getReport());
									} catch (Exception e1) {
										e1.printStackTrace();
									}
									MainFrame.getInstance().setWaitCursor(false);
									notRunning = true;
								}
							}.start();
						}
						
						/* ============================================= */
					}
				});
		
		
		allergyBox = createTextBox();
		allergyScroller = new JScrollPane(allergyBox);
		allergyScroller.setOpaque(false);
		allergyScroller.getViewport().setOpaque(false);
		
		drugBox = createTextBox();
		drugScroller = new JScrollPane(drugBox);
		drugScroller.setOpaque(false);
		drugScroller.getViewport().setOpaque(false);
		
		implantsBox = createTextBox();
		implantsScroller = new JScrollPane(implantsBox);
		implantsScroller.setOpaque(false);
		implantsScroller.getViewport().setOpaque(false);
		
		
        details = new DetailsPanel(this);
		
		
		
    }

	public boolean isFilledOK() {
		boolean ok = true;
		return ok;
	}

	
	private JEditorPane createTextBox() {
		JEditorPane pane = new JEditorPane();
		pane.setFont(GECAMedFonts.TEXTFIELD_FONT);
		pane.setForeground(Color.RED);
		return pane;
	}
	
	public void openImage(final String dicomIDs) {
		if (!notRunning)
			return;

		new Thread() {
			public void run() {
				try {
					notRunning = false;
					long start = System.currentTimeMillis();
					MainFrame.getInstance().setWaitCursor(true);
					CaraImage im = manager.getImage(dicomIDs);
					if (im == null) {
						System.out.println("ERROR getting Image for ID: "
								+ dicomIDs);
					} else {
						BufferedInputStream bIn = new BufferedInputStream(
								new ByteArrayInputStream(im.getData()));
						im = null;
						DICOM dic = new DICOM(bIn);
						dic.run("test");
						dicomFileDialog.showImage(dic);
						System.out.println("getting Image for ID: " + dicomIDs
								+ " took "
								+ (System.currentTimeMillis() - start));
					}
				} catch (Exception e1) {
					e1.printStackTrace();
				}
				MainFrame.getInstance().setWaitCursor(false);
				notRunning = true;
			}
		}.start();
	}
	
	private GECAMedAction getActionReload()
    {
    	GECAMedAction a =  new GECAMedAction(PatientManagerModule.getInstance(), "cara.reload", GECAMedModule.getIcon(GECAMedModule.RELOAD),KeyEvent.VK_R, true, true, false) {

			private static final long serialVersionUID = 1L;

				public void actionPerformed(ActionEvent e)
                {
					int row = table.getSelectedRow();
					setPatient(patient, true);
					try {
						if (table.getSelectedRow() != row)
							table.setRowSelectionInterval(row, row);
					} catch (Exception ee) {
					}
                }
            };
            return a;
    }
	
	
	public static ImageIcon getIcon(String p_IconName)
	{
	    return IconFetcher.getIcon(PatientCaraPanel.class, p_IconName);
	}
	
	
	private void reloadCara() {
		new Thread() {
			public void run() {
				System.out.println("isrunning " +isRunning );
				if (isRunning) 
					return;
				isRunning = true;
				while (isRunning) {
					int row = table.getSelectedRow();
					if (caraTableModel.setPatient(patient, false)) {
						try {
							if (table.getSelectedRow() != row)
								table.setRowSelectionInterval(row, row);
						} catch (Exception ee) {
						}
					}
					try {
						Thread.sleep(4000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}.start();
	}
	
	class HasDicomRenderer extends LineColorCellRenderer 
	{ 
		private static final long serialVersionUID = 1L;
		private final ImageIcon ICON_DICOM = PatientCaraPanel.getIcon(PatientCaraPanel.ICON_DICOM);
		private final ImageIcon ICON_DICOM_EMPTY = PatientCaraPanel.getIcon(PatientCaraPanel.ICON_DICOM_EMPTY);
		
		public HasDicomRenderer() {
			setHorizontalAlignment(JLabel.CENTER);
		}
		
		public void setValue( Object value ) 
		  { 
		    if ( CaraTableModel.DICOM_OK.equals(value)) { 
		    	setIcon(ICON_DICOM);
//		    } else  if ( CaraTableModel.DICOM_NOT_ARRIVED.equals(value)) { 
//		    	setIcon(ICON_DICOM_EMPTY);
		    } else
		      setIcon(null); 
		  } 
	}
	
	class HasTextRenderer extends LineColorCellRenderer 
	{ 
		private static final long serialVersionUID = 1L;
		private final ImageIcon ICON_TEXT = PatientCaraPanel.getIcon(PatientCaraPanel.ICON_TEXT);

		public HasTextRenderer() {
			setHorizontalAlignment(JLabel.CENTER);
		}
		
		public void setValue( Object value ) 
		  { 
		    if ( (Boolean)value ) 
		    { 
		    	setIcon(ICON_TEXT);
		    } 
		    else 
		      setIcon(null); 
		  } 
	}
	
	
	class StatusRenderer extends LineColorCellRenderer 
	{ 
		private static final long serialVersionUID = 1L;
		private final ImageIcon ICON_PLANED = PatientCaraPanel.getIcon(PatientCaraPanel.ICON_STUDY_PLANED);
		private final ImageIcon ICON_DONE = PatientCaraPanel.getIcon(PatientCaraPanel.ICON_STUDY_DONE);
		
		public StatusRenderer() {
			setHorizontalAlignment(JLabel.CENTER);
		}
		
		public void setValue( Object value ) 
		  { 
			if (value== null) {
				setToolTipText(Translatrix.getTranslationString("cara.planed"));
				setIcon(ICON_PLANED);
			} else if (((String)value).toUpperCase().startsWith("F")) {
				setToolTipText(Translatrix.getTranslationString("cara.done"));
				setIcon(ICON_DONE);
			} else {
				setToolTipText(Translatrix.getTranslationString("cara.planed"));
				setIcon(ICON_PLANED);
			}
		  }
	}


	@Override
	public String getName() {
		return NAME;
	}
	
}
