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.bouncycastle.util.encoders.Base64;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
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.domain.NewsMessage;
import be.ehealth.businessconnector.ehbox.api.utils.QualityType;
import be.ehealth.businessconnector.ehbox.v3.EhboxTestDataBuilder;
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.session.Session;
import be.ehealth.technicalconnector.utils.IdentifierType;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.Message;
import be.fgov.ehealth.ehbox.core.v3.CustomMetaType;
import be.fgov.ehealth.ehbox.publication.protocol.v3.DestinationContextType;
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 EhboxV3ServicePublicationIntegrationTest {

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

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

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

    @BeforeClass
    public static void initSession() throws Exception {
        Properties props = TestPropertiesLoader.getProperties(TEST_PROPERTIES_FILE);
        SessionInitializer.init(props, true);
    }


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

    /**
     * Test the sendMessage operation from the eHealthBox Service through the use of the Business Connector. This test creates and sends a
     * message to a predefined eHealthBox, based on a person's INSS
     * 
     * The following main steps are done: - Create the parameters of the new message - Invoke the business connector - Verify the response
     * 
     * @throws Exception
     */
    @Test
    public void testSendNewsEncryptedMessage() throws Exception {
        try {
            /*
             * Create the parameters of the new message
             */
            SendMessageBuilder builder = BuilderFactory.getSendMessageBuilder();


            NewsMessage<Message> news = new NewsMessage<Message>();
            news.getDocument().setTitle("Encrypted news " + new Date());
            news.getDocument().setContent("eureka".getBytes());
            news.getDocument().setFilename("test.txt");
            news.setDestinations(getDestination());
            news.setImportant(true);
            news.setEncrypted(true);

            SendMessageRequest request = builder.buildMessage(news);

            CustomMetaType type = new CustomMetaType();
            type.setValue("");
            type.setKey("");


            /*
             * 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());
        } catch (Exception e) {
            EhboxTestUtilities.logStackTrace(e);
            Assert.fail(e.getMessage());
        }
    }

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


        NewsMessage<Message> news = new NewsMessage<Message>();
        news.getDocument().setTitle("News " + new Date());
        news.getDocument().setContent("eureka".getBytes());
        news.getDocument().setFilename("test.txt");

        news.setDestinations(getDestination());
        news.setImportant(true);
        news.setEncrypted(false);

        SendMessageRequest request = builder.buildMessage(news);


        LOG.debug(request.getContentContext().getContent().getDocument().getDigest());
        LOG.debug(new String(Base64.decode(request.getContentContext().getContent().getDocument().getDigest())));
        /*
         * 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());

    }

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

        DocumentMessage<Message> documentMsg = new DocumentMessage<Message>();
        documentMsg.setDestinations(getDestination());
        documentMsg.setImportant(false);
        documentMsg.setEncrypted(true);

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

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

        Document annex = new Document();
        annex.setTitle("properties");
        annex.setContent(EhboxV3ServicePublicationIntegrationTest.class.getResourceAsStream(FILE_AS_DOC));
        annex.setFilename("be.ehealth.technicalconnector.properties");
        annex.setMimeType("text/plain");
        documentMsg.getAnnexList().add(annex);

        SendMessageRequest request = builder.buildMessage(documentMsg);
        /*
         * 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());


    }

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

        DocumentMessage<Message> documentMsg = new DocumentMessage<Message>();
        documentMsg.setDestinations(getDestination());
        documentMsg.setImportant(false);

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


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

        Document annex = new Document();
        annex.setTitle("properties");
        annex.setContent(EhboxV3ServicePublicationIntegrationTest.class.getResourceAsStream(FILE_AS_DOC));
        annex.setFilename("be.ehealth.technicalconnector.properties");
        annex.setMimeType("text/plain");
        documentMsg.getAnnexList().add(annex);
        documentMsg.setEncrypted(true);

        SendMessageRequest request = builder.buildMessage(documentMsg);
        /*
         * 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());


    }

    private List<Addressee> getDestination() {
        List<Addressee> addresseeList = new ArrayList<Addressee>();
        Addressee addressee = new Addressee(IdentifierType.NIHII_HOSPITAL);
        addressee.setId("71089914");
        addressee.setQuality(QualityType.HOSPITAL_NIHII);
        // addressee.setApplicationId(applicationId)
        addresseeList.add(addressee);

        return addresseeList;
    }

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

        DocumentMessage<Message> documentMsg = new DocumentMessage<Message>();
        documentMsg.setDestinations(getDestination());
        documentMsg.setImportant(false);

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

        Document doc = new Document();
        doc.setTitle(documentMsg.getPublicationId() + " Döé\"'(§è!çà)-ument   |; ¢¾ñ");
        doc.setContent(EhboxV3ServicePublicationIntegrationTest.class.getResourceAsStream(FILE_AS_DOC));
        doc.setMimeType("text/plain");
        doc.setFilename("be.ehealth.businessconnector.properties");
        documentMsg.setDocument(doc);

        Document annex = new Document();
        annex.setTitle("properties");
        annex.setContent(new byte[]{});
        annex.setFilename("be.ehealth.technicalconnector.properties");
        annex.setMimeType("text/plain");
        documentMsg.getAnnexList().add(annex);

        SendMessageRequest request = builder.buildMessage(documentMsg);

        /*
         * 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());

    }


    @Test
    public void testCreateMassMailingRequest() throws Exception {
        DocumentMessage<Message> buildFullExampleDocumentMessage = EhboxTestDataBuilder.buildFullExampleDocumentMessage(true, true);
        buildFullExampleDocumentMessage.getDestinations().clear();
        buildFullExampleDocumentMessage.getDestinations().add(EhboxTestDataBuilder.getAdresseeAllDoctors());

        SendMessageRequest result = BuilderFactory.getSendMessageBuilder().buildMessage(buildFullExampleDocumentMessage);
        boolean destinationContextAllFound = false;
        for (DestinationContextType destination : result.getDestinationContexts()) {
            if (destination.getId().equals("ALL")) {
                destinationContextAllFound = true;
            }
        }
        Assert.assertTrue(destinationContextAllFound);
    }

}
