package lu.tudor.santec.gecamed.esante.gui.tab;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JPopupMenu.Separator;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.ScrollPaneConstants;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import lu.tudor.santec.gecamed.core.gui.GECAMedColors;
import lu.tudor.santec.gecamed.core.gui.GECAMedIconNames;
import lu.tudor.santec.gecamed.core.gui.GECAMedModule;
import lu.tudor.santec.gecamed.core.gui.IconFetcher;
import lu.tudor.santec.gecamed.core.gui.utils.GECAMedGuiUtils;
import lu.tudor.santec.gecamed.core.gui.widgets.animatedicon.AnimatedIcon;
import lu.tudor.santec.gecamed.core.utils.GECAMedUtils;
import lu.tudor.santec.gecamed.esante.ejb.entity.beans.CdaDocument;
import lu.tudor.santec.gecamed.esante.ejb.entity.beans.Dsp;
import lu.tudor.santec.gecamed.esante.gui.IconNames;
import lu.tudor.santec.gecamed.esante.gui.utils.ESanteGuiUtils;
import lu.tudor.santec.gecamed.esante.gui.webservice.DspPrivileges;
import lu.tudor.santec.gecamed.esante.gui.webservice.Security;
import lu.tudor.santec.gecamed.esante.gui.worker.DocumentWorker;
import lu.tudor.santec.gecamed.esante.utils.ESanteUtils;
import lu.tudor.santec.gecamed.patient.gui.PatientManagerModule;
import lu.tudor.santec.i18n.Translatrix;

import org.apache.log4j.Logger;

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

