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

import java.awt.BorderLayout;
import java.awt.Component;
import java.net.URL;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;

import javax.persistence.Transient;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;

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.listener.AEntryAction;
import lu.tudor.santec.gecamed.core.gui.listener.IEntryPrintRenderer;
import lu.tudor.santec.gecamed.core.gui.listener.IEntryTypeHandler;
import lu.tudor.santec.gecamed.core.gui.plugin.IFileHandler;
import lu.tudor.santec.gecamed.core.gui.plugin.filehandler.DefaultEntryDeleteAction;
import lu.tudor.santec.gecamed.core.gui.plugin.filehandler.DefaultFileViewHandler;
import lu.tudor.santec.gecamed.core.gui.utils.LineColorCellRenderer;
import lu.tudor.santec.gecamed.esante.ejb.session.beans.CDAManagerBean;
import lu.tudor.santec.gecamed.esante.gui.IconNames;
import lu.tudor.santec.gecamed.esante.gui.actions.UploadToDspAction;
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.webservice.WebserviceConstants;
import lu.tudor.santec.gecamed.office.ejb.entity.beans.Physician;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.Incident;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.IncidentEntry;
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.history.table.HistoryTablePanel;
import lu.tudor.santec.i18n.Translatrix;

import org.apache.commons.io.FilenameUtils;
import org.apache.log4j.Logger;

import furbelow.AnimatedIcon;

