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

import org.hamcrest.CoreMatchers;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;

import be.ehealth.businessconnector.ehbox.api.domain.Addressee;
import be.ehealth.businessconnector.ehbox.api.domain.DocumentMessage;
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.MessageBuilder;
import be.ehealth.businessconnector.ehbox.v3.builders.BuilderFactory;
import be.ehealth.businessconnector.ehbox.v3.session.ServiceFactory;
import be.ehealth.technicalconnector.exception.TechnicalConnectorException;
import be.ehealth.technicalconnector.utils.IdentifierType;
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.Message;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.MoveMessageResponse;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.Row;
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;


/**
 * @author eh062
 */
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class SendingFullOptionsEncryptedMessageToInstitutionIntegrationTest {

    private static final String MESSAGE_TITLE = "Scenario 2";

    private static final String MESSAGE_CONTENT = "message test connector scenario 2";

    private static final String MESSAGE_DESTINATION_ID = "0809394427";

    private static final String MESSAGE_DESTINATION_ID_TYPE = "CBE";

    private static final String MESSAGE_DESTINATION_QUALITY = "INSTITUTION";

    private static final String MESSAGE_ANNEX_TITLE = "Annex.pdf";

    private static final String MESSAGE_ANNEX_MIME_TYPE = "application/pdf";

    private static final String MESSAGE_ANNEX_CONTENT = "annex connector scenario 2";

    private static final String MESSAGE_FREE_TEXT = "Free information test scenario 2";

    private static final String MESSAGE_CUSTOM_META_KEY = "CustomMeta";

    private static final String MESSAGE_CUSTOM_META_VALUE = "[Connector]";

    private static final String EXPECTED_RESPONSE_CODE = "100";

    private static final String INBOX = "INBOX";

    private static final String BININBOX = "BININBOX";

    private static final String SENTBOX = "SENTBOX";

    private static final BoxIdType BOX_ID = EhboxTestDataBuilder.generateBoxId(MESSAGE_DESTINATION_ID, MESSAGE_DESTINATION_ID_TYPE, MESSAGE_DESTINATION_QUALITY);

    private static String currentMessageId;

    /*************************************/
    /*                                   */
    /* JUNIT METHODS */
    /*                                   */
    /*************************************/

    @BeforeClass
    public static void checkSenderIsDoctor() throws TechnicalConnectorException {
        Assume.assumeTrue(EhboxTestUtilities.isDoctorTest());
    }

    @BeforeClass
    public static void setUp() throws Exception {
        EhboxTestUtilities.createSession();
    }

    @AfterClass
    public static void tearDown() {
        EhboxTestUtilities.destroySession();
    }

    /*************************************/
    /*                                   */
    /* TEST METHODS */
    /*                                   */
    /*************************************/

    private SendMessageRequest prepareAndVerifySendMessageRequest(DocumentMessage<Message> message) throws Exception {
        SendMessageRequest request = EhboxTestUtilities.prepareSendRequest(message);

        Assert.assertTrue("There should be a receipt on the publication set", request.getContentContext().getContentSpecification().isPublicationReceipt());
        Assert.assertTrue("There should be a receipt on the read set", request.getContentContext().getContentSpecification().isReadReceipt());
        Assert.assertTrue("There should be a receipt on the reception set", request.getContentContext().getContentSpecification().isReceivedReceipt());

        return request;
    }

    @Test
    public void testStep1sendEcryptedFullOptionMessageFromDoctorToInstitution() throws Exception {
        final Addressee destination = EhboxTestDataBuilder.generateDestination(MESSAGE_DESTINATION_ID, IdentifierType.CBE, QualityType.INSTITUTION_CBE);
        MessageBuilder builder = MessageBuilder.create(destination, MESSAGE_CONTENT).title(MESSAGE_TITLE).encrypted(true).important(true).receiveAck(true).publicationAck(true).readAck(true);
        DocumentMessage<Message> message = EhboxTestDataBuilder.generateDocumentMessage(builder);


        message.getAnnexList().add(EhboxTestDataBuilder.generateDocument(MESSAGE_ANNEX_TITLE, MESSAGE_ANNEX_MIME_TYPE, MESSAGE_ANNEX_CONTENT));

        message.setFreeText(MESSAGE_FREE_TEXT);

        message.getCustomMetas().put(MESSAGE_CUSTOM_META_KEY, MESSAGE_CUSTOM_META_VALUE);

        SendMessageRequest request = this.prepareAndVerifySendMessageRequest(message);
        SendMessageResponse response = EhboxTestUtilities.sendMessage(request);

        Assert.assertEquals(EXPECTED_RESPONSE_CODE, response.getStatus().getCode());

        currentMessageId = response.getId();
        Assert.assertNotNull("Message ID should not be null", currentMessageId);

        EhboxTestUtilities.waitForProcessing();
    }

    @Test
    public void testStep2verifyAcknowledgments() throws Exception {
        GetMessageAcknowledgmentsStatusResponse acks = EhboxTestUtilities.getMessageAcknowledgements(currentMessageId, EhboxTestDataBuilder.getEhboxSender());

        for (Row currentAcknowledgementsStatus : acks.getAcknowledgmentsStatus().getRows()) {
            Assert.assertNull("The message should not have been read yet", currentAcknowledgementsStatus.getRead());
            Assert.assertNull("The message not should have been received", currentAcknowledgementsStatus.getReceived());
        }
    }

    @Test
    public void testStep3checkIfMessageIsInList() throws Exception {
        Assert.assertTrue("The message with id " + currentMessageId + " should be in the list", EhboxTestUtilities.isMessageInList(currentMessageId, INBOX, BOX_ID));
    }

    @Test
    public void testStep4checkIfMessageIsInAllEhBoxesMessagesList() throws Exception {
        Assert.assertTrue("The message with id " + currentMessageId + " should be in the list", EhboxTestUtilities.isMessageInAllEhBoxesList(currentMessageId, INBOX, BOX_ID));
    }

    @Test
    public void testStep5verifyFullMessage() throws Exception {
        GetFullMessageResponse fullMessage = EhboxTestUtilities.getFullMessage(currentMessageId, INBOX, BOX_ID);

        be.ehealth.businessconnector.ehbox.api.domain.Message<GetFullMessageResponse> retrievedFullMessage = BuilderFactory.getConsultationMessageBuilder().buildFullMessage(fullMessage);
        Assert.assertThat("The message " + currentMessageId + " should be of type DocumentMessage", retrievedFullMessage, CoreMatchers.instanceOf(DocumentMessage.class));

        DocumentMessage<GetFullMessageResponse> inboxMessage = (DocumentMessage<GetFullMessageResponse>) retrievedFullMessage;

        String messageTitle = inboxMessage.getDocumentTitle();
        Assert.assertTrue("Message title should be \"" + MESSAGE_TITLE + "\" but was \"" + messageTitle + "\"", messageTitle.equals(MESSAGE_TITLE));
        Assert.assertTrue("The content of the inbox message is not the expected one", org.bouncycastle.util.Arrays.areEqual(inboxMessage.getDocument().getContent(), MESSAGE_CONTENT.getBytes()));
        Assert.assertTrue("The message should be encrypted", inboxMessage.isEncrypted());
        Assert.assertTrue("The message should be important", inboxMessage.isImportant());
        Assert.assertTrue("The message should have an annex", inboxMessage.isHasAnnex());
        Assert.assertTrue("The message should have 1 annex", inboxMessage.getAnnexList().size() == 1);
        Assert.assertTrue("The message should have some free information", inboxMessage.isHasFreeInformations());
        Assert.assertTrue("The message should have a custom metadata", inboxMessage.getCustomMetas().size() == 1);

        String annexTitle = inboxMessage.getAnnexList().get(0).getTitle();
        Assert.assertTrue("The message annex title should be \"" + MESSAGE_ANNEX_TITLE + "\" but was \"" + annexTitle + "\"", MESSAGE_ANNEX_TITLE.equals(annexTitle));

        String customMeta = inboxMessage.getCustomMetas().get(MESSAGE_CUSTOM_META_KEY);
        Assert.assertTrue("The message custom metadata should be \"" + MESSAGE_CUSTOM_META_VALUE + "\" but was \"" + customMeta + "\"", MESSAGE_CUSTOM_META_VALUE.equals(customMeta));
    }

    @Test
    public void testStep6moveMessage() throws Exception {
        MoveMessageResponse response = ServiceFactory.getEhealthBoxServiceV3().moveMessage(BuilderFactory.getRequestBuilder().createMoveMessageRequest(INBOX, BININBOX, BOX_ID, currentMessageId));
        Assert.assertTrue("The message should have been moved", EXPECTED_RESPONSE_CODE.equals(response.getStatus().getCode()));
    }

    @Test
    public void testStep7deleteMessage() throws Exception {
        EhboxTestUtilities.deleteMessages(BININBOX, BOX_ID, currentMessageId);
        EhboxTestUtilities.deleteMessages(SENTBOX, EhboxTestDataBuilder.getEhboxSender(), currentMessageId);
    }

}