/**
 * @author jens.ferring(at)tudor.lu
 * 
 * @version
 * <br>$Log: CdaDocumentListPanel.java,v $
 * <br>Revision 1.29  2014-02-19 09:58:37  ferring
 * <br>Disintegrate document icon set
 * <br>
 * <br>Revision 1.28  2014-02-07 14:12:22  ferring
 * <br>remove tool tips
 * <br>
 * <br>Revision 1.27  2014-02-06 17:47:43  ferring
 * <br>remove the tool tip on list and tree, if there is no document
 * <br>
 * <br>Revision 1.26  2014-02-06 14:26:59  ferring
 * <br>Tool tip and blocked icon added
 * <br>
 * <br>Revision 1.25  2014-02-05 07:05:27  ferring
 * <br>confidentiality icon added
 * <br>
 * <br>Revision 1.24  2014-02-04 10:08:34  ferring
 * <br>eSante ID management completed
 * <br>Only those documents will be shown, that are retrieved by the RSQ
 * <br>
 * <br>Revision 1.23  2014-01-30 17:05:44  ferring
 * <br>Presence password button added
 * <br>
 * <br>Revision 1.22  2014-01-23 15:02:11  ferring
 * <br>DSP last names changed
 * <br>
 * <br>Revision 1.21  2014-01-17 08:49:34  ferring
 * <br>DspPrivileges not stored in DSP anymore
 * <br>
 * <br>Revision 1.20  2014-01-10 13:17:17  ferring
 * <br>Mandate caching and DSP info renewing fixed
 * <br>
 * <br>Revision 1.19  2014-01-09 17:31:23  ferring
 * <br>Mandate will be renewed after presence password and EHR status is now visible
 * <br>
 * <br>Revision 1.18  2014-01-09 16:44:33  ferring
 * <br>Error handling for SAML assertions changed
 * <br>
 * <br>Revision 1.17  2014-01-09 14:30:27  ferring
 * <br>mandate not shown, if it can't be translated
 * <br>
 * <br>Revision 1.16  2014-01-09 10:27:51  ferring
 * <br>mandate not shown, if it can't be translated
 * <br>
 * <br>Revision 1.15  2014-01-06 12:34:28  ferring
 * <br>download site constants moved
 * <br>
 * <br>Revision 1.14  2013-12-19 12:36:08  ferring
 * <br>comment removed
 * <br>
 * <br>Revision 1.13  2013-12-17 16:49:51  ferring
 * <br>RSQ handling changed
 * <br>
 * <br>Revision 1.12  2013-12-05 12:27:19  ferring
 * <br>CDA  columns renamed
 * <br>Login data of user stored
 * <br>Checking if CDA doc exists, creating a new one
 * <br>
 * <br>Revision 1.11  2013-11-28 10:38:21  ferring
 * <br>GECAMedUtils split into utils and GUI utils classes
 * <br>
 * <br>Revision 1.10  2013-11-26 10:30:03  ferring
 * <br>translated
 * <br>
 * <br>Revision 1.9  2013-11-25 08:27:21  ferring
 * <br>Root expanding and notifying of JTree fixed
 * <br>
 * <br>Revision 1.8  2013-11-22 14:51:11  ferring
 * <br>Restructured CDA tree and list notification, in order not to use an EntityBean as model.
 * <br>Buttons added to delete the CDA file and remove the incident entry
 * <br>
 * <br>Revision 1.7  2013-11-21 12:24:00  ferring
 * <br>button tooltipps added
 * <br>
 * <br>Revision 1.6  2013-11-21 10:50:56  ferring
 * <br>tree added to root
 * <br>
 * <br>Revision 1.5  2013-11-21 09:48:54  ferring
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.4  2013-11-14 17:56:33  ferring
 * <br>check if document needs to be downloaded and better check if documents can be integrated
 * <br>
 * <br>Revision 1.3  2013-11-12 07:56:37  ferring
 * <br>TreeModel changed
 * <br>
 * <br>Revision 1.2  2013-11-11 11:46:32  ferring
 * <br>load documents from database before synchronising with eSante,
 * <br>expand all option added,
 * <br>Download documents option added
 * <br>and stop option removed
 * <br>
 * <br>Revision 1.1  2013-11-08 08:49:27  ferring
 * <br>ESanteDocumentListPanel refactored to CdaDocumentpanel
 * <br>
 * <br>Revision 1.17  2013-11-05 09:47:56  ferring
 * <br>ESantePatient changed to Dsp. The Dsp object will be stored in the database, if a patient is linked with eSanté.
 * <br>
 * <br>Revision 1.16  2013-10-28 16:54:12  ferring
 * <br>eSante and GECAMed patient compare dialog added and a lot of bug fixes
 * <br>
 * <br>Revision 1.15  2013-10-23 07:32:32  ferring
 * <br>icon names changed to constants
 * <br>
 * <br>Revision 1.14  2013-10-22 05:55:53  ferring
 * <br>loading gif added
 * <br>
 * <br>Revision 1.13  2013-10-21 08:21:01  ferring
 * <br>Selection and expanding changed
 * <br>
 * <br>Revision 1.12  2013-10-11 12:30:02  ferring
 * <br>Document tree rendering improved
 * <br>
 * <br>Revision 1.11  2013-10-11 07:50:23  ferring
 * <br>Switching document view changed
 * <br>and rendering improved
 * <br>
 * <br>Revision 1.10  2013-10-10 13:32:09  ferring
 * <br>notify document tree for changes
 * <br>
 * <br>Revision 1.9  2013-10-09 13:36:36  ferring
 * <br>eSanté icon changed and tree view initialised
 * <br>
 * <br>Revision 1.8  2013-10-08 08:54:14  ferring
 * <br>class name refactoring and tree view implementation (first steps)
 * <br>
 * <br>Revision 1.7  2013-10-01 13:14:57  ferring
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.6  2013-09-30 10:56:34  ferring
 * <br>eSante integration in GECAMed and synchronise funktion added
 * <br>
 * <br>Revision 1.5  2013-09-13 14:18:56  ferring
 * <br>eSante bugs fixed and database implementation started
 * <br>
 * <br>Revision 1.4  2013-09-10 06:16:28  ferring
 * <br>eSante improvements
 * <br>
 * <br>Revision 1.3  2013-07-15 06:18:37  ferring
 * <br>logging changed
 * <br>
 * <br>Revision 1.2  2013-07-03 13:06:22  ferring
 * <br>eSante module handling changed
 * <br>
 * <br>Revision 1.1  2013-06-26 11:19:37  ferring
 * <br>migrating eSante view from dialogs to eSante patient tab
 * <br>
 */