/**
 * Handler for the files.
 * 
 * @author martin.heinemann@tudor.lu 04.03.2008 10:36:20
 * 
 * 
 * @version <br>
 *          $Log: FileHandler.java,v $
 *          Revision 1.34  2014-02-13 15:35:06  donak
 *          Fixed bug in routine detecting if the user is already logged into a patient dap but needs a presence password for uploading a document
 *          Fixed isUploadAllowed() routine and also its usage. This routine now indicates if the user is allowed to upload a document with his current permissions. If you want to determine if the user might be allowed to upload a document by providing a presence password, please use isPresencePasswordAllowed()
 *
 *          Revision 1.33  2014-01-31 16:29:43  donak
 *          Added error dialog when document cannot be uploaded due to invalid access privileges
 *          Fixed bug that prevented saml assertions from being renewed after they exceeded in cache
 *          Fixed bug that prevented documents from being uploaded (gecamed id has not been written to template due to renaming of placeholder)
 *          SMART UPLOAD (TM) feature: Upload option is added to context menu dependent on dsp access permissions and upload success probability calculations
 *          Upload support for images added
 *
 *          Revision 1.32  2014-01-30 18:14:12  donak
 *          upload option will only be offered, if the user possesses the appropriate mandate and access rights to the dsp.
 *
 *          Revision 1.31  2013-12-27 18:09:25  donak
 *          Cleanup of imports
 *
 *          Revision 1.30  2013-11-12 12:48:22  donak
 *          Document upload:
 *          * conversion to pdf/a using open office has been moved to the server. OpenOffice 4 has to be located in the jboss work directory. ATTENTION: it still has to be evaluated if the license agreement dialog occurs when instance is started the first time on the server.
 *          * If document contains a description, the first forty characters of the description followed by three dots will be used as title instead of the filename
 *          * Upload of incident type letters has been fixed
 *          * upload for docx files has been added
 *
 *          Upload parameters:
 *          * database does now support storage of user dependent properties
 *          * The system will automatically remember the last chosen values for confidentiality, facility type, and speciality and propose them as default when the next document will be uploaded.
 *
 *          Inactivity Monitor:
 *          * the event mouse wheel scrolling is now taken into account for resetting the logoff timer
 *          * the logoff delay is now stored in the database. If the database does not contain this parameter, it will be created
 *
 *          General:
 *          * Optimized incident entry bean handling. Caching will now avoid copying the binary content and the generated pdf content of an incident entry as these elements should only be loaded when needed. Now it should be save to re-implement a proper getBinaryContent() handling.
 *
 *          Revision 1.29  2013-10-29 10:04:08  donak
 *          Fixed: Unlinked patient records possessed the possibility to upload documents to the DSP, which is impossible
 *          Fixed: User will now be informed if client time is out of sync with the server and thus the saml assertion is denied
 *
 *          Revision 1.28  2013-10-23 09:37:38  donak
 *          Undo conversion deactivation
 *
 *          Revision 1.26  2013-10-16 14:37:00  donak
 *          Finished document uploading.
 *          Increased performance, more intuitive upload process including progress indicator
 *          Created a separate library-like class for IncidentEntry to pdf conversion
 *
 *          Revision 1.25  2013-10-11 16:50:09  donak
 *          Added pdf conversion support for all remaining file types (open office, ms office, flash, rtf). New office file types (docx, etc.) are not yet supported. An open office installation on the client system is necessary to make the new feature work.
 *
 *          Revision 1.24  2013-10-11 12:18:09  donak
 *          Display "my dsp" icon for files and prescriptions that have been uploaded to dsp
 *          Resize of "my dsp" icons
 *
 *          Revision 1.23  2013-10-10 16:31:35  donak
 *          Started to add eSanté "uploaded" indicators to incident entries
 *
 *          Revision 1.22  2013-10-09 16:29:35  donak
 *          Integration of cda unique document id
 * Revision 1.21 2013-09-30 12:02:15 donak
 *          Added handler for uploading supported file types to eSant� DSP
 *          Revision 1.19 2013-02-14 08:15:18 ferring incident selection added
 *          to new letters and improved for files $Log: FileHandler.java,v $
 *          Revision 1.21 2013-09-30 12:02:15 donak Added handler for uploading
 *          supported file types to eSant� DSP
 * 
 *          Revision 1.20 2013-09-13 15:37:36 ferring *** empty log message ***
 * 
 *          Revision 1.19 2013-02-14 08:15:18 ferring incident selection added
 *          to new letters and improved for files
 * 
 *          Revision 1.18 2013-02-13 14:43:35 gbosch Provisionary fix for
 *          deployment problem related to MainFrame class.
 * 
 *          Revision 1.17 2013-02-08 15:27:17 ferring Option added for files and
 *          letters to attach them to another incident
 * 
 *          Revision 1.16 2013-02-05 13:15:18 ferring letter status added
 * 
 *          Revision 1.15 2010-10-13 06:52:47 hermen cleanup
 * 
 *          Revision 1.14 2010-04-26 16:42:58 troth Redesign of the prescription
 *          view
 * 
 *          Revision 1.13 2009-05-06 16:00:05 heinemann added method to generate
 *          printable output of the incident entrys
 * 
 *          Revision 1.12 2008-12-16 10:35:43 hermen added fixJarUrl for
 *          Webstart icon url bug
 * 
 *          Revision 1.11 2008-12-10 15:17:02 hermen added bugfix for java5
 *          webstart resource loading
 * 
 *          Revision 1.10 2008-09-25 09:43:07 heinemann fixed copyrights
 * 
 *          Revision 1.9 2008-07-10 10:21:26 heinemann *** empty log message ***
 * 
 *          Revision 1.8 2008-04-11 14:47:41 heinemann *** empty log message ***
 * 
 *          Revision 1.7 2008-04-10 14:19:30 heinemann added original filename o
 *          the IncidentEntry table. differs to filename which is the generated
 *          name of the timestamp+originalfilename
 * 
 *          Revision 1.6 2008-04-09 12:53:59 heinemann *** empty log message ***
 * 
 *          Revision 1.5 2008-04-09 09:39:43 heinemann *** empty log message ***
 * 
 *          Revision 1.4 2008-03-28 14:56:36 heinemann *** empty log message ***
 * 
 *          Revision 1.3 2008-03-20 16:08:14 heinemann *** empty log message *** <br>
 *          Revision 1.2 2008-03-10 12:37:52 heinemann <br>
 *          *** empty log message *** <br>
 * <br>
 *          Revision 1.1 2008-03-06 15:34:27 heinemann <br>
 *          *** empty log message *** <br>
 * 
 */
public class FileHandler implements IEntryTypeHandler {

	/***************************************************************************
	 * File extension for which this handler is capable of
	 */
	public static final String EXT_JPG = "jpg";
	public static final String EXT_PNG = "png";
	public static final String EXT_JPEG = "jpeg";
	public static final String EXT_TIFF = "tiff";
	public static final String EXT_BMP = "bmp";
	public static final String EXT_GIF = "gif";

	public static final String EXT_DOC = "doc";
	public static final String EXT_ODT = "odt";
	public static final String EXT_XLS = "xls";
	public static final String EXT_ODS = "ods";
	public static final String EXT_PDF = "pdf";
	public static final String EXT_TXT = "txt";

	public static final String EXT_MP3 = "mp3";
	public static final String EXT_WAV = "wav";
	public static final String EXT_WMV = "wmv";
	public static final String EXT_OGG = "ogg";
	public static final String EXT_AVI = "avi";
	public static final String EXT_MPG = "mpg";
	public static final String EXT_MPEG = "mpeg";

	// default fall back
	public static final String EXT_ALL = "*";

	/***************************************************************************
	 * Mime-Types for which this handler is capable of
	 */
	public static final String MIME_JPG = "image/jpeg";
	public static final String MIME_TIFF = "image/tiff";
	public static final String MIME_BMP = "image/bmp";
	public static final String MIME_PNG = "image/png";
	public static final String MIME_GIF = "image/gif";

