/*
 * Copyright (c) Smals
 */
package be.ehealth.businessconnector.ehbox.v3;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.junit.Assert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;

import be.ehealth.businessconnector.ehbox.api.domain.Addressee;
import be.ehealth.businessconnector.ehbox.api.domain.Document;
import be.ehealth.businessconnector.ehbox.api.domain.DocumentMessage;
import be.ehealth.businessconnector.ehbox.api.domain.ErrorMessage;
import be.ehealth.businessconnector.ehbox.api.utils.QualityType;
import be.ehealth.businessconnector.ehbox.api.utils.SigningValue;
import be.ehealth.businessconnector.ehbox.v3.builders.BuilderFactory;
import be.ehealth.businessconnector.ehbox.v3.session.EhealthBoxServiceV3;
import be.ehealth.businessconnector.ehbox.v3.session.ServiceFactory;
import be.ehealth.technicalconnector.exception.ConnectorException;
import be.ehealth.technicalconnector.exception.TechnicalConnectorException;
import be.ehealth.technicalconnector.exception.UnsealConnectorException;
import be.ehealth.technicalconnector.service.keydepot.KeyDepotManagerFactory;
import be.ehealth.technicalconnector.service.keydepot.impl.KeyDepotServiceImpl;
import be.ehealth.technicalconnector.session.Session;
import be.ehealth.technicalconnector.utils.ConnectorIOUtils;
import be.ehealth.technicalconnector.utils.ConnectorXmlUtils;
import be.ehealth.technicalconnector.utils.TemplateEngineUtils;
import be.fgov.ehealth.commons.core.v1.LocalisedString;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.DeleteMessageRequest;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.DeleteMessageResponse;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.DeleteOoOResponse;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.GetAllEhboxesMessagesListResponse;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.GetBoxInfoResponse;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.GetFullMessageRequest;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.GetFullMessageResponse;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.GetMessageAcknowledgmentsStatusResponse;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.GetMessageListResponseType;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.GetMessagesListRequest;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.GetMessagesListResponse;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.GetOoOListResponse;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.Message;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.OoO;
import be.fgov.ehealth.ehbox.core.v3.BoxIdType;
import be.fgov.ehealth.ehbox.core.v3.EhboxIdentifierType;
import be.fgov.ehealth.ehbox.core.v3.SenderType;
import be.fgov.ehealth.ehbox.publication.protocol.v3.SendMessageRequest;
import be.fgov.ehealth.ehbox.publication.protocol.v3.SendMessageResponse;
import be.fgov.ehealth.technicalconnector.tests.session.SessionInitializer;
import be.fgov.ehealth.technicalconnector.tests.utils.TestPropertiesLoader;
import be.fgov.ehealth.technicalconnector.tests.utils.XmlAsserter;


/**
 * utility class to use in tests.
 *
 * @author EHP
 */
public final class EhboxTestUtilities {


    private static final Logger LOG = LoggerFactory.getLogger(EhboxTestUtilities.class);

    private static final String PROPERTIES_FILEPATH = "/be.ehealth.businessconnector.ehboxv3.test.properties";

    private static final int START = 1;

    private static final int END = 100;

    /**
     * only static methods needed.
     */
    private EhboxTestUtilities() {
        super();
    }

    /**
     * safest way to delete without exceptions. determines boxIdToUse message by message.
     *
     * @throws ConnectorException
     */
    public static void safeDeleteAllMessageOneByOne() throws ConnectorException {
        EhealthBoxServiceV3 service = be.ehealth.businessconnector.ehbox.v3.session.ServiceFactory.getEhealthBoxServiceV3();

        for (String source : EhboxTestUtilities.getListOfAllSources()) {
            GetMessageListResponseType allEhboxesMessagesList = service.getAllEhboxesMessagesList(BuilderFactory.getRequestBuilder().createAllEhboxesMessagesListRequest(source));
            for (Message message : allEhboxesMessagesList.getMessages()) {
                BoxIdType boxIdToUse = mapSender(message.getSender());
                service.deleteMessage(BuilderFactory.getRequestBuilder().createDeleteMessageRequest(source, boxIdToUse, message.getMessageId()));
            }
        }

    }

