/*******************************************************************************
 * 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.core.gui.plugin.filehandler;

import java.awt.event.ActionEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.swing.AbstractAction;
import javax.swing.Action;

import lu.tudor.santec.gecamed.core.gui.GECAMedIconNames;
import lu.tudor.santec.gecamed.core.gui.GECAMedModule;
import lu.tudor.santec.gecamed.core.gui.MainFrame;
import lu.tudor.santec.gecamed.core.gui.plugin.IFileHandler;
import lu.tudor.santec.gecamed.core.gui.plugin.filehandler.FileOpener.FileOpenerListener;
import lu.tudor.santec.gecamed.core.gui.widgets.ErrorDialog;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.IncidentEntry;
import lu.tudor.santec.gecamed.patient.gui.history.FileHandler;
import lu.tudor.santec.gecamed.patient.gui.history.contextmenu.ChangeIncidentAction;
import lu.tudor.santec.gecamed.patient.gui.history.table.HistoryTablePanel;
import lu.tudor.santec.gecamed.patient.utils.EntryDeletedException;
import lu.tudor.santec.i18n.Translatrix;

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

/**
 * 
 * Can show images like jpeg, tiff, etc.
 * 
 * @author martin.heinemann@tudor.lu
 * 07.12.2007
 * 14:40:59
 *
 *
 * @version
 * <br>$Log: DefaultFileViewHandler.java,v $
 * <br>Revision 1.20  2014-02-17 14:04:31  ferring
 * <br>Editing file entries by clicking removed, context menu option to edit description and file name added instead
 * <br>
 * <br>Revision 1.19  2013-10-23 13:19:31  ferring
 * <br>FileOpening fixed
 * <br>
 * <br>Revision 1.18  2013-10-21 08:17:08  ferring
 * <br>message shown when file opening failed
 * <br>
 * <br>Revision 1.17  2013-07-15 06:18:37  ferring
 * <br>logging changed
 * <br>
 * <br>Revision 1.16  2013-06-10 08:08:26  ferring
 * <br>Handling to open files changed
 * <br>
 * <br>Revision 1.15  2013-02-08 15:27:16  ferring
 * <br>Option added for files and letters to attach them to another incident
 * <br>
 * <br>Revision 1.14  2013-01-14 11:01:29  ferring
 * <br>keep compatibility with java 1.5
 * <br>
 * <br>Revision 1.13  2012-10-02 11:22:08  ferring
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.12  2012-10-02 11:08:09  ferring
 * <br>system call handling improved
 * <br>
 * <br>Revision 1.11  2012-10-02 06:28:41  ferring
 * <br>file opening improved - using Desktop API if possible, else, for Linux better choose of the system command
 * <br>
 * <br>Revision 1.10  2008-09-25 09:43:06  heinemann
 * <br>fixed copyrights
 * <br>
 * <br>Revision 1.9  2008-05-27 15:55:22  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.8  2008-04-09 09:39:43  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.7  2008-03-20 16:08:14  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.6  2008-03-12 13:55:59  hermen
 * <br>fixed kde-open
 * <br>
 * <br>Revision 1.5  2008-03-12 13:34:26  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.4  2008-03-12 12:43:52  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.3  2008-03-12 12:33:26  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.2  2008-02-22 13:10:41  mack
 * <br>Removed obsolete imports
 * <br>
 * <br>Revision 1.1  2007-12-17 14:59:59  heinemann
 * <br>plugins and file store and open
 * <br>
 *   
 */
public class DefaultFileViewHandler implements IFileHandler {
	
	/** the logger Object for this class */
	private static Logger logger = Logger.getLogger(DefaultFileViewHandler.class.getName());
	
	
	private AbstractAction defaultAction;
	private AbstractAction changeIncidentAction;
	private AbstractAction changeDescriptionAction;
	private ArrayList<Action> actionList;
	private HashSet<String> extensions;
	private HashSet<String> mimetypes;
//	private File file;
	private byte[] binaryData;
	private String filename;
	private IncidentEntry entry;

	public DefaultFileViewHandler() {
		/* ================================================== */
		initDefaultAction();
		/* ------------------------------------------------------- */
		// actions
		/* ------------------------------------------------------- */
		this.actionList = new ArrayList<Action>();
		actionList.add(defaultAction);
		actionList.add(changeDescriptionAction);
		actionList.add(changeIncidentAction);
		/* ------------------------------------------------------- */
		// extensions
		/* ------------------------------------------------------- */
		this.extensions = new HashSet<String>();
		extensions.add(FileHandler.EXT_ALL);
		/* ------------------------------------------------------- */
		// mimetypes
		/* ------------------------------------------------------- */
		this.mimetypes = new HashSet<String>();
		mimetypes.add(FileHandler.MIME_ALL);
		/* ================================================== */
	}
	

	/**
	 * Show image 
	 */
	public void defaultAction() {
		/* ====================================================== */
		this.defaultAction.actionPerformed(null);
		/* ====================================================== */
	}

	/**
	 * 
	 */
	public List<Action> getActions(IncidentEntry entry) {
		/* ====================================================== */
		this.entry = entry;
		return actionList;
		/* ====================================================== */
	}

	/**
	 * 
	 */
	public Set<String> getSupportedExtensions() {
		/* ====================================================== */
		return extensions;
		/* ====================================================== */
	}

	/**
	 * 
	 */
	public Set<String> getSupportedMimetypes() {
		/* ====================================================== */
		return mimetypes;
		/* ====================================================== */
	}

	/**
	 * 
	 */
	public void setFile(URL fileUrl) {
		/* ====================================================== */
//		this.fileURL = fileUrl;
		/* ====================================================== */
	}