	// default fall back
	public static final String MIME_ALL = "*";

	/***************************************************************************
	 * Mime-Type icons
	 */
	private static final URL ICON_LETTER = PatientManagerModule.class.getResource("resources/icons/" + PatientManagerModule.MIME_LETTER);
	private static final URL ICON_AUDIO = PatientManagerModule.class.getResource("resources/icons/" + PatientManagerModule.MIME_AUDIO);
	// private static final URL ICON_FORMULA =
	// PatientManagerModule.class.getResource("resources/icons/"+PatientManagerModule.MIME_FORMULA);
	private static final URL ICON_IMAGE = PatientManagerModule.class.getResource("resources/icons/" + PatientManagerModule.MIME_IMAGE);
	private static final URL ICON_PDF = PatientManagerModule.class.getResource("resources/icons/" + PatientManagerModule.MIME_PDF);
	private static final URL ICON_SPREAD = PatientManagerModule.class.getResource("resources/icons/" + PatientManagerModule.MIME_SPREAD);
	private static final URL ICON_TEXT = PatientManagerModule.class.getResource("resources/icons/" + PatientManagerModule.MIME_TEXT);
	private static final URL ICON_UNKNOWN = PatientManagerModule.class.getResource("resources/icons/" + PatientManagerModule.MIME_UNKNOWN);
	private static final URL ICON_VIDEO = PatientManagerModule.class.getResource("resources/icons/" + PatientManagerModule.MIME_VIDEO);

	/* ------------------------------------------------------- */
	private static final ImageIcon IMAGE_LETTER = PatientManagerModule.getMediumIcon(PatientManagerModule.MIME_LETTER);
	private static final ImageIcon IMAGE_AUDIO = PatientManagerModule.getMediumIcon(PatientManagerModule.MIME_AUDIO);
	// private static final ImageIcon IMAGE_FORMULA =
	// PatientManagerModule.getMediumIcon(PatientManagerModule.MIME_FORMULA);
	private static final ImageIcon IMAGE_IMAGE = PatientManagerModule.getMediumIcon(PatientManagerModule.MIME_IMAGE);
	private static final ImageIcon IMAGE_PDF = PatientManagerModule.getMediumIcon(PatientManagerModule.MIME_PDF);
	private static final ImageIcon IMAGE_SPREAD = PatientManagerModule.getMediumIcon(PatientManagerModule.MIME_SPREAD);
	private static final ImageIcon IMAGE_TEXT = PatientManagerModule.getMediumIcon(PatientManagerModule.MIME_TEXT);
	private static final ImageIcon IMAGE_UNKNOWN = PatientManagerModule.getMediumIcon(PatientManagerModule.MIME_UNKNOWN);
	private static final ImageIcon IMAGE_VIDEO = PatientManagerModule.getMediumIcon(PatientManagerModule.MIME_VIDEO);

	// for the html rendering
	public static HashMap<String, URL> iconMimeMapping = new HashMap<String, URL>();
	public static HashMap<String, URL> iconExtensionMapping = new HashMap<String, URL>();
	// for normal rendering
	public static HashMap<String, ImageIcon> imageExtensionMapping = new HashMap<String, ImageIcon>();