    /**
     * @param sender
     * @return
     */
    private static BoxIdType mapSender(SenderType sender) {
        if (sender != null) {
            BoxIdType boxIdType = new BoxIdType();
            boxIdType.setId(sender.getId());
            boxIdType.setQuality(sender.getQuality());
            boxIdType.setType(sender.getType());
            boxIdType.setSubType(sender.getSubType());
            return boxIdType;
        }
        return null;
    }

    public static void deleteAllMessagesForSource(String source, BoxIdType boxId) throws MalformedURLException, ConnectorException {
        EhealthBoxServiceV3 service = ServiceFactory.getEhealthBoxServiceV3();
        GetMessageListResponseType messagesList = service.getMessageList(BuilderFactory.getRequestBuilder().createGetMessagesListRequest(source, 1, 100, boxId));
        LOG.debug("deleteAllMessagesForSource : deleting first  100  messages");
        deleteMessages(source, messagesList, boxId);
        messagesList = service.getMessageList(BuilderFactory.getRequestBuilder().createGetMessagesListRequest(source, 1, 100, boxId));
        while (messagesList.getMessages().size() > 0) {
            LOG.debug("deleteAllMessagesForSource : remaining messages : " + messagesList.getMessages().size() + "  deleting next 100 messages");
            deleteMessages(source, messagesList, boxId);
            messagesList = service.getMessageList(BuilderFactory.getRequestBuilder().createGetMessagesListRequest(source, 1, 100, boxId));
        }

    }


    /**
     * @param source
     * @param allEhboxesMessagesList
     * @param boxId                  the ehealthbox to use
     * @throws ConnectorException
     */
    private static void deleteMessages(String source, GetMessageListResponseType allEhboxesMessagesList, BoxIdType boxId) throws ConnectorException {
        Set<String> messageIdsToDelete = new HashSet<String>();
        LOG.debug("deleteMessages : deleting following messages");
        for (Message messageToDelete : allEhboxesMessagesList.getMessages()) {
            messageIdsToDelete.add(messageToDelete.getMessageId());
            logMessage(messageToDelete);
        }
        deleteMessages(source, messageIdsToDelete, boxId);
    }

    /**
     * @param source
     * @param messageIdsToDelete
     * @param boxId              the ehealthbox to use
     * @return
     * @throws ConnectorException
     */
    private static void deleteMessages(String source, Set<String> messageIdsToDelete, BoxIdType boxId) throws ConnectorException {
        if (messageIdsToDelete.isEmpty()) {
            return;
        }
        String[] messageIdsToDeleteArray = messageIdsToDelete.toArray(new String[]{});
        DeleteMessageResponse deleteMessages = deleteMessages(source, messageIdsToDeleteArray);
        Assert.assertTrue("100".equals(deleteMessages.getStatus().getCode()));
    }

    public static DeleteMessageResponse deleteMessages(String source, String... messageIds) throws ConnectorException {
        DeleteMessageRequest request = BuilderFactory.getRequestBuilder().createDeleteMessageRequest(source, messageIds);
        EhealthBoxServiceV3 service = be.ehealth.businessconnector.ehbox.v3.session.ServiceFactory.getEhealthBoxServiceV3();
        DeleteMessageResponse response = service.deleteMessage(request);
        Assert.assertTrue("100".equals(response.getStatus().getCode()));
        return response;
    }

    public static DeleteMessageResponse deleteMessages(String source, BoxIdType boxId, String... messageIds) throws ConnectorException {
        DeleteMessageRequest request = BuilderFactory.getRequestBuilder().createDeleteMessageRequest(source, boxId, messageIds);
        EhealthBoxServiceV3 service = be.ehealth.businessconnector.ehbox.v3.session.ServiceFactory.getEhealthBoxServiceV3();
        DeleteMessageResponse response = service.deleteMessage(request);
        Assert.assertTrue("100".equals(response.getStatus().getCode()));
        return response;
    }