	/**
	 * 
	 */
	public void setFile(byte[] binaryData, String filename) {
		/* ====================================================== */
		this.binaryData = binaryData;
		this.filename   = filename;
		/* ====================================================== */
	}
	
	
	
	/**
	 * @throws Exception 
	 * @throws EntryDeletedException 
	 * @throws FileNotFoundException 
	 * 
	 */
	private boolean createTempfile()  {
		/* ================================================== */
		File file;
		/* ------------------------------------------------------- */
		if (entry != null) {
			/* ------------------------------------------------------- */
			this.filename = entry.getFileName();
			try
			{
				this.binaryData = FileOpener.loadBinary(entry);
			}
			catch (FileNotFoundException e)
			{
				logger.error("Error while trying to load data of incident entry file", e);
				HistoryTablePanel.showEntryNotOpenedDialog(HistoryTablePanel.EOF_FILE_NOT_FOUND, e, entry);
			}
			catch (EntryDeletedException e)
			{
				logger.error("Error while trying to load data of incident entry file", e);
				HistoryTablePanel.showEntryNotOpenedDialog(HistoryTablePanel.EOF_ENTRY_NOT_FOUND, e, entry);
			}
			catch (Exception e)
			{
				logger.error("Error while trying to load data of incident entry file", e);
				return false;
			}
			/* ------------------------------------------------------- */
		}
		try {
			file = FileOpener.createGECAMedTempFile(FilenameUtils.getBaseName(filename),
					 "."+FilenameUtils.getExtension(filename));
			FileOutputStream fout = new FileOutputStream(file);
			fout.write(binaryData);
			fout.close();
			
			return true;
		} catch (IOException e) {
			logger.error("Error while trying to write temp file to open incident entry.", e);
			return HistoryTablePanel.showEntryNotOpenedDialog(HistoryTablePanel.EOF_COULDNT_WRITE_FILE, e, entry);
		}
		/* ================================================== */
	}
	
	
	/**
	 * 
	 */
	private void initDefaultAction() 
	{
		defaultAction = new AbstractAction(Translatrix.getTranslationString("plugin.file.viewer.open"), 
				GECAMedModule.getSmallIcon(GECAMedIconNames.OPEN)) {

			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e) 
			{
				openFile();
			}
		};
		
		changeDescriptionAction = new AbstractAction(
				Translatrix.getTranslationString("History.changeFileDescription.menuItemText"),
				GECAMedModule.getSmallIcon(GECAMedIconNames.RENAME))
		{
			private static final long	serialVersionUID	= 1L;

			public void actionPerformed (ActionEvent e)
			{
				ChangeFileDescriptionDialog.showDialog(entry);
			}
		};
		
		changeIncidentAction = ChangeIncidentAction.getInstance();
	}
	
	
	public void openFile ()
	{
		if (entry != null)
		{
			/* ---------------------------------------- */
			// Look if the tmp file of this entry already exists
			/* ---------------------------------------- */
			File tmpFile = FileOpener.getCachedFile(entry);
			if (tmpFile != null)
			{
				FileOpener.open(tmpFile, new OpenListener(entry));
				return;
			}
			
			/* ------------------------------------------------------- */
			// load the binary data
			/* ------------------------------------------------------- */
			try
			{
				FileOpener.loadBinary(entry);
			}
			catch (FileNotFoundException e)
			{
				logger.error("Error while trying to open file entry.", e);
				HistoryTablePanel.showEntryNotOpenedDialog(HistoryTablePanel.EOF_FILE_NOT_FOUND, e, entry);
			}
			catch (EntryDeletedException e)
			{
				logger.error("Error while trying to open file entry.", e);
				HistoryTablePanel.showEntryNotOpenedDialog(HistoryTablePanel.EOF_ENTRY_NOT_FOUND, e, entry);
			}
			catch (Exception e)
			{
				logger.error("Error while trying to open file entry.", e);
				return;
			}
			
			binaryData	= entry.getBinaryContent();
			if (binaryData == null)
			{
				logger.warn("Couldn't load the file data of entry "+entry.getId()+".");
				HistoryTablePanel.showEntryNotOpenedDialog(HistoryTablePanel.EOF_DEFAULT, null, entry);
				return;
			}
			
//			if (!createTempfile())
//			{
//				logger.error("Cannot open file " + entry.getFileName());
//				return;
//			}
			filename	= entry.getFileName();
		}
		else if (binaryData == null)
		{
			logger.error("Cannot open file " + filename);
			return;
		}
		
		FileOpener.open(binaryData, filename, new OpenListener(entry));
		
		entry = null;
	}
	
	
	
	/* ======================================== */
	// CLASS: FileOpenerListener
	/* ======================================== */
	
	private static class OpenListener implements FileOpenerListener
	{
		/* ======================================== */
		// MEMBERS
		/* ======================================== */
		
		private IncidentEntry entry;
		
		
		
		/* ======================================== */
		// CONSTRUCTOR
		/* ======================================== */
		
		public OpenListener (IncidentEntry entry)
		{
			this.entry = entry;
		}
		
		
		
		/* ======================================== */
		// CLASS BODY
		/* ======================================== */
		
		public void openedSuccessfull (File file)
		{
			FileOpener.cacheFile(file, entry);
		}
		
		
		public void openingFailed (File file, String reason, Throwable cause)
		{
			FileOpener.cacheFile(null, entry);
			
			ErrorDialog.showErrorDialog(MainFrame.getInstance(), 
					Translatrix.getTranslationString("DefaultFileViewHandler.errorOpeningFileTitle"), 
					Translatrix.getTranslationString("DefaultFileViewHandler.errorOpeningFileMessage", new String[] { file.getAbsolutePath() })
					+ "\n" + reason, 
					cause);
		}
	}
}
