package lu.tudor.santec.gecamed.esante.ejb.session.interfaces;

import java.util.Date;
import java.util.List;
import java.util.Set;

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.utils.exceptions.DspLinkingException;

/**
 * @author jens.ferring(at)tudor.lu
 * 
 * @version
 * <br>$Log: CDAManager.java,v $
 * <br>Revision 1.17  2014-02-18 13:17:33  ferring
 * <br>Patients with Luxembourg ID, but without DSP, are now connected to their DSP or Luxembourg ID is removed, if no DSP was found.
 * <br>If only one DSP was found in search, the compare DSP and patient dialog is shown directly.
 * <br>
 * <br>Revision 1.16  2014-02-06 17:48:40  ferring
 * <br>flag added, to decide if the document shall be stored on the server or not
 * <br>
 * <br>Revision 1.15  2014-01-21 14:32:05  ferring
 * <br>myDSP configuration can be changed and reloaded.
 * <br>The clean CDA files on server function was added
 * <br>
 * <br>Revision 1.14  2014-01-09 14:31:18  ferring
 * <br>clear CDA file methods provided
 * <br>
 * <br>Revision 1.13  2013-12-17 16:49:51  ferring
 * <br>RSQ handling changed
 * <br>
 * <br>Revision 1.12  2013-12-06 16:25:25  ferring
 * <br>CDA synch fixed
 * <br>
 * <br>Revision 1.11  2013-11-22 14:44:26  ferring
 * <br>method added to delete CDA file
 * <br>
 * <br>Revision 1.10  2013-11-18 15:37:02  ferring
 * <br>Restructured methods with SoapSender and DocumentWorker restructured.
 * <br>Checking the IPID, if it changes and refreshing the data.
 * <br>
 * <br>Revision 1.9  2013-11-05 09:47:57  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.8  2013-10-21 08:14:55  ferring
 * <br>linking and unlinking patient changed
 * <br>
 * <br>Revision 1.7  2013-10-08 12:46:48  donak
 * <br>eSant� upload dialog and logging
 * <br>
 * <br>Revision 1.6  2013-10-08 08:54:14  ferring
 * <br>class name refactoring and tree view implementation (first steps)
 * <br>
 * <br>Revision 1.5  2013-10-03 12:51:17  ferring
 * <br>eSanté logging method added
 * <br>
 * <br>Revision 1.4  2013-09-30 10:56:38  ferring
 * <br>eSante integration in GECAMed and synchronise funktion added
 * <br>
 * <br>Revision 1.3  2013-09-23 09:30:43  ferring
 * <br>eSante: saving document data in database
 * <br>
 * <br>Revision 1.2  2013-09-19 12:24:43  ferring
 * <br>eSante bugs fixed and documents stored in database
 * <br>
 * <br>Revision 1.1  2013-09-13 14:18:56  ferring
 * <br>eSante bugs fixed and database implementation started
 * <br>
 */

public interface CDAManager
{
	/**
	 * @param patientId The ID of the patient, to check the last update for
	 * @return The newest eSanteCreationDate of all documents of the referred 
	 * patient.
	 */
	public Date lastUpdated (Integer patientId);
	
//	 * This method will check, whether there is a former version of this 
//	 * document and add this as new version or simply add this as the first
//	 * version.<br>
//	 * <b>In EACH case, 
	/**
	 * <b>This creates a new entry.</b> If you want to change 
	 * an existing entry, use the {@link #changeDocument(CDADocument)} method.
	 * 
	 * @param document The CDA document to add or update.
	 * @return The stored document.
	 */
	public CdaDocument saveCdaDocument(CdaDocument update);
	
	/**
	 * Loads a cda document from database.
	 * 
	 * @param documentUid
	 *            The uid the document has in the eSanté dsp
	 * @param dspId
	 *            the id of the dsp where the document is located
	 * @return The CDA document from the database or null is no corresponding document could be found. If no document could be found, it usually means that
	 *         either a provided id is invalid or (more likely) that the document is not locally available (e.g. had been uploaded by another entity but not
	 *         downloaded by this gecamed instance).
	 */
	public CdaDocument getCdaByUid(String documentUid, Integer dspId);
	