    /**
     * @param message
     */
    public static void logMessage(Message message) {
        StringBuilder sb = new StringBuilder();
        logMessage(message, sb);
        LOG.debug(sb.toString());
    }

    /**
     * compares a jaxb object with the expected xml.
     *
     * @param fileLocation the file location of the expected xml file.
     * @param jaxbObject   jaxbObject
     * @throws IOException
     * @throws SAXException
     * @throws TechnicalConnectorException
     */
    public static void compareXmlWithExpectedFile(String fileLocation, Object jaxbObject) throws SAXException, IOException, TechnicalConnectorException {
        Properties props = TestPropertiesLoader.getProperties(PROPERTIES_FILEPATH);
        Map<String, Object> ctx = new HashMap<String, Object>();
        ctx.put("senderId",props.getProperty("test.sender.id"));
        String expected = TemplateEngineUtils.generate(ctx, fileLocation);
        String actualXml = ConnectorXmlUtils.toString(jaxbObject);
        XmlAsserter.assertSimilar(expected, actualXml);

    }

    /**
     * @param buildFullMessage
     */
    public static void logFullMessage(be.ehealth.businessconnector.ehbox.api.domain.Message<GetFullMessageResponse> message) {
        StringBuilder sb = new StringBuilder("logging message :\n");
        sb.append("\n  message.getPublicationDateTime():").append(message.getPublicationDateTime()).append("\n");
        sb.append("\n  message.getPublicationId():").append(message.getPublicationId()).append("\n");
        sb.append("\n  message.getSender():").append(message.getSender()).append("\n");
        GetFullMessageResponse original = message.getOriginal();
        sb.append("\n  original.getId():").append(original.getId()).append("\n");
        sb.append("\n  original.getStatus().getCode():").append(original.getStatus().getCode()).append("\n");
        for (LocalisedString localisedString : original.getStatus().getMessages()) {
            sb.append("\n  original.getStatus().getMessages().localisedString.getValue();:").append(localisedString.getValue()).append("\n");
        }

        sb.append("\n  original.getMessageInfo().getPublicationDate():").append(original.getMessageInfo().getPublicationDate()).append("\n");
        LOG.debug("logFullMessage : " + sb.toString());
    }

    public static void logStackTrace(Throwable e) {
        StackTraceElement[] stackTrace = e.getStackTrace();
        StringBuilder sb = new StringBuilder();
        sb.append(e.getMessage()).append("\n");
        for (StackTraceElement stackTraceElement : stackTrace) {
            sb.append(stackTraceElement.getClassName()).append(".").append(stackTraceElement.getMethodName());
            sb.append(":").append(stackTraceElement.getLineNumber()).append("\n");
        }
        LOG.debug("logStackTrace : \n" + sb.toString());
    }

