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

import java.io.IOException;

import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.esante.gui.dialogs.ErrorWithLinkPopup;
import lu.tudor.santec.gecamed.esante.utils.OpenOfficeException;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.IncidentEntry;
import lu.tudor.santec.gecamed.patient.ejb.session.beans.IncidentManagerBean;
import lu.tudor.santec.gecamed.patient.ejb.session.interfaces.IncidentManager;
import lu.tudor.santec.gecamed.prescription.gui.util.PrescriptionPrinter;
import lu.tudor.santec.i18n.Translatrix;
import net.sf.jasperreports.engine.JRException;

import org.apache.commons.lang3.exception.ExceptionUtils;

/**
 * 
 * Incident Manager Session Bean
 * 
 * @author martin.heinemann@tudor.lu
 * 
 * 
 * @version <br>
 *          $Log: GecamedToPdfConverterClient.java,v $
 *          Revision 1.7  2014-01-09 14:32:26  ferring
 *          *** empty log message ***
 *
 *          Revision 1.6  2014-01-03 14:46:22  ferring
 *          debug option added (outcommented)
 *
 *          Revision 1.5  2014-01-02 15:08:04  donak
 *          Implemented authentication workflow: user-saml request --> check ehr access permissions --> dsp saml request --> actual webservice request
 *          All saml assertions independent of type are cached.
 *
 *          Revision 1.4  2013-12-31 17:07:38  donak
 *          Fixed bug of eSanté Connection Kit specification
 *          Added mechanism to request mandate before final saml assertion is requested. DOES NOT WORK COMPLETELY, YET.
 *
 *          Revision 1.3  2013-12-27 18:09:26  donak
 *          Cleanup of imports
 *
 *          Revision 1.2  2013-11-14 18:17:17  donak
 *          Fixed versioning issue between JODConverter (Java 1.6) and JBOSS (Java 1.5). Server-side PDF ==> PDF/A conversion should work now.
 *          Fixed IncidentEntry getBinaryContent(). Now a call to this functions always provides the binary content of an incident entry, if any. function works on client and server side.
 *          Implemented function to update incident entry upload status w/o updating all bean properties.
 *          Fixed issue with retrieving default user inactivity logout delay from database
 *
 *          Revision 1.1  2013-11-12 12:48:23  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.
 * <br>
 *          Revision 1.0 2013-11-04 14:06:03 donak <br>
 *
 */

public class GecamedToPdfConverterClient {
	/**
	 * This calls the convert function on the server side for converting the content of the provided incident entry to pdf/a format. In case of an error, the
	 * error user dialog will be displayed and the error will be logged.
	 * 
	 * @param entry
	 *            The incident entry of which the content should be converted to pdf/a
	 * @return The incident entry content in pdf/a format or null if the content could not be converted or found.
	 */
	public static byte[] transformToPdfA(IncidentEntry entry){
		String entryType = null;
		String errorMessage = "Unable to transform the document.";
		StringBuilder errorDetails = null;
		Exception exception;
		
		try {
			IncidentManager iManager = (IncidentManager) ManagerFactory.getRemote(IncidentManagerBean.class);
			
			// prescription has first to be transformed to pdf
			if (IncidentManager.PRESCRIPTION.equals(entry.getEntryType().getName())) {
				
//				// TODO REMOVE DEBUG CODE BELOW
//				FileOutputStream fos = new FileOutputStream(new File("d:/TEMP/Prescription.pdf"));
//				byte[] data = PrescriptionPrinter.printPrescriptionToPdf(iManager.getCorrespondingPrescription(entry.getId()), true);
//				fos.write(data, 0, data.length);
//				fos.flush();
//				fos.close();

				// generate binary data (pdf) that is further down converted to pdf/a. Currently this is necessary as the current outdated version of jasper
				// report does not support direct conversion to pdf/a
				entry.setBinaryContent(PrescriptionPrinter.printPrescriptionToPdf(iManager.getCorrespondingPrescription(entry.getId()), true));
			}
			// transform the content of the incident entry on the GECAMed server. (an open office installation is needed for that)
			
			// TODO REMOVE DEBUG CODE BELOW
//			if (IncidentManager.PRESCRIPTION.equals(entry.getEntryType().getName())) {
//				
//				FileOutputStream fos = new FileOutputStream(new File("d:/TEMP/Prescription.pdf"));
//				byte[] data = iManager.transformToPdfA(entry);
//				fos.write(data, 0, data.length);
//				fos.flush();
//				fos.close();
//				return null;
//			}
			
//			return GecamedToPdfConverterServer.convert(entry, iManager);
			return iManager.transformToPdfA(entry);
		} catch (OpenOfficeException e) {
			// special case, Openoffice is not installed correctly on the server.
			exception = null;
			errorMessage = e.getMessage();
			String path = ((OpenOfficeException)e).getOpenOfficeLocation();
			ErrorWithLinkPopup.getInstance().show(
					Translatrix.getTranslationString("GecamedToPdfConverterClient.ooError.title"),
					Translatrix.getTranslationString("GecamedToPdfConverterClient.ooError.desc", new String[] {path}),
					Translatrix.getTranslationString("GecamedToPdfConverterClient.ooError.link"),
					Translatrix.getTranslationString("GecamedToPdfConverterClient.ooError.url")
					);
			
		} catch (IOException e) {
			exception = e;
			// explain the problem a little bit more in detail
			errorDetails = new StringBuilder(500).append("\n").append(e.getMessage());
			errorMessage = e.getMessage();
		} catch (JRException e) {
			exception = e;
			// explain the problem a little bit more in detail
			errorDetails = new StringBuilder(500).append("\nGeneral exception occurred during preparing and uploading the document");
		} catch (Exception e) {
			exception = e;
			errorDetails = new StringBuilder("\nAn exception occurred while converting the data to upload into a PDF/A file.");
		}
		
		if (exception != null)
		{
			// get document type and set the first character to upper case
			entryType = Character.toUpperCase(entry.getEntryType().getName().charAt(0)) + entry.getEntryType().getName().substring(1);
			
//			if (entry.getFileName() != null) {
//				errorDetails.append(" \"").append(entry.getFileName()).append("\"");
//			}
			errorDetails.append(".\nPlease analyse exception stack trace for further details:\n\n").append(ExceptionUtils.getStackTrace(exception));
	
			int patientId = ((IncidentManager) ManagerFactory.getRemote(IncidentManagerBean.class)).getIncident(entry.getIncidentId()).getPatientId();
	
			// indicate error to the user
			lu.tudor.santec.gecamed.core.gui.widgets.ErrorDialog.showESanteErrorDialog(lu.tudor.santec.gecamed.core.gui.MainFrame.getInstance(), errorMessage, errorDetails.toString(), patientId, entryType);
		}
		
		return null;
	}
}