	/**
	 * This will change an existing CDA document entry.
	 * <b>This method will in NO case create a new entry</b>. If you want
	 * to add a new document or a new version of a document, use the 
	 * {@link #addOrUpdateDocument(CDADocument)} method.
	 * 
	 * @param document The document to change.
	 * @param saveCdaFile Flag to decide, whether the document shall be 
	 * 	stored on the server, if the content is available.
	 * @return The changed document.
	 */
	public CdaDocument updateCdaDocument(CdaDocument document, boolean saveCdaFile);
	
//	/**
//	 * If the document is persistent, the persistent object will be changed,#
//	 * otherwise a new object will be stored (as update of an existing document).
//	 * 
//	 * @param document The document to store
//	 * @return The stored document
//	 */
//	public CdaDocument saveDocument (CdaDocument document);
	
	/**
	 * @param patientId The patient to get the documents of.
	 * @return A list of all CDA documents of the referred patient.
	 */
	public List<CdaDocument> getDocuments (Integer patientId);
	
	/**
	 * @param document The document to load the data of
	 * @return The CDA file bytes
	 * @throws Exception
	 */
	public byte[] loadCDAFileContent (CdaDocument document) throws Exception;
	
	/**
	 * Returns the current version of the CDA document, that belongs 
	 * to the incident entry with the given entryId.
	 * 
	 * @param entryId The incident entry ID
	 * @return The document of the specified incident entry
	 */
	public CdaDocument getDocument (Integer entryId);
	
	/**
	 * Creates the given DSP and links it with the patient set in the DSP,
	 * by adding the OID of the DSP as its Luxembourg ID.
	 * 
	 * @param dsp The DSP to link
	 */
	public Dsp linkDsp (Dsp dsp) throws DspLinkingException;
	
	/**
	 * Removes the link of the patient, defined by the patient ID (Sets the luxembourg_id to <code>null</code>),
	 * deletes the DSP itself and all CDA documents including its incident entries and files.
	 * 
	 * @param patientId The patient to unlink
	 */
	public void unlinkDsp (Integer patientId);
	
	/**
	 * Logs an erroneous soap message to the appropriate directory on the
	 * GECAMed server
	 * 
	 * @param data
	 *            The content of uploaded the (should contain not just the cda
	 *            content but the whole soap message)
	 * @param filename
	 *            The name of the file. GECAMed will normalize it if necessary.
	 *            Further it must not contain a filename extension as ".xml"
	 *            will automatically be added.
	 * @return The path to the logged message. This might differ from the
	 *         provided data as GECAMed might normalize the filename. In case of
	 *         an error, the reason is logged to the normal log file and the
	 *         method returns null.
	 */
	public String logErroneousMessage (String data, String filename);
	
	/**
	 * Logs an uploaded message file to the appropriate directory on the GECAMed
	 * server
	 * 
	 * @param data
	 *            The content of uploaded the (should contain not just the cda
	 *            content but the whole soap message)
	 * @param filename
	 *            The name of the file. GECAMed will normalize it if necessary.
	 *            Further it must not contain a filename extension as ".xml"
	 *            will automatically be added.
	 * @param patientId
	 *            The (GECAMed) id of the patient to whom this file belongs
	 * @return The path to the logged message. This might differ from the
	 *         provided data as GECAMed might normalize the filename. In case of
	 *         an error, the reason is logged to the normal log file and the
	 *         method returns null.
	 */
	public String logUploadedMessage(String data, String filename, int patientId);
	
	/**
	 * @param data The bytes to write into the file.
	 * @param filename The name of the file to store - will be extended by a time stamp to make it unique.
	 * @return The filename, where the file was saved, including the path.
	 */
	public String log (byte[] data, String filename);

	/**
	 * Saves (only) the error message set in this document.
	 * 
	 * @param document The document with a new error message to save
	 */
	public void updateError (CdaDocument document);
	
	/**
	 * Saves (only) the read flag set for this document.
	 * 
	 * @param document The document to change the read flag
	 */
	public void updateRead (CdaDocument document);
	
	public void updateDspOid (Integer dspId, Integer patientId, String dspOid);

	public Dsp getLinkedDsp (Integer patientId);
	
	public Set<String> getCdaOidSet (Integer dspId);
	
	public Long countDownloadedNotIntegratedCdaDocuments ();
	
	public List<CdaDocument> getDownloadedNotInegratedCdaDocuments (int maxCount);
	
	public CdaDocument deleteCdaFile (CdaDocument document);
}