    /**
     * @param source
     * @throws MalformedURLException
     * @throws TechnicalConnectorException
     * @throws EhboxBusinessConnectorException
     * @throws BusinessError
     * @throws SystemError
     */
    public static void showMessagesFromSource(String source) throws Exception {
        GetMessageListResponseType response = EhboxTestUtilities.retrieveMessageFromSourceAndCheckStatus(source);
        // print out the messageId's for the given folder
        List<Message> list = response.getMessages();
        StringBuilder errorDetailMessagesStringBuilder = new StringBuilder();
        Boolean errorsFound = false;
        errorDetailMessagesStringBuilder.append("showMessagesFromSource " + source + ": number of messages: " + list.size());
        for (Message message : list) {
            try {

                be.ehealth.businessconnector.ehbox.api.domain.Message<Message> msg = BuilderFactory.getConsultationMessageBuilder().buildMessage(message);
                if (msg instanceof ErrorMessage<?>) {
                    errorsFound = true;
                    ErrorMessage<Message> errorMessage = (ErrorMessage<Message>) msg;
                    GetFullMessageResponse fullMessage = EhboxTestUtilities.getFullMessage(source, errorMessage.getId());
                    be.ehealth.businessconnector.ehbox.api.domain.Message<GetFullMessageResponse> buildFullMessage = BuilderFactory.getConsultationMessageBuilder().buildFullMessage(fullMessage);
                    EhboxTestUtilities.appendErrorDescription(buildFullMessage, errorDetailMessagesStringBuilder);
                }

            } catch (Exception e) {
                LOG.info("\t exception " + e.getMessage() + " for message with id " + message.getMessageId());
                LOG.error("showMessagesFromSource : error occured , log till now : " + errorDetailMessagesStringBuilder.toString());
                Assert.fail("exception occured : " + e.getMessage());
            }
            logMessage(message, errorDetailMessagesStringBuilder);

        }
        if (errorsFound) {
            LOG.debug("testShowAllErrorMessagesForInbox : ERRORS FOUND :");
        } else {
            LOG.debug("testShowAllErrorMessagesForInbox : No error messages");
        }
        LOG.debug(errorDetailMessagesStringBuilder.toString());
    }

    /**
     * @param message
     * @param errorDetailMessagesStringBuilder
     */
    private static void logMessage(Message message, StringBuilder sb) {
        String title = message.getContentInfo() == null ? "NO CONTENTINFO TO RETRIEVE TITLE" : message.getContentInfo().getTitle();
        sb.append(" message  title :").append(title).append(" , messageType ").append(message.getClass().getCanonicalName()).append(" , id: ").append(message.getMessageId()).append(" publication date : ").append(message.getMessageInfo().getPublicationDate());
    }


    /**
     * @param buildFullMessage
     * @param sb
     */
    public static void appendErrorDescription(be.ehealth.businessconnector.ehbox.api.domain.Message<GetFullMessageResponse> buildFullMessage, StringBuilder sb) {
        if (buildFullMessage instanceof ErrorMessage<?>) {
            ErrorMessage<?> errorMessage = (ErrorMessage<?>) buildFullMessage;
            sb.append("error : code =").append(errorMessage.getErrorCode()).append("  ");
            for (String errorMessageString : errorMessage.getErrorMsg()) {
                sb.append("[").append(errorMessageString).append("] ");
            }
            sb.append("\n");
        } else {
            Assert.fail("logError called on non error object : error in test setup");
        }

    }

    /**
     * @param source
     * @return
     * @throws MalformedURLException
     * @throws TechnicalConnectorException
     * @throws EhboxBusinessConnectorException
     * @throws BusinessError
     * @throws SystemError
     */
    public static GetMessageListResponseType retrieveMessageFromSourceAndCheckStatus(String source) throws Exception {
        GetMessagesListRequest request = new GetMessagesListRequest();
        request.setSource(source);


        /*
         * Invoke the business connector framework's eHealthBox's getMessageList operation
         */
        EhealthBoxServiceV3 service = ServiceFactory.getEhealthBoxServiceV3();
        GetMessageListResponseType response = service.getMessageList(request);

        /*
         * Verify the response
         */
        // check if there are no errors
        Assert.assertEquals("100", response.getStatus().getCode());
        // check if a messageId has been returned
        Assert.assertNotNull(response.getMessages());
        return response;
    }

    /**
     * @param source
     * @param fullMessageId
     * @return
     * @throws MalformedURLException
     * @throws TechnicalConnectorException
     * @throws EhboxBusinessConnectorException
     * @throws BusinessError
     * @throws SystemError
     */
    public static GetFullMessageResponse getFullMessage(String source, String fullMessageId) throws Exception {
        EhealthBoxServiceV3 service = ServiceFactory.getEhealthBoxServiceV3();
        GetFullMessageRequest request = new GetFullMessageRequest();
        // set the messageId, use the messageId of the message that has been sent in testSendMessage
        // request.setMessageId(shortMessage.getMessageId());
        request.setMessageId(fullMessageId);
        request.setSource(source);

        /*
         * Invoke the business connector framework's eHealthBox's getFullMessage operation
         */
        EhboxTestUtilities.waitForProcessing();
        GetFullMessageResponse response = service.getFullMessage(request);
        return response;
    }


