package be.ehealth.businessconnector.ehbox.v3.session;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.UUID;

import org.apache.commons.lang.StringUtils;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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.utils.QualityType;
import be.ehealth.businessconnector.ehbox.v3.EhboxTestUtilities;
import be.ehealth.businessconnector.ehbox.v3.builders.BuilderFactory;
import be.ehealth.businessconnector.ehbox.v3.builders.SendMessageBuilder;
import be.ehealth.technicalconnector.exception.TechnicalConnectorException;
import be.ehealth.technicalconnector.session.Session;
import be.ehealth.technicalconnector.utils.IdentifierType;
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.GetFullMessageRequest;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.GetFullMessageResponse;
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.Message;
import be.fgov.ehealth.ehbox.core.v3.BoxIdType;
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;

/**
 * eHealthBox Service Integration Tests This test shows the use of the eHealthBox Service through the use of the Business Connector.
 * 
 * The tests below use the Session Management Service to manage the session and SAML/STS token. The eHealthBox of the test user specified in
 * the business connector property file is used, these tests expect that this is set to a valid INSS of a citizen.
 * 
 * @author EHP
 * 
 */
public class EhboxV3ServicePharmacistIntegrationTest {

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

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

    private static Properties props;

    @BeforeClass
    public static void initSession() throws Exception {
        Session.getInstance().unloadSession();
        initSessionAndProps();
    }

    @AfterClass
    public static void closeSession() throws Exception {
        Session.getInstance().unloadSession();
    }

    /**
     * @throws TechnicalConnectorException
     * @throws Exception
     */
    private static void initSessionAndProps() throws TechnicalConnectorException, Exception {
        props = TestPropertiesLoader.getProperties(FILE_AS_DOC);
        SessionInitializer.init(props, true);
    }

    /**
     * @throws Exception
     */
    @Test
    public void testSendGetAndDeleteDocument() throws Exception {
        /*
         * Create the parameters of the new message
         */
        SendMessageBuilder builder = BuilderFactory.getSendMessageBuilder();

        DocumentMessage<Message> documentMsg = new DocumentMessage<Message>();
        documentMsg.setDestinations(getDestinations());
        // documentMsg.setSender(getSender());
        documentMsg.setImportant(false);

        documentMsg.setFreeText("Free text:" + UUID.randomUUID());


        Document doc = new Document();
        doc.setTitle("Document " + new Date());
        doc.setContent(EhboxV3ServicePharmacistIntegrationTest.class.getResourceAsStream(FILE_AS_DOC));
        doc.setMimeType("text/plain");
        doc.setFilename("be.ehealth.businessconnector.properties");
        documentMsg.setDocument(doc);

        SendMessageRequest request = builder.buildMessage(documentMsg);
        request.setBoxId(getdestination());
        /*
         * Invoke the business connector framework's eHealthBox's sendMessage operation
         */
        EhealthBoxServiceV3 service = ServiceFactory.getEhealthBoxServiceV3();
        SendMessageResponse response = service.sendMessage(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.getId());

        LOG.debug("Message Sent: " + response.getId());
        /*
         * Create the parameters of the new message
         */
        // set the folder (INBOX | SENTBOX | BININBOX | BINSENTBOX)
        String source = "INBOX";
        EhboxTestUtilities.waitForProcessing();
        GetMessagesListRequest listRequest = BuilderFactory.getRequestBuilder().createGetMessagesListRequest(source);
        listRequest.setBoxId(getBoxId(request));
        GetMessageListResponseType listResponse = ServiceFactory.getEhealthBoxServiceV3().getMessageList(listRequest);

        /*
         * Verify the response
         */
        // check if there are no errors
        Assert.assertEquals("100", listResponse.getStatus().getCode());
        // check if a messageId has been returned
        Assert.assertNotNull(listResponse.getMessages());
        // print out the messageId's for the given folder
        boolean found = false;
        List<String> foundMessageIds = new ArrayList<String>();

        EhboxTestUtilities.waitForProcessing();
        for (Message message : listResponse.getMessages()) {
            // JAXB.marshal(message, System.out);
            foundMessageIds.add(message.getMessageId());
            try {
                if (response.getId().equals(message.getMessageId())) {
                    GetFullMessageRequest messageRequest = new GetFullMessageRequest();
                    messageRequest.setSource(source);
                    messageRequest.setMessageId(response.getId());
                    messageRequest.setBoxId(getBoxId(request));
                    GetFullMessageResponse messageResponse = ServiceFactory.getEhealthBoxServiceV3().getFullMessage(messageRequest);

                    //
                    /*
                     * Verify the response
                     */
                    // check if there are no errors
                    Assert.assertEquals("100", messageResponse.getStatus().getCode());
                    // check if a messageId has been returned
                    Assert.assertNotNull(messageResponse.getMessage());
                    // print out the messageId's for the given folder
                    found = true;
                    break;
                }
            } catch (Exception e) {
                LOG.info("\t" + message.getMessageId());
            }
        }
        if (!found) {
            Assert.fail("message  with id " + response.getId() + " not found in list " + StringUtils.join(foundMessageIds.iterator(), ", "));
        }

        /*
         * Invoke the business connector framework's eHealthBox's getMessageList operation
         */

        DeleteMessageRequest deleteMessageRequest = BuilderFactory.getRequestBuilder().createDeleteMessageRequest(source, getdestination(), response.getId());
        // deleteMessageRequest.setBoxId(response.);
        DeleteMessageResponse deleteMessageResponse = ServiceFactory.getEhealthBoxServiceV3().deleteMessage(deleteMessageRequest);
        Assert.assertEquals("100", deleteMessageResponse.getStatus().getCode());
    }


    private List<Addressee> getDestinations() {
        List<Addressee> addresseeList = new ArrayList<Addressee>();
        addresseeList.add(getSender());
        return addresseeList;
    }

    /**
     * @param request
     * @param getFullMessageRequest
     */
    private BoxIdType getBoxId(SendMessageRequest request) {
        BoxIdType boxId = new BoxIdType();
        boxId.setId(request.getDestinationContexts().get(0).getId());
        boxId.setQuality(request.getDestinationContexts().get(0).getQuality());
        boxId.setType(request.getDestinationContexts().get(0).getType());
        return boxId;
    }

    /**
     * @return
     */
    private Addressee getSender() {
        String type = props.getProperty("test.sender.type");
        String quality = props.getProperty("test.sender.quality");

        Addressee addressee = new Addressee(type, QualityType.getInstance(quality, IdentifierType.NIHII));
        addressee.setId(props.getProperty("test.sender.id"));

        return addressee;
    }

    private BoxIdType getdestination() {
        BoxIdType sender = new BoxIdType();
        sender.setId(props.getProperty("test.destination.id"));
        sender.setQuality(props.getProperty("test.destination.quality"));
        sender.setType(props.getProperty("test.destination.type"));
        return sender;
    }


}