	static {
		/* ------------------------------------------------------- */
		iconMimeMapping.put("text/plain", ICON_TEXT);
		iconMimeMapping.put(MIME_PNG, ICON_IMAGE);
		iconMimeMapping.put(MIME_BMP, ICON_IMAGE);
		iconMimeMapping.put(MIME_GIF, ICON_IMAGE);
		iconMimeMapping.put(MIME_JPG, ICON_IMAGE);
		iconMimeMapping.put(MIME_TIFF, ICON_IMAGE);
		iconMimeMapping.put("content/unknown", ICON_UNKNOWN);
		iconMimeMapping.put("application/pdf", ICON_PDF);
		/* ------------------------------------------------------- */
		// images
		iconExtensionMapping.put(EXT_JPG, ICON_IMAGE);
		iconExtensionMapping.put(EXT_PNG, ICON_IMAGE);
		iconExtensionMapping.put(EXT_JPEG, ICON_IMAGE);
		iconExtensionMapping.put(EXT_TIFF, ICON_IMAGE);
		iconExtensionMapping.put(EXT_BMP, ICON_IMAGE);
		iconExtensionMapping.put(EXT_GIF, ICON_IMAGE);
		// documents
		iconExtensionMapping.put(EXT_DOC, ICON_LETTER);
		iconExtensionMapping.put(EXT_ODT, ICON_LETTER);
		iconExtensionMapping.put(EXT_XLS, ICON_SPREAD);
		iconExtensionMapping.put(EXT_ODS, ICON_SPREAD);
		iconExtensionMapping.put(EXT_PDF, ICON_PDF);
		iconExtensionMapping.put(EXT_TXT, ICON_TEXT);
		// audio
		iconExtensionMapping.put(EXT_MP3, ICON_AUDIO);
		iconExtensionMapping.put(EXT_WAV, ICON_AUDIO);
		iconExtensionMapping.put(EXT_WMV, ICON_AUDIO);
		iconExtensionMapping.put(EXT_OGG, ICON_AUDIO);
		// video
		iconExtensionMapping.put(EXT_AVI, ICON_VIDEO);
		iconExtensionMapping.put(EXT_MPG, ICON_VIDEO);
		iconExtensionMapping.put(EXT_MPEG, ICON_VIDEO);
		/* ------------------------------------------------------- */
		// image rendering
		/* ------------------------------------------------------- */
		// images
		imageExtensionMapping.put(EXT_JPG, IMAGE_IMAGE);
		imageExtensionMapping.put(EXT_PNG, IMAGE_IMAGE);
		imageExtensionMapping.put(EXT_JPEG, IMAGE_IMAGE);
		imageExtensionMapping.put(EXT_TIFF, IMAGE_IMAGE);
		imageExtensionMapping.put(EXT_BMP, IMAGE_IMAGE);
		imageExtensionMapping.put(EXT_GIF, IMAGE_IMAGE);
		// documents
		imageExtensionMapping.put(EXT_DOC, IMAGE_LETTER);
		imageExtensionMapping.put(EXT_ODT, IMAGE_LETTER);
		imageExtensionMapping.put(EXT_XLS, IMAGE_SPREAD);
		imageExtensionMapping.put(EXT_ODS, IMAGE_SPREAD);
		imageExtensionMapping.put(EXT_PDF, IMAGE_PDF);
		imageExtensionMapping.put(EXT_TXT, IMAGE_TEXT);
		// audio
		imageExtensionMapping.put(EXT_MP3, IMAGE_AUDIO);
		imageExtensionMapping.put(EXT_WAV, IMAGE_AUDIO);
		imageExtensionMapping.put(EXT_WMV, IMAGE_AUDIO);
		imageExtensionMapping.put(EXT_OGG, IMAGE_AUDIO);
		// video
		imageExtensionMapping.put(EXT_AVI, IMAGE_VIDEO);
		imageExtensionMapping.put(EXT_MPG, IMAGE_VIDEO);
		imageExtensionMapping.put(EXT_MPEG, IMAGE_VIDEO);
		/* ------------------------------------------------------- */
	}

	/**
	 * 
	 */
	private Collection<IFileHandler> fileHandlers = new HashSet<IFileHandler>();

	private FileRenderer renderer = new FileRenderer();

	// define upload action
	private UploadToDspAction uploadToDspAction;
	
	// define update action
	private UploadToDspAction updateDocumentAction;
	
	private DefaultEntryDeleteAction deleteAction;
	
	/** the logger Object for this class */
	private static Logger logger = Logger.getLogger(FileHandler.class.getName());