    /**
     * @param boxId  the ehealthbox to use
     * @param string
     * @throws ConnectorException
     */
    public static void deleteAllOutOfOfficesForCurrentUser(BoxIdType boxId) throws ConnectorException {
        EhealthBoxServiceV3 service = ServiceFactory.getEhealthBoxServiceV3();
        GetOoOListResponse ooOList = service.getOoOList(BuilderFactory.getRequestBuilder().createGetOoOListRequest(boxId));
        List<String> oOoIdList = new ArrayList<String>();
        for (OoO oOo : ooOList.getOoOs()) {
            oOoIdList.add(oOo.getOoOId());
            LOG.debug("deleteAllOutOfOfficesForCurrentUser : adding delete id for oOo" + oOoToString(oOo));
        }
        if (!oOoIdList.isEmpty()) {
            DeleteOoOResponse deleteOoOResponse = service.deleteOoO(BuilderFactory.getRequestBuilder().createDeleteOoORequest(boxId, oOoIdList));
            Assert.assertEquals("delete oo should have succeeded", "100", deleteOoOResponse.getStatus().getCode());
        } else {
            LOG.debug("deleteAllOutOfOfficesForCurrentUser : no Out off offices found");
        }
    }


    /**
     * @param oOo
     * @return
     */
    private static String oOoToString(OoO oOo) {
        StringBuilder sb = new StringBuilder();
        sb.append("[ id:)").append(oOo.getOoOId());
        sb.append("StartDate").append(oOo.getStartDate());
        sb.append("EndDate").append(oOo.getEndDate());
        for (BoxIdType boxId : oOo.getSubstitutes()) {
            sb.append(" boxId:(").append(boxIdToString(boxId)).append(")");
        }
        return sb.toString();
    }


    /**
     * @param boxId
     * @return
     */
    private static Object boxIdToString(BoxIdType boxId) {
        StringBuilder sb = new StringBuilder();
        sb.append(" [").append("id:").append(boxId.getId());
        sb.append(", quality:").append(boxId.getQuality());
        sb.append(", type:").append(boxId.getType());
        sb.append(", subType:").append(boxId.getSubType());
        sb.append("]");
        return sb.toString();
    }


    /**
     * @param sendDocument
     * @return
     * @throws UnsealConnectorException
     */
    public static String documentToString(Document doc) throws UnsealConnectorException {
        StringBuilder sb = new StringBuilder();
        sb.append("Document[");
        sb.append(",fileName:").append(doc.getFilename());
        sb.append(",title:").append(doc.getTitle());
        sb.append(",mimeType:").append(doc.getMimeType());
        sb.append(", signing:").append(signingToString(doc.getSigning()));
        if (doc.getContent() != null && doc.getContent().length > 0) {
            sb.append("content : \n").append(new String(doc.getContent())).append("\n");
        } else {
            sb.append("\n no content\n");
        }
        sb.append("]");

        return sb.toString();
    }


    /**
     * @param signing
     * @return
     */
    private static Object signingToString(SigningValue signing) {
        StringBuilder sb = new StringBuilder();
        sb.append("SigningValue[");
        if (signing != null) {
            sb.append("downLoadFileName:").append(signing.getSigningDownloadFileName());
            sb.append(" ,signingType:").append(signing.getSigningType());
        }
        sb.append("]");
        return sb.toString();
    }