public class CdaDocumentListPanel extends JPanel implements MouseListener, 
		ListSelectionListener, ListCellRenderer, TreeSelectionListener, TreeCellRenderer
{
	/* ======================================== */
	// CONSTANTS
	/* ======================================== */
	
	public static final int	SHOW_LIST	= 0;
	public static final int	SHOW_TREE	= 1;
	
	private static final long		serialVersionUID	= 334378478507779757L;
	
	private static final Color		BUSY_COLOR			= new Color(245, 240, 186, 125);
	
	private static final Color		ENQUEUED_COLOR		= BUSY_COLOR; // new Color(247, 247, 255, 125);
	
	
	
	/* ======================================== */
	// MEMBERS
	/* ======================================== */
	
	/** the logger Object for this class */
	private static Logger					logger			= Logger.getLogger(CdaDocumentListPanel.class.getName());
	
	private static CellConstraints			cc;
	
	
	private AnimatedIcon				loadingIcon		= new AnimatedIcon(new ImageIcon(
			IconNames.class.getResource("resources/icons/" +  IconNames.LOADING_ANIMATED)));
	
	private JPanel			infoPanel;
	
	private JLabel			dspInfoLabel;
	
	private JLabel			statusInfoLabel;
	
	private ImageIcon		genderIcon;
	
	private JList			documentList;
	
//	private CdaListModel	documentListModel;
	private CdaHandler		cdaHandler;
	
	private JTree			documentTree;
	
	private CdaTreeRoot		documentTreeRoot;
	
	private JScrollPane		documentScroller;
	
	private JMenuItem		expandAllAction;
	
	private Separator		expandAllSeparator;
	
	private JMenuItem		integrateAction;
	
	private JMenuItem		openAction;
	
	private JMenuItem		downloadAction;
	
	private JMenuItem		disintegrateAction;
	
//	private JMenuItem		deleteFileAction;
	
	private JPopupMenu		popup;
	
	private JLabel			busyIcon;
	
	private	JLabel			confidentialIcon;
	
	private JLabel			blockedIcon;
	
	private JPanel			cellPanel;
	
	private JLabel			cell;
	
	private JLabel			structureCell;
	
	private int				activatedView;
	
	private JButton			switchViewButton;
	
	private List<CdaDocumentListListener>	listeners	= new LinkedList<CdaDocumentListListener>();
	
	
	
	/* ======================================== */
	// CONSTRUCTORS
	/* ======================================== */
	
	public CdaDocumentListPanel (JButton switchViewButton)
	{
		this.switchViewButton = switchViewButton;
		initComponents();
	}
	
	
	public CdaDocumentListPanel (int viewOption)
	{
		this(new JButton());
		switchView(viewOption);
	}
	
	
	
	/* ======================================== */
	// CLASS BODY
	/* ======================================== */
	
	public void setData (Dsp dsp)
	{
		cdaHandler.setDsp(dsp);
		
		if (dsp == null)
		{
			dspInfoLabel.setText(null);
			genderIcon = null;
			statusInfoLabel.setText(null);
		}
		else
		{
			// show the data
			printDspInfo(dsp);
		}
	}
	
	
	public void clearPanel ()
	{
		documentTreeRoot.clear();
		repaint();
	}
	
	
	public void addDocumentListener (CdaDocumentListListener l)
	{
		listeners.add(l);
	}
	
	
	public boolean removeDocumentListener (CdaDocumentListListener l)
	{
		return listeners.remove(l);
	}
	
	
	public List<CdaDocument> getSeletedDocuments ()
	{
		ArrayList<CdaDocument> documents;
		
		if (activatedView == SHOW_LIST)
		{
			// get the documents selected in the LIST
			Object[] docs = documentList.getSelectedValues();
			
			documents = new ArrayList<CdaDocument>(docs.length);
			for (Object doc : docs)
			{
				if (doc == null)
					break;
				documents.add((CdaDocument) doc);
			}
		}
		else if (activatedView == SHOW_TREE)
		{
			// get the documents selected in the TREE
			TreePath[]	paths = documentTree.getSelectionPaths();
			CdaTreeNode	node;
			CdaDocument	document;
			
			if (paths == null)
				return new LinkedList<CdaDocument>();
			
			Set<CdaDocument> selection = new TreeSet<CdaDocument>();
			for (TreePath path : paths)
			{
				node		= (CdaTreeNode) path.getLastPathComponent();
				if (node.isLeaf())
				{
					document	= node.getDocument();
					selection.add(document);
				}
				else
				{
					selection.addAll(node.getDocuments());
				}
			}
			documents = new ArrayList<CdaDocument>(selection);
		}
		else
		{
			return null;
		}
		
		return documents;
	}
	
	
	public void switchView ()
	{
		switch (activatedView)
		{
			case SHOW_LIST:
				
				switchView(SHOW_TREE);
				break;
			
			case SHOW_TREE:
			default:
				
				switchView(SHOW_LIST);
				break;
		}
	}
	
	
	public void switchView (int viewOption)
	{
		if (activatedView == viewOption)
			return;
		
		activatedView = viewOption;
		
		switch (viewOption)
		{
			case CdaDocumentListPanel.SHOW_LIST:
				
				documentScroller.setViewportView(documentList);
				switchViewButton.setIcon(ESanteGuiUtils.getIcon(IconNames.SHOW_TREE, 32));
				switchViewButton.setToolTipText(Translatrix.getTranslationString("esante.CdaList.switchToTree"));
				break;
				
			case CdaDocumentListPanel.SHOW_TREE:
				
				documentScroller.setViewportView(documentTree);
				documentTree.validate();
				switchViewButton.setIcon(ESanteGuiUtils.getIcon(IconNames.SHOW_LIST, 32));
				switchViewButton.setToolTipText(Translatrix.getTranslationString("esante.CdaList.switchToList"));
				break;
		}
		
		switchViewButton.repaint();
		documentSelectionChanged();
		documentScroller.validate();
	}
	
	
	public CdaHandler getCdaHandler ()
	{
		return cdaHandler;
	}
	
	
	/* ---------------------------------------- */
	// MOUSE LISTENER METHODS
	/* ---------------------------------------- */
	
	public void mouseClicked (MouseEvent e)
	{
		if (e.getClickCount() >= 2)
		{
			if (activatedView == SHOW_TREE)
			{
				TreePath selection = documentTree.getSelectionPath();
				
				if (selection == null || !((CdaTreeNode)selection.getLastPathComponent()).isLeaf())
					return;
			}
			openSelectedDocuments();
		}
	}
	
	
	public void mousePressed (MouseEvent e)
	{
		if (e.isPopupTrigger())
			showPopup(e);
	}
	
	
	public void mouseReleased (MouseEvent e)
	{
		if (e.isPopupTrigger())
			showPopup(e);
	}
	
	
	public void mouseEntered (MouseEvent e) {}
	public void mouseExited (MouseEvent e) {}
	
	
	/* ---------------------------------------- */
	// LIST SELECTION LISTENER METHODS
	/* ---------------------------------------- */
	
	
	public void valueChanged (ListSelectionEvent e)
	{
		documentSelectionChanged();
	}
	
	
	/* ---------------------------------------- */
	// LIST CELL RENDERER METHOD
	/* ---------------------------------------- */
	
	public Component getListCellRendererComponent (JList list, 
			Object value, int index, boolean isSelected, boolean cellHasFocus)
	{
		if (list.getModel().getSize() == 0)
		{
			documentList.setToolTipText(null);
			documentTree.setToolTipText(null);
		}
		
		return render(list, (CdaDocument) value, isSelected, index);
	}
	
	
	/* ---------------------------------------- */
	// TREE CELL RENDERER METHOD 
	/* ---------------------------------------- */
	
	public Component getTreeCellRendererComponent (JTree tree, Object value, 
			boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus)
	{
		CdaTreeNode	node	= (CdaTreeNode) value;
		CdaDocument	doc		= node.getDocument();
		
		
		if (doc != null)
		{
			// let the render function render the document
			return render(tree, doc, selected, row);
		}
		else
		{
			documentList.setToolTipText(null);
			documentTree.setToolTipText(null);
			// render the node structure here
			if (node.getLevel() == CdaTreeNode.LEVEL_ROOT)
				structureCell.setText("Total Documents: "+node.getDocumentCount());
			else
				structureCell.setText(String.valueOf(node) + " (" + node.getDocumentCount() + ")");
			if (selected)
				structureCell.setBackground(GECAMedColors.c_ListSelectionBackground);
			else if (node.getLevel() == CdaTreeNode.LEVEL_CLASS)
				structureCell.setBackground(new Color(230, 230, 230));
			else 
				structureCell.setBackground(Color.WHITE);
			
			return structureCell;
		}
	}
	
	
	/* ---------------------------------------- */
	// TREE SELECTION LISTENER METHOD
	/* ---------------------------------------- */
	
	public void valueChanged (TreeSelectionEvent e)
	{
		documentSelectionChanged();
	}
	
	
	
	/* ======================================== */
	// HELP METHODS
	/* ======================================== */
	
	private void initComponents ()
	{
		cc			= new CellConstraints();
		
		initRenderComponents();
		
		// create the scroll pane to put the list and tree with CDA documents in
		documentScroller	= new JScrollPane();
		documentScroller.setOpaque(false);
		documentScroller.getViewport().setOpaque(false);
		documentScroller.getVerticalScrollBar().setUnitIncrement(16);
		documentScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		documentScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
		
		// create the list of CDA documents
		cdaHandler			= new CdaHandler();
		documentList		= new JList(new CdaListModel(cdaHandler));
		documentList.setCellRenderer(this);
		documentList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
		documentList.addListSelectionListener(this);
		documentList.addMouseListener(this);
		
		// create the tree of CDA documents
		documentTreeRoot	= new CdaTreeRoot();
		cdaHandler.addCdaListener(documentTreeRoot);
		documentTree		= new JTree((TreeModel)documentTreeRoot);
		documentTree.setCellRenderer(this);
		documentTree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
		documentTree.addTreeSelectionListener(this);
		documentTree.addMouseListener(this);
		documentTree.setRootVisible(true);
		documentTreeRoot.addTree(documentTree);
		
		// create the popup for the documents
		popup				= new JPopupMenu();
		popup.setBackground(GECAMedColors.c_GECAMedBackground);
		
		expandAllAction		= new JMenuItem(new AbstractAction(
				Translatrix.getTranslationString("esante.CdaList.actions.expandAll"), 
				ESanteGuiUtils.getIcon(IconNames.EXPAND_ALL, 18))
		{
			private static final long	serialVersionUID	= 1L;
			
			public void actionPerformed (ActionEvent e)
			{
				expandAllFromSelectedNode(e);
			}
		});
		expandAllAction.setOpaque(false);
		popup.add(expandAllAction);
		
		expandAllSeparator	= new Separator();
		popup.add(expandAllSeparator);
		
		openAction			= new JMenuItem(new AbstractAction(
				Translatrix.getTranslationString("esante.CdaList.actions.openDocument"),
				GECAMedModule.getSmallIcon(GECAMedIconNames.OPEN))
		{
			private static final long	serialVersionUID	= 1L;
			
			public void actionPerformed (ActionEvent e)
			{
				openSelectedDocuments();
			}
		});
		openAction.setOpaque(false);
		popup.add(openAction);
		
		downloadAction		= new JMenuItem(new AbstractAction(
				Translatrix.getTranslationString("esante.CdaList.actions.downloadDocument"),
				ESanteGuiUtils.getIcon(IconNames.DOWNLOAD, 18))
		{
			private static final long	serialVersionUID	= 1L;
			
			public void actionPerformed (ActionEvent e)
			{
				downloadSelectedDocuments();
			}
		});
		downloadAction.setOpaque(false);
		popup.add(downloadAction);
		
		integrateAction		= new JMenuItem(new AbstractAction(
				Translatrix.getTranslationString("esante.CdaList.actions.integrateDocument"),
				ESanteGuiUtils.getIcon(IconNames.INTEGRATE_DOC, IconFetcher.SMALLPIX))
		{
			private static final long	serialVersionUID	= 1L;
			
			public void actionPerformed (ActionEvent e)
			{
				integrateSelectedDocuments();
			}
		});
		integrateAction.setOpaque(false);
		popup.add(integrateAction);
		
		disintegrateAction	= new JMenuItem(new AbstractAction(
				Translatrix.getTranslationString("esante.CdaList.actions.disintegrateDocument"),
				ESanteGuiUtils.getIcon(IconNames.DISINTEGRATE_DOC, IconFetcher.SMALLPIX))
		{
			private static final long	serialVersionUID	= 1L;

			public void actionPerformed (ActionEvent e)
			{
				disintegrateSelectedDocuments();
			}
		});
		disintegrateAction.setOpaque(false);
		popup.add(disintegrateAction);
		
//		deleteFileAction	= new JMenuItem(new AbstractAction(
//				Translatrix.getTranslationString("esante.CdaList.actions.deleteDownloadedDocument"))
//		{
//			private static final long	serialVersionUID	= 1L;
//
//			public void actionPerformed (ActionEvent e)
//			{
//				deleteCdaFileOfSelectedDocuments();
//			}
//		});		
//		deleteFileAction.setOpaque(false);
//		popup.add(deleteFileAction);
		
		
		// define the layout
		setLayout(new FormLayout(
				// columns
				"0px, f:0px:g, 0px", 
				// rows
				"0px, f:p, 5px, f:0px:g, 0px"));
		setOpaque(false);
		
		// add the component(s)
		add(infoPanel,			cc.xy(2, 2));
		add(documentScroller,	cc.xy(2, 4));
	}
	
	
	private void initRenderComponents ()
	{
		// define the panel and labels for the renderer
		cellPanel	= new JPanel(new FormLayout("f:d:g,f:min(p;32px),f:min(p;32px),f:min(p;32px)", "p"));
		cellPanel.setOpaque(true);
		cellPanel.setBorder(BorderFactory.createEmptyBorder());
		cell		= new JLabel();
		cell.setBackground(BUSY_COLOR);
		cell.setOpaque(false);
		busyIcon	= new JLabel();
		busyIcon.setBackground(BUSY_COLOR);
		busyIcon.setOpaque(false);
		structureCell = new JLabel();
		structureCell.setOpaque(true);
		
		confidentialIcon	= new JLabel();
		confidentialIcon.setOpaque(false);
		
		blockedIcon	= new JLabel();
		blockedIcon.setOpaque(false);
		
		cellPanel.setOpaque(true);
		cellPanel.setBackground(cell.getBackground());
		cellPanel.add(cell, 			cc.xy(1, 1));
		cellPanel.add(confidentialIcon,	cc.xy(2, 1));
		cellPanel.add(busyIcon,			cc.xy(3, 1));
		cellPanel.add(blockedIcon,		cc.xy(4, 1));
		
		// create the panel to show information about process and DSP data
		infoPanel		= new JPanel(new BorderLayout());
		infoPanel.setOpaque(false);
		dspInfoLabel	= new JLabel();
		dspInfoLabel.setOpaque(false);
		infoPanel.add(dspInfoLabel, BorderLayout.CENTER);
		statusInfoLabel	= new JLabel();
		statusInfoLabel.setOpaque(false);
		statusInfoLabel.setForeground(Color.ORANGE);
		infoPanel.add(statusInfoLabel, BorderLayout.SOUTH);
	}
	
	
	private void expandAllFromSelectedNode (ActionEvent e)
	{
		((CdaTreeNode) documentTree.getSelectionPath().getLastPathComponent())
				.expand(documentTree, CdaTreeNode.LEVEL_DOCUMENT);
	}
	
	
	private JPanel render(JComponent source, CdaDocument document, boolean selected, int row)
	{
		if (document == null)
		{
			cell.setText("");
			cell.setIcon(null);
			cell.setBackground(ENQUEUED_COLOR);
			busyIcon.setIcon(null);
			confidentialIcon.setIcon(null);
			blockedIcon.setIcon(null);
		}
		else
		{
			// set the text of cell
			cell.setText(document.toHtml(false));
			
	//		cell.setEnabled(!document.isAvailable());
			
			// set the busy icon, if loading
			if (document.isBusy())
			{
				busyIcon.setOpaque(true);
				cell.setOpaque(true);
				cell.setBackground(BUSY_COLOR);
				busyIcon.setIcon(loadingIcon);
			}
			else if (document.isEnqueued())
			{
				busyIcon.setOpaque(false);
				cell.setOpaque(true);
				cell.setBackground(ENQUEUED_COLOR);
				busyIcon.setIcon(null);
			}
			else 
			{
				busyIcon.setOpaque(false);
				cell.setOpaque(false);
				busyIcon.setIcon(null);
			}
			
			if (CdaDocument.CONFIDENTIALITY_RESTRICTED.equals(document.getConfidentialityCode()))
				confidentialIcon.setIcon(ESanteGuiUtils.getIcon(IconNames.LOCK_RESTRICTED, 24));
			else if (CdaDocument.CONFIDENTIALITY_PRIVATE.equals(document.getConfidentialityCode()))
				confidentialIcon.setIcon(ESanteGuiUtils.getIcon(IconNames.LOCK_PRIVATE, 24));
	//		else if (CdaDocument.CONFIDENTIALITY_BLOCKED.equals(document.getConfidentialityCode()))
	//			confidentialIcon.setIcon(ESanteUtils.getIcon(IconNames.LOCK_BLOCKED, 24));
			else
				confidentialIcon.setIcon(null);
			
			source.setToolTipText(document.getToolTip());
			
			if (document.isBlocked())
				blockedIcon.setIcon(ESanteGuiUtils.getIcon(IconNames.PATIENT_BLOCKED, 24));
			else
				blockedIcon.setIcon(null);
			
			// set the status icon
			cell.setIcon(getDocumentIcon(document));
		}
		
		// define the background
		if (selected)
			cellPanel.setBackground(GECAMedColors.c_ListSelectionBackground);
		else if (row % 2 == 0)
			cellPanel.setBackground(GECAMedColors.c_EvenLineBackground);
		else 
			cellPanel.setBackground(GECAMedColors.c_OddLineBackground);
		
		return cellPanel;
	}
	
	
	/** 
	 * Get the icon for this document mainly depending on the document state
	 */
	private ImageIcon getDocumentIcon (CdaDocument document)
	{
		int			status	= document.getStatus();
		
		
		if (document.getOriginIncidentEntryId() != null)
			return ESanteGuiUtils.getIcon(IconNames.STATUS_UPLOADED, 32);
		
		switch (status)
		{
			case CdaDocument.STATUS_ERROR:
				return ESanteGuiUtils.getIcon(IconNames.STATUS_ERROR, 32);
				
			case CdaDocument.STATUS_NEW:
				return  ESanteGuiUtils.getIcon(IconNames.STATUS_NEW, 32);
				
			case CdaDocument.STATUS_UNREAD:
				return  ESanteGuiUtils.getIcon(IconNames.STATUS_UNREAD, 32);
				
			case CdaDocument.STATUS_UNREAD_AND_DOWNLOADED:
				return  ESanteGuiUtils.getIcon(IconNames.STATUS_UNREAD_AND_DOWNLOADED, 32);
				
			case CdaDocument.STATUS_UNREAD_AND_INTEGRATED:
				return  ESanteGuiUtils.getIcon(IconNames.STATUS_UNREAD_AND_INTEGRATED, 32);
				
			case CdaDocument.STATUS_READ:
				return  ESanteGuiUtils.getIcon(IconNames.STATUS_READ, 32);
				
			case CdaDocument.STATUS_READ_AND_DOWNLOADED:
				return  ESanteGuiUtils.getIcon(IconNames.STATUS_READ_AND_DOWNLOADED, 32);
				
			case CdaDocument.STATUS_READ_AND_INTEGRATED:
				return  ESanteGuiUtils.getIcon(IconNames.STATUS_READ_AND_INTEGRATED, 32);
				
			case CdaDocument.STATUS_UPLOADED:
				return  ESanteGuiUtils.getIcon(IconNames.STATUS_UPLOADED, 32);
		}
		return  ESanteGuiUtils.getESanteIcon(32);
	}
	
	
	private void showPopup (MouseEvent e)
	{
		Component invoker;
		String mediaType = null;
		
		if (!e.isPopupTrigger())
			return;
		
		if (activatedView == SHOW_LIST)
		{
			int index	= documentList.locationToIndex(e.getPoint());
			
			if (index < 0)
				return;
			
			if (GECAMedGuiUtils.isShortCutDown(e))
				documentList.addSelectionInterval(index, index);
			else
				documentList.setSelectedIndex(index);
			
			invoker	= documentList;
//			popup.show(documentList, e.getX(), e.getY());
		}
		else if (activatedView == SHOW_TREE) 
		{
			TreePath path = documentTree.getClosestPathForLocation(e.getX(), e.getY());
			
			if (path == null)
				return;
			
			if (GECAMedGuiUtils.isShortCutDown(e))
				documentTree.addSelectionPath(path);
			else
				documentTree.setSelectionPath(path);
			
			invoker = documentTree;
//			popup.show(documentTree, e.getX(), e.getY());
		}
		else
		{
			return;
		}
		
		if (activatedView == SHOW_TREE 
				&& !((CdaTreeNode)documentTree.getSelectionPath()
						.getLastPathComponent()).isLeaf())
		{
			expandAllAction.setVisible(true);
			expandAllSeparator.setVisible(true);
		}
		else
		{
			expandAllAction.setVisible(false);
			expandAllSeparator.setVisible(false);
		}
		
		List<CdaDocument> selectedDocuments = getSeletedDocuments();
		
		if (selectedDocuments == null || selectedDocuments.isEmpty()){
			return;
		}
		mediaType = "";
		// the effort to determine the media type only makes sense for a single document
		if(selectedDocuments.size()==1){
			mediaType = selectedDocuments.get(0).getMediaType();
		}
		// prevent batch download of multiple documents - legal requirement of the eHealth infrastructure in Luxembourg
		// Also, currently just documents of type pdf should be diplayed in Gecamed - even if Gecamed is capable to display virtually any type of document (system apps are used for display)
		integrateAction.setEnabled((selectedDocuments.size() == 1) && ESanteUtils.containsIntegratableDocument(selectedDocuments)&&("application/pdf".equals(mediaType.toLowerCase())));
		downloadAction.setEnabled(ESanteUtils.containsDownloadableDocument(selectedDocuments));
		disintegrateAction.setEnabled(ESanteUtils.containsDisintegratableDocument(selectedDocuments));
//		deleteFileAction.setEnabled(ESanteUtils.containsDeletableDocument(selectedDocuments));
		
		popup.show(invoker, e.getX(), e.getY());
	}
	
	
	private void documentSelectionChanged ()
	{
		List<CdaDocument> documents = getSeletedDocuments();
		
		for (CdaDocumentListListener l : listeners)
		{
			l.documentSelectionChanged(documents);
		}
	}
	
	
	private void downloadSelectedDocuments ()
	{
		List<CdaDocument> documents = getSeletedDocuments();
		
		for (CdaDocumentListListener l : listeners)
		{
			l.downloadDocuments(documents);
		}
	}
	
	
	private void openSelectedDocuments ()
	{
		List<CdaDocument> documents = getSeletedDocuments();
		
		for (CdaDocumentListListener l : listeners)
		{
			l.openDocuments(documents);
		}
	}
	
	
	private void integrateSelectedDocuments ()
	{
		List<CdaDocument> documents = getSeletedDocuments();
		
		for (CdaDocumentListListener l : listeners)
		{
			l.integrateDocuments(documents);
		}
	}
	
	
	private void disintegrateSelectedDocuments ()
	{
		for (CdaDocument document : getSeletedDocuments())
			DocumentWorker.disintegrateDocument(document, cdaHandler);
	}
	
	
//	private void deleteCdaFileOfSelectedDocuments ()
//	{
//		for (CdaDocument document : getSeletedDocuments())
//			DocumentWorker.deleteCdaFile(document, cdaHandler);
//	}
	
	
	public void printDspInfo (Dsp dsp)
	{
		DspPrivileges	privileges	= Security.getCachedDspPrivileges(dsp.getDspOid());
		StringBuilder	info		= new StringBuilder("<html><font size=5>");
		String			firstname	= dsp.getGivenName();
		String			surname		= dsp.getCommonName();
		String			birthname	= dsp.getFamilyName();
		String			birthdate	= dsp.getBirthDateString("yyyy-MM-dd");
		String			gender		= dsp.getSex();
		String			address		= dsp.getAddressesString();
		String			mandateKey	= privileges != null ? "esante.eSanteTab.mandates." + privileges.getMandate() : "";
		String			mandateValue= Translatrix.getTranslationString(mandateKey);
		
		
		if (GECAMedUtils.isEmpty(firstname))
			firstname = null;
		if (GECAMedUtils.isEmpty(surname))
			surname = null;
		if (GECAMedUtils.isEmpty(birthname))
			birthname = null;
		if (GECAMedUtils.isEmpty(birthdate))
			birthdate = null;
		if (GECAMedUtils.isEmpty(gender))
			gender = null;
		if (GECAMedUtils.isEmpty(address))
			address = null;
		if (GECAMedUtils.isEmpty(mandateValue) 
				|| mandateValue.equals(mandateKey))
			mandateValue = null;
		
		if (surname != null)
			info.append(surname);
		
		if (birthname != null)
		{
			if (surname != null)
				info.append(" ").append(Translatrix.getTranslationString("esante.eSanteTab.nee")).append(" ");
			info.append(birthname);
		}
		
		if (firstname != null)
		{
			if (surname != null || birthname != null)
				info.append(", ");
			info.append(firstname).append(" ");
		}
		else if (surname != null || birthname != null)
		{
			info.append(" ");
		}
		
		if (birthdate != null)
			info.append("(").append(birthdate).append(")");
		
		if (address != null)
			info.append("</font><font size=3> - ").append(address);
		
		if (mandateValue != null)
		{
			info.append("</font><br><font size=2>")
					.append(Translatrix.getTranslationString("esante.eSanteTab.mandates"))
					.append(" ")
					.append(mandateValue);
		}
		else if (privileges != null)
		{
			logger.warn("Couldn't find a translation for mandate " + privileges.getMandate());
		}
		
		String ehrStateTranslationKey = null;
		if (privileges != null)
		{
			if (mandateValue != null)
				info.append(" | ");
			
			switch (privileges.getEhrState())
			{
				case DspPrivileges.DSP_STATE_OPEN:
					if (privileges.isActivated())
						ehrStateTranslationKey = "esante.accessRights.dspState.activated";
					else
						ehrStateTranslationKey = "esante.accessRights.dspState.open";
					break;

				case DspPrivileges.DSP_STATE_CLOSED:
					ehrStateTranslationKey = "esante.accessRights.dspState.closed";
					break;

				case DspPrivileges.DSP_STATE_DELETED:
					ehrStateTranslationKey = "esante.accessRights.dspState.deleted";
					break;
			}
			
			if (ehrStateTranslationKey != null)
				info.append(Translatrix.getTranslationString("esante.accessRights.dspState", 
						new String[] { Translatrix.getTranslationString(ehrStateTranslationKey) }));
		}
		
		info.append("</font></html>");
		
		if (gender == null)
		{
			genderIcon = null;
		}
		else if (gender.equals(Dsp.GENDER_MALE))
		{
			genderIcon = PatientManagerModule.getIcon("male.png");
		}
		else if (gender.equals(Dsp.GENDER_FEMALE))
		{
			genderIcon = PatientManagerModule.getIcon("female.png");
		}
		else
		{
			genderIcon = null;
		}
		
		dspInfoLabel.setText(info.toString());
		dspInfoLabel.setIcon(genderIcon);
		
		ESanteTab.getESanteTab(dsp.getPatientId()).enablePresencePasswordButton();
	}
}