	private static DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());

	private static DateFormat timeFormatter = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault());

	/**
	 * 
	 */
	public FileHandler() {

		// load the handler
		// ImageViewHandler imageViewHandler = new ImageViewHandler();
		DefaultFileViewHandler defaultViewHandler = new DefaultFileViewHandler();

		// fileHandlers.add(imageViewHandler);
		fileHandlers.add(defaultViewHandler);
		/* ------------------------------------------------------- */
		// create action instance for uploading files to DSP
		this.uploadToDspAction = new UploadToDspAction();

		this.updateDocumentAction = new UploadToDspAction(Translatrix.getTranslationString("esante.actions.updateDocument"));

		this.deleteAction = new DefaultEntryDeleteAction(Translatrix.getTranslationString("plugin.file.delete"),
				Translatrix.getTranslationString("plugin.file.delete"), Translatrix.getTranslationString("plugin.file.delete.question"));
	}

	
	/**
	 * Indicates if the local Gecamed patient is currently linked to an electronic health record (dsp) 
	 * @return True, if the patient is linked to a dsp
	 */
	private boolean isPatientLinkedToDsp() {
		
		Patient patient = GECAMedModule.getCurrentPatient();
		return CDAManagerBean.getInstance().getLinkedDsp(patient.getId()) != null;
	}
	
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * lu.tudor.santec.gecamed.core.gui.listener.IEntryTypeHandler#getRenderer
	 * (java.lang.String)
	 */
	public TableCellRenderer getRenderer(String entryType) {
		/* ====================================================== */
		return renderer;
		/* ====================================================== */
	}

	public HashMap<Integer, Object> getSpecialEntries(String entryType, Integer patientId) {
		/* ====================================================== */
		// as the files may contain binary data, we will do nothing here to load
		// the data only when it is really needed.
		// the adminstrative file data (name, description, size) is stored in
		// the
		// incident entry.
		return null;
		/* ====================================================== */
	}

	
	/***************************************************************************
	 * Open the entry -> default action
	 */
	public boolean openEntry (IncidentEntry entry)
	{
		if (entry == null)
			return false;
		/* ------------------------------------------------------- */
		List<IFileHandler> handler = getHandlers(entry.getEntryType().getMimeType());
		if (handler == null || handler.size() < 1)
			return HistoryTablePanel.showEntryNotOpenedDialog(HistoryTablePanel.EOF_MODULE_NOT_LOADED, null, entry);
		
		
		for (IFileHandler gh : handler)
		{
//			gh.setFile(bytes, entry.getFileName());
			gh.getActions(entry);
			gh.defaultAction();
			break;
		}
		return true;
	}
	

	/**
	 * Get the handlers for that mimetype
	 * 
	 * @param mimetype
	 * @return
	 */
	private List<IFileHandler> getHandlers(String mimetype) {
		/* ================================================== */
		List<IFileHandler> handlers = new ArrayList<IFileHandler>();

		for (IFileHandler gh : fileHandlers) {
			/* ------------------------------------------------------- */
			if (gh.getSupportedMimetypes().contains(mimetype)) {
				/* ------------------------------------------------------- */
				handlers.add(gh);
				/* ------------------------------------------------------- */
			}
			/* ------------------------------------------------------- */
		}
		/* ------------------------------------------------------- */
		// call default handler, if nothing happend until now
		if (handlers.size() < 1) {
			/* ------------------------------------------------------- */
			/* ------------------------------------------------------- */
			for (IFileHandler gh : fileHandlers) {
				/* ------------------------------------------------------- */
				IFileHandler fileHandler = gh;
				if (fileHandler.getSupportedMimetypes().contains(MIME_ALL)) {
					/* ------------------------------------------------------- */
					handlers.add(fileHandler);
					/* ------------------------------------------------------- */
				}
			}
			/* ------------------------------------------------------- */
		}

		return handlers;
		/* ================================================== */
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * lu.tudor.santec.gecamed.core.gui.listener.IEntryTypeHandler#getActions
	 * (lu.tudor.santec.gecamed.patient.ejb.entity.beans.IncidentEntry)
	 */
	public Collection<Action> getActions(IncidentEntry entry) {
		/* ====================================================== */
		List<IFileHandler> handler = getHandlers(entry.getEntryType().getMimeType());
		List<Action> actions = new ArrayList<Action>();
		/* ------------------------------------------------------- */
		for (IFileHandler ha : handler) {
			/* ------------------------------------------------------- */
			List<Action> handlerActions = ha.getActions(entry);
			if (handlerActions != null) {
				// actions.addAll(ha.getActions(entry));
				for (Action a : ha.getActions(entry)) {
					if (a instanceof AEntryAction)
						((AEntryAction) a).setEntry(entry);
					actions.add(a);
				}
			}
			/* ------------------------------------------------------- */
		}
		// get the type of the document
		String fileType = FilenameUtils.getExtension(entry.getFileName());

		// obtain user privileges from cache
		DspPrivileges privileges = Security.getCachedDspPrivileges(GECAMedModule.getCurrentPatient().getIdLuxembourg());
		// only add an upload option if the patient has been linked to a dsp and the user possesses sufficient permissions
		// However if the user is not logged into the eSanté DSP thoses permissions cannot be determined.
		// Thus show the upload option also in this case (however only for supported document types)
		if (isPatientLinkedToDsp() && WebserviceConstants.UPLOAD_DOCUMENT_TYPES.contains(fileType)
				&& ((privileges == null) || privileges.isUploadAllowed() || privileges.isPresencePasswordAllowed())) {

			if (entry.getCdaUniqueId() == null) {
				// this prescription is not yet available in the eSanté DSP, thus add the upload item to the context menu
				this.uploadToDspAction.setEntry(entry);
				actions.add(this.uploadToDspAction);
			} else {
				// add item for replacing the document
				this.updateDocumentAction.setUploadMode(WebserviceConstants.UPLOAD_REPLACE_DOCUMENT);
				this.updateDocumentAction.setEntry(entry);
				actions.add(this.updateDocumentAction);
			}
		}

		this.deleteAction.setEntry(entry);
		actions.add(this.deleteAction);

		return actions;
		/* ====================================================== */
	}

	public JPopupMenu getPopup(IncidentEntry entry) {
		return null;
	}

	/**
	 * Returns an ImageIcon for a file extension
	 * 
	 * @param extension
	 * @return
	 */
	public static ImageIcon getImage(String extension) {
		/* ================================================== */
		String ext = extension;
		if (ext.contains(".")) {
			// cut
			ext = FilenameUtils.getExtension(ext);
		}
		/* ------------------------------------------------------- */
		ext = ext.toLowerCase();
		/* ------------------------------------------------------- */
		ImageIcon image = imageExtensionMapping.get(ext);
		if (image == null)
			image = IMAGE_UNKNOWN;
		/* ------------------------------------------------------- */
		return image;
		/* ================================================== */
	}

	/**
	 * Tries to return an icon string for the mimetype
	 * 
	 * @param mimetype
	 * @return null, if no type was found
	 */
	public static String getIconMime(String mimetype) {
		/* ================================================== */
		if (mimetype == null)
			return null;
		/* ------------------------------------------------------- */
		String mime = mimetype.toLowerCase();
		/* ------------------------------------------------------- */
		String icon = iconMimeMapping.get(mime).toString();
		return icon;
		/* ================================================== */
	}

	/**
	 * @param extension
	 *            the file extension
	 * @return
	 */
	public static String getIcon(String extension) {
		/* ================================================== */
		String ext = extension;
		if (ext.contains(".")) {
			// cut
			ext = FilenameUtils.getExtension(ext);
		}
		/* ------------------------------------------------------- */
		ext = ext.toLowerCase();
		/* ------------------------------------------------------- */
		URL icon = iconExtensionMapping.get(ext);
		if (icon == null)
			icon = ICON_UNKNOWN;
		/* ------------------------------------------------------- */

		// // fixes java5 webstart resource loading bug
		// if (icon.indexOf(".jar") < 0) {
		// String jarFile =
		// LetterHandler.class.getProtectionDomain().getCodeSource().getLocation().toString();
		// String path = icon.replaceAll("jar:", "");
		// String validPath = "jar:" + jarFile + "!/" + path;
		// // System.out.println("newPath:" + validPath);
		// return validPath;
		// }
		return IconFetcher.fixJarURL(icon).toString();
		/* ================================================== */
	}

	/**
	 * @author martin.heinemann@tudor.lu 04.03.2008 10:46:21
	 * 
	 * 
	 * @version <br>
	 *          $Log: FileHandler.java,v $
	 *          Revision 1.34  2014-02-13 15:35:06  donak
	 *          Fixed bug in routine detecting if the user is already logged into a patient dap but needs a presence password for uploading a document
	 *          Fixed isUploadAllowed() routine and also its usage. This routine now indicates if the user is allowed to upload a document with his current permissions. If you want to determine if the user might be allowed to upload a document by providing a presence password, please use isPresencePasswordAllowed()
	 *
	 *          Revision 1.33  2014-01-31 16:29:43  donak
	 *          Added error dialog when document cannot be uploaded due to invalid access privileges
	 *          Fixed bug that prevented saml assertions from being renewed after they exceeded in cache
	 *          Fixed bug that prevented documents from being uploaded (gecamed id has not been written to template due to renaming of placeholder)
	 *          SMART UPLOAD (TM) feature: Upload option is added to context menu dependent on dsp access permissions and upload success probability calculations
	 *          Upload support for images added
	 *
	 *          Revision 1.32  2014-01-30 18:14:12  donak
	 *          upload option will only be offered, if the user possesses the appropriate mandate and access rights to the dsp.
	 *
	 *          Revision 1.31  2013-12-27 18:09:25  donak
	 *          Cleanup of imports
	 *
	 *          Revision 1.30  2013-11-12 12:48:22  donak
	 *          Document upload:
	 *          * conversion to pdf/a using open office has been moved to the server. OpenOffice 4 has to be located in the jboss work directory. ATTENTION: it still has to be evaluated if the license agreement dialog occurs when instance is started the first time on the server.
	 *          * If document contains a description, the first forty characters of the description followed by three dots will be used as title instead of the filename
	 *          * Upload of incident type letters has been fixed
	 *          * upload for docx files has been added
	 *
	 *          Upload parameters:
	 *          * database does now support storage of user dependent properties
	 *          * The system will automatically remember the last chosen values for confidentiality, facility type, and speciality and propose them as default when the next document will be uploaded.
	 *
	 *          Inactivity Monitor:
	 *          * the event mouse wheel scrolling is now taken into account for resetting the logoff timer
	 *          * the logoff delay is now stored in the database. If the database does not contain this parameter, it will be created
	 *
	 *          General:
	 *          * Optimized incident entry bean handling. Caching will now avoid copying the binary content and the generated pdf content of an incident entry as these elements should only be loaded when needed. Now it should be save to re-implement a proper getBinaryContent() handling.
	 *
	 *          Revision 1.29  2013-10-29 10:04:08  donak
	 *          Fixed: Unlinked patient records possessed the possibility to upload documents to the DSP, which is impossible
	 *          Fixed: User will now be informed if client time is out of sync with the server and thus the saml assertion is denied
	 *
	 *          Revision 1.28  2013-10-23 09:37:38  donak
	 *          Undo conversion deactivation
	 *
	 *          Revision 1.26  2013-10-16 14:37:00  donak
	 *          Finished document uploading.
	 *          Increased performance, more intuitive upload process including progress indicator
	 *          Created a separate library-like class for IncidentEntry to pdf conversion
	 *
	 *          Revision 1.25  2013-10-11 16:50:09  donak
	 *          Added pdf conversion support for all remaining file types (open office, ms office, flash, rtf). New office file types (docx, etc.) are not yet supported. An open office installation on the client system is necessary to make the new feature work.
	 *
	 *          Revision 1.24  2013-10-11 12:18:09  donak
	 *          Display "my dsp" icon for files and prescriptions that have been uploaded to dsp
	 *          Resize of "my dsp" icons
	 *
	 *          Revision 1.23  2013-10-10 16:31:35  donak
	 *          Started to add eSanté "uploaded" indicators to incident entries
	 *
	 *          Revision 1.22  2013-10-09 16:29:35  donak
	 *          Integration of cda unique document id
	 * Revision 1.21 2013-09-30 12:02:15
	 *          donak Added handler for uploading supported file types to eSant�
	 *          DSP Revision 1.19 2013-02-14 08:15:18 ferring incident selection
	 *          added to new letters and improved for files $Log:
	 *          FileHandler.java,v $ Revision 1.21 2013-09-30 12:02:15 donak
	 *          Added handler for uploading supported file types to eSant� DSP
	 * 
	 *          Revision 1.20 2013-09-13 15:37:36 ferring *** empty log message
	 *          ***
	 * 
	 *          Revision 1.19 2013-02-14 08:15:18 ferring incident selection
	 *          added to new letters and improved for files
	 * 
	 *          Revision 1.18 2013-02-13 14:43:35 gbosch Provisionary fix for
	 *          deployment problem related to MainFrame class.
	 * 
	 *          Revision 1.17 2013-02-08 15:27:17 ferring Option added for files
	 *          and letters to attach them to another incident
	 * 
	 *          Revision 1.16 2013-02-05 13:15:18 ferring letter status added
	 * 
	 *          Revision 1.15 2010-10-13 06:52:47 hermen cleanup
	 * 
	 *          Revision 1.14 2010-04-26 16:42:58 troth Redesign of the
	 *          prescription view
	 * 
	 *          Revision 1.13 2009-05-06 16:00:05 heinemann added method to
	 *          generate printable output of the incident entrys
	 * 
	 *          Revision 1.12 2008-12-16 10:35:43 hermen added fixJarUrl for
	 *          Webstart icon url bug
	 * 
	 *          Revision 1.11 2008-12-10 15:17:02 hermen added bugfix for java5
	 *          webstart resource loading
	 * 
	 *          Revision 1.10 2008-09-25 09:43:07 heinemann fixed copyrights
	 * 
	 *          Revision 1.9 2008-07-10 10:21:26 heinemann *** empty log message
	 *          ***
	 * 
	 *          Revision 1.8 2008-04-11 14:47:41 heinemann *** empty log message
	 *          ***
	 * 
	 *          Revision 1.7 2008-04-10 14:19:30 heinemann added original
	 *          filename o the IncidentEntry table. differs to filename which is
	 *          the generated name of the timestamp+originalfilename
	 * 
	 *          Revision 1.6 2008-04-09 12:53:59 heinemann *** empty log message
	 *          ***
	 * 
	 *          Revision 1.5 2008-04-09 09:39:43 heinemann *** empty log message
	 *          ***
	 * 
	 *          Revision 1.4 2008-03-28 14:56:36 heinemann *** empty log message
	 *          ***
	 * 
	 *          Revision 1.3 2008-03-20 16:08:14 heinemann *** empty log message
	 *          *** <br>
	 *          Revision 1.2 2008-03-10 12:37:52 heinemann <br>
	 *          *** empty log message *** <br>
	 * <br>
	 *          Revision 1.1 2008-03-06 15:34:27 heinemann <br>
	 *          *** empty log message *** <br>
	 * 
	 */
	class FileRenderer extends LineColorCellRenderer {

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		private final static int fontSize = 9;

		private JLabel fileTypeLabel;
		private JLabel uploadedIconLabel;
		private JPanel cellPanel;
		
		private ImageIcon eSanteIcon;
		private AnimatedIcon uploadingIcon;		

		public FileRenderer() {
			this.fileTypeLabel = new JLabel();
			this.fileTypeLabel.setOpaque(false);
			this.uploadedIconLabel = new JLabel();
			this.uploadedIconLabel.setOpaque(false);
			this.cellPanel = new JPanel(new BorderLayout());
			this.cellPanel.setOpaque(true);
			this.cellPanel.add(fileTypeLabel, BorderLayout.WEST);
			this.cellPanel.add(uploadedIconLabel, BorderLayout.EAST);
			// DO NOT use IconFetcher for this at this location. Otherwise animation will fail!
			this.uploadingIcon = new AnimatedIcon( new ImageIcon(IconNames.class.getResource("resources/icons/" +  IconNames.LOADING_ANIMATED)));
			this.eSanteIcon = ESanteGuiUtils.getESanteIcon(64);
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see lu.tudor.santec.gecamed.core.gui.utils.LineColorCellRenderer# getTableCellRendererComponent(javax.swing.JTable, java.lang.Object, boolean,
		 * boolean, int, int)
		 */
		@Override
		public Component getTableCellRendererComponent(JTable p_Table, Object value, boolean p_IsSelected, boolean hasFocus, int p_Row, int p_Column) {

			this.setIcon(null);
			if (value instanceof IncidentEntry) {
				IncidentEntry entry = (IncidentEntry) value;
				// type name
				if (p_Column == 2) {
					// render the column
					return super.getTableCellRendererComponent(p_Table, "F", p_IsSelected, hasFocus, p_Row, p_Column);
					// document details: Document typ icon, filename, description, eSanté DSP icon (if document is already uploaded)
				} else if (p_Column == 3) {
					// assemble the representation of the document details: filename and description
					StringBuffer buff = new StringBuffer("<html><span style=\"font-family:Arial;font-size:" + fontSize + "px;\">");
					// add the icon that symbolizes the file type
					ImageIcon icon = FileHandler.getImage(entry.getFileName());
					this.fileTypeLabel.setIcon(icon);
					// add the description if there is any
					if (entry.getTextContent() != null) {
						buff.append(entry.getTextContent().replaceAll("\n", "<br>") + "<br>");
					}
					// add the filename
					if (entry.getFileName() != null) {
						buff.append(entry.getOriginalFilename());
					}
					// add the filename
					if (entry.getFileSize() != null) {
						try {
							if ((entry.getFileSize()/1024)<1000) {
								buff.append(" ("+(entry.getFileSize()/1024)+"kb)");	
							} else {
								buff.append(" ("+(entry.getFileSize()/1024/1024)+"mb)");
							}							
						} catch (Exception e) {}
						
					}
					// and finish the html content
					buff.append("</span></html>");
					
					if (entry.getCdaUniqueId() == null) {
						// document hat not been uploaded to DSP - display no icon at all
						this.uploadedIconLabel.setIcon(null);
					} else if (entry.getCdaUniqueId().equals(IconNames.UPLOAD_INDICATOR_STRING)) {
						// if the document is currently in the upload process, display an animated gif to indicate activity
						this.uploadedIconLabel.setIcon(this.uploadingIcon);
					} else{
						// if the document has already been uploaded to the dsp indicate this by a "my dsp" icon
						this.uploadedIconLabel.setIcon(this.eSanteIcon);	
					}
										
					// render the cell
					super.getTableCellRendererComponent(p_Table, buff.toString(), p_IsSelected, hasFocus, p_Row, p_Column);
					// and add it to the table
					this.cellPanel.add(this, BorderLayout.CENTER);
					// set the alignment
					this.setHorizontalAlignment(JLabel.LEFT);
					// and also the background color
					this.cellPanel.setBackground(this.getBackground());

					return this.cellPanel;
					/* ------------------------------------------------------- */
				}
				/* ------------------------------------------------------- */
			}
			return super.getTableCellRendererComponent(p_Table, value, p_IsSelected, hasFocus, p_Row, p_Column);
		}
	}

	public IEntryPrintRenderer getPrintRenderer(String entryType) {
		/* ====================================================== */
		// TODO Auto-generated method stub
		return null;
		/* ====================================================== */
	}

	@Transient
	public static String getHistoryText(Incident incident) {
		Physician physician = MainFrame.getPhysicianById(incident.getPhysicianId());

		return new StringBuilder("<html>").append(dateFormatter.format(incident.getIncidentDate())).append(" <font size=2>")
				.append(timeFormatter.format(incident.getIncidentDate())).append("</font> ").append(physician.getMnemonic()).append("</html>").toString();
	}
}