    /**
     * @param boxId
     * @return
     */
    public static Addressee mapBoxIdTypeToAddressee(BoxIdType boxId) {
        if (boxId == null) {
            return null;
        }
        // we only use a small subset of qualities
        QualityType type = null;
        if ("DOCTOR".equals(boxId.getQuality())) {
            if ("NIHII".equals(boxId.getType())) {
                type = QualityType.DOCTOR_NIHII;
            } else if ("INSS".equals(boxId.getType())) {
                type = QualityType.DOCTOR_SSIN;
            }
        }
        if ("PHARMACY".equals(boxId.getQuality())) {
            if ("NIHII".equals(boxId.getType())) {
                type = QualityType.PHARMACY_NIHII;
            } else {
                throw new IllegalArgumentException("combination in boxId of " + boxId.getQuality() + " and " + boxId.getType() + " not supported : for PHARMACY only NIHII is allowed");
            }
        }
        if (type == null) {
            throw new UnsupportedOperationException("test mapping for this combination not provided : complete the method mapBoxIdTypeToAddressee in class " + EhboxTestUtilities.class.getCanonicalName());
        }
        return new Addressee(boxId.getId(), type);
    }


    /**
     * @return
     */
    public static List<String> getListOfAllSources() {
        List<String> sources = new ArrayList<String>();
        sources.add("INBOX");
        sources.add("SENTBOX");
        sources.add("BININBOX");
        sources.add("BINSENTBOX");
        return sources;
    }


    /**
     * @param destination
     * @return
     */
    public static BoxIdType mapDestinationToBoxIdType(EhboxIdentifierType destination) {
        BoxIdType boxIdType = new BoxIdType();
        boxIdType.setId(destination.getId());
        boxIdType.setQuality(destination.getQuality());
        boxIdType.setSubType(destination.getSubType());
        boxIdType.setType(destination.getType());
        return boxIdType;
    }

    /**
     * checks properties to see if these are tests for persphysician.
     *
     * @param testConfigProperties
     * @return
     */
    public static boolean isDoctorTest(Properties testConfigProperties) {
        return "persphysician".equals(testConfigProperties.getProperty("session.professionType"));
    }

    /**
     * checks properties to see if these are tests for persphysician.
     *
     * @param testConfigPropertiesFile
     * @return
     * @throws TechnicalConnectorException
     */
    public static boolean isDoctorTest(String testConfigPropertiesFile) throws TechnicalConnectorException {
        return isDoctorTest(TestPropertiesLoader.getProperties(testConfigPropertiesFile));
    }

    /**
     * checks properties to see if these are tests for persphysician.
     *
     * @param testConfigPropertiesFile
     * @return
     * @throws TechnicalConnectorException
     */
    public static boolean isDoctorTest() throws TechnicalConnectorException {
        return isDoctorTest(TestPropertiesLoader.getProperties(PROPERTIES_FILEPATH));
    }


    public static void waitForProcessing() {
        waitForProcessing(500);
    }

    public static void waitForProcessing(int waitPeriodInMilliSeconds) {
        LOG.debug("sleep " + waitPeriodInMilliSeconds + " milliseconds to allow ehbox to process the message");
        try {
            Thread.sleep(waitPeriodInMilliSeconds);
        } catch (InterruptedException e) {
            // just go on
        }
    }

    /**
     * creates and initializes the session for using test configuration file (properties)
     *
     * @throws Exception
     */
    public static void createSession() throws Exception {
        Properties props = TestPropertiesLoader.getProperties(PROPERTIES_FILEPATH);
        Session.getInstance().unloadSession();
        SessionInitializer.init(props);
    }

    /**
     * destroys the session if any exists
     */
    public static void destroySession() {
        KeyDepotManagerFactory.getKeyDepotManager().setKeyDepotService(new KeyDepotServiceImpl());
        Session.getInstance().getSession().setEncryptionCredential(null);
        Session.getInstance().unloadSession();
    }

    /**
     * prepares the send request message (true form of the message that will be sent)
     *
     * @param message
     * @return
     * @throws Exception
     */
    public static SendMessageRequest prepareSendRequest(DocumentMessage<Message> message) throws Exception {
        return BuilderFactory.getSendMessageBuilder().buildMessage(message);
    }

    /**
     * sends the given send request
     *
     * @param request
     * @return
     * @throws Exception
     */
    public static SendMessageResponse sendMessage(SendMessageRequest request) throws Exception {
        return ServiceFactory.getEhealthBoxServiceV3().sendMessage(request);
    }

    /**
     * tells if the given messageID is in the all ehboxes list of message retrieved from the given source of the given boxID
     *
     * @param messageId
     * @param source
     * @param boxId
     * @return
     * @throws Exception
     */
    public static boolean isMessageInAllEhBoxesList(String messageId, String source, BoxIdType boxId) throws Exception {
        GetAllEhboxesMessagesListResponse list = ServiceFactory.getEhealthBoxServiceV3().getAllEhboxesMessagesList(BuilderFactory.getRequestBuilder().createAllEhboxesMessagesListRequest(source));
        for (Message message : list.getMessages()) {
            if (message.getMessageId().equals(messageId)) {
                return true;
            }
        }
        return false;
    }

    /**
     * verifies if the given messageID is in the list of message retrieved from the given source of the given boxID
     *
     * @param messageId
     * @param source
     * @param boxId
     * @return
     * @throws Exception
     */
    public static boolean isMessageInList(String messageId, String source, BoxIdType boxId) throws Exception {
        GetMessagesListResponse list = ServiceFactory.getEhealthBoxServiceV3().getMessageList(BuilderFactory.getRequestBuilder().createGetMessagesListRequest(source, START, END, boxId));
        for (Message inboxMessage : list.getMessages()) {
            if (inboxMessage.getMessageId().equals(messageId)) {
                return true;
            }
        }

        return false;
    }

    /**
     * verifies if the given messageID is in the list retrieved from the given source of the current boxID the current boxID is the one of
     * whoever is authenticated through the session
     *
     * @param messageId
     * @param source
     * @return
     * @throws Exception
     */
    public static boolean isMessageInList(String messageId, String source) throws Exception {
        GetMessagesListResponse list = ServiceFactory.getEhealthBoxServiceV3().getMessageList(BuilderFactory.getRequestBuilder().createGetMessagesListRequest(source));
        for (Message inboxMessage : list.getMessages()) {
            if (inboxMessage.getMessageId().equals(messageId)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Retrieves the full message corresponding to the given messageID from the given source of the given boxID
     *
     * @param messageId
     * @param source
     * @param boxId
     * @return
     * @throws Exception
     */
    public static GetFullMessageResponse getFullMessage(String messageId, String source, BoxIdType boxId) throws Exception {
        return ServiceFactory.getEhealthBoxServiceV3().getFullMessage(BuilderFactory.getRequestBuilder().createGetFullMessageRequest(messageId, source, boxId));
    }

    /**
     * Retrieves the information related to the given boxID
     *
     * @param boxId
     * @return
     * @throws Exception
     */
    public static GetBoxInfoResponse getBoxInfo(BoxIdType boxId) throws Exception {
        return ServiceFactory.getEhealthBoxServiceV3().getBoxInfo(BuilderFactory.getRequestBuilder().createBoxInfoRequest(boxId));
    }

    /**
     * Retrieves the acknowledgements of the message corresponding to the messageID from the given source of the given boxID
     *
     * @param messageId
     * @param boxId
     * @return
     * @throws Exception
     */
    public static GetMessageAcknowledgmentsStatusResponse getMessageAcknowledgements(String messageId, BoxIdType boxId) throws Exception {
        return ServiceFactory.getEhealthBoxServiceV3().getMessageAcknowledgmentsStatusRequest(BuilderFactory.getRequestBuilder().createGetMessageAcknowledgmentsStatusRequest(messageId, START, END, boxId));
    }

}
