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

import java.util.Properties;

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

import be.ehealth.businessconnector.ehbox.api.domain.Addressee;
import be.ehealth.businessconnector.ehbox.api.domain.Document;
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.businessconnector.ehbox.v3.session.EhealthBoxServiceV3;
import be.ehealth.businessconnector.ehbox.v3.session.ServiceFactory;
import be.ehealth.technicalconnector.exception.TechnicalConnectorException;
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.IdentifierType;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.GetFullMessageResponse;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.Message;
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;


/**
 * @author eh062
 * 
 *         Class created for JIRA EHCON-569
 */
public class MessageWithHasAnnexPropertyIntegrationTest {

    private static final String MESSAGE_TITLE = "title";

    private static final String MESSAGE_MIME_TYPE = "text/plain";

    private static final String MESSAGE_FILENAME = "test.txt";

    private static final String MESSAGE_CONTENT = "This seems to work";

    private static final String ANNEX_MIME_TYPE = "text/plain";

    private static final String ANNEX_TITLE = "annex title";

    private static final String ANNEX_FILENAME = "annex filename";

    private static final String EXPECTED_RESPONSE_CODE = "100";

    private static final String INBOX_FOLDER = "INBOX";

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

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

    @BeforeClass
    public static void setUp() throws Exception {
        Properties props = TestPropertiesLoader.getProperties(PROPERTIES_FILEPATH);
        Session.getInstance().unloadSession();
        SessionInitializer.init(props, true);
    }


    private NewsMessage<Message> createMessage() {
        Addressee destination = new Addressee(IdentifierType.SSIN);
        destination.setId(EhboxTestDataBuilder.getInssUser1());
        destination.setQuality(QualityType.DOCTOR_SSIN);

        NewsMessage<Message> message = new NewsMessage<Message>();
        message.getDocument().setTitle(MESSAGE_TITLE);
        message.getDocument().setContent(MESSAGE_CONTENT.getBytes());
        message.getDocument().setFilename(MESSAGE_FILENAME);
        message.getDocument().setMimeType(MESSAGE_MIME_TYPE);
        message.getDestinations().add(destination);
        message.setImportant(true);

        return message;
    }

    private Document createAnnex() {
        Document annex = new Document();
        annex.setFilename(ANNEX_FILENAME);
        annex.setMimeType(ANNEX_MIME_TYPE);
        annex.setTitle(ANNEX_TITLE);
        annex.setContent(MESSAGE_CONTENT.getBytes());

        return annex;
    }

    private String sendMessage(NewsMessage<Message> message) throws Exception {
        SendMessageBuilder builder = BuilderFactory.getSendMessageBuilder();
        SendMessageRequest request = builder.buildMessage(message);
        EhealthBoxServiceV3 service = ServiceFactory.getEhealthBoxServiceV3();
        SendMessageResponse response = service.sendMessage(request);

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

        return response.getId();
    }

    private NewsMessage<GetFullMessageResponse> retrieveMessageInInbox(String messageId) throws Exception {
        GetFullMessageResponse fullMessage = ServiceFactory.getEhealthBoxServiceV3().getFullMessage(BuilderFactory.getRequestBuilder().createGetFullMessageRequest(messageId, INBOX_FOLDER, EhboxTestDataBuilder.getEhboxSender()));
        Assert.assertNotNull("The messag " + messageId + "should exist", fullMessage);

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

        return (NewsMessage<GetFullMessageResponse>) retrievedFullMessage;
    }

    private void verifyInboxMessage(NewsMessage<GetFullMessageResponse> inboxMessage) throws Exception {
        String messageTitle = inboxMessage.getDocumentTitle();
        Assert.assertTrue("Message title should be \"" + MESSAGE_TITLE + "\" but was \"" + messageTitle + "\"", messageTitle.equals(MESSAGE_TITLE));
        byte[] content = inboxMessage.getDocument().getContent();
        Assert.assertNotNull(content);
        Assert.assertArrayEquals("The content of the inbox message is not the expected one: expected " + MESSAGE_CONTENT + " but was " + new String(content), content, MESSAGE_CONTENT.getBytes());
    }

    private void verifyInboxMessageAnnex(NewsMessage<GetFullMessageResponse> inboxMessage) {
        Assert.assertTrue("There should be an annex", inboxMessage.isHasAnnex());
        Assert.assertTrue("There should be only 1 annex", inboxMessage.getAnnexList().size() == 1);

        Document annex = inboxMessage.getAnnexList().get(0);

        String title = annex.getTitle();
        Assert.assertTrue("Annex title should be \"" + ANNEX_TITLE + "\" but was \"" + title + "\"", title.equals(ANNEX_TITLE));

        String mimeType = annex.getMimeType();
        Assert.assertTrue("Annex mime type should be \"" + ANNEX_MIME_TYPE + "\" but was \"" + mimeType + "\"", mimeType.equals(ANNEX_MIME_TYPE));

        String filename = annex.getFilename();
        Assert.assertTrue("Annex filename should be \"" + ANNEX_FILENAME + "\" but was \"" + filename + "\"", filename.equals(ANNEX_FILENAME));
    }

    @Test
    public void sendAndConsultNonEncryptedMessageWithoutAnnex() throws Exception {
        // 1) create the message
        NewsMessage<Message> message = this.createMessage();
        message.setEncrypted(false);

        // 2) send it and retrieve the response ID
        String messageId = this.sendMessage(message);
        Assert.assertNotNull("Message ID should not be null", messageId);

        // 3) wait a few seconds so that the system can process the message
        EhboxTestUtilities.waitForProcessing();

        // 4) retrieve the message and check that there is indeed no annex
        NewsMessage<GetFullMessageResponse> inboxMessage = this.retrieveMessageInInbox(messageId);
        Assert.assertFalse("There should not be an annex", inboxMessage.isHasAnnex());
        this.verifyInboxMessage(inboxMessage);
    }

    @Test
    public void sendAndConsultEncryptedMessageWithoutAnnex() throws Exception {
        // 1) create the message
        NewsMessage<Message> message = this.createMessage();
        message.setEncrypted(true);

        // 2) send it and retrieve the response ID
        String messageId = this.sendMessage(message);
        Assert.assertNotNull("Message ID should not be null", messageId);

        // 3) wait a few seconds so that the system can process the message
        EhboxTestUtilities.waitForProcessing();

        // 4) retrieve the message and check that there is indeed no annex
        NewsMessage<GetFullMessageResponse> inboxMessage = this.retrieveMessageInInbox(messageId);
        Assert.assertFalse("There should not be an annex", inboxMessage.isHasAnnex());
        this.verifyInboxMessage(inboxMessage);
    }

    @Test
    public void sendAndConsultNonEncryptedMessageWithAnnex() throws Exception {
        // 1) create the message
        NewsMessage<Message> message = this.createMessage();
        message.setEncrypted(false);

        // 2) create the annex and add it to the message
        message.getAnnexList().add(this.createAnnex());

        // 3) send the message and retrieve the response ID
        String messageId = this.sendMessage(message);
        Assert.assertNotNull("Message ID should not be null", messageId);

        // 4) wait a few seconds so that the system can process the message
        EhboxTestUtilities.waitForProcessing();

        // 5) retrieve the message and check that there is indeed no annex
        NewsMessage<GetFullMessageResponse> inboxMessage = this.retrieveMessageInInbox(messageId);
        this.verifyInboxMessage(inboxMessage);
        this.verifyInboxMessageAnnex(inboxMessage);
    }

    @Test
    public void sendAndConsultEncryptedMessageWithAnnex() throws Exception {
        // 1) create the message
        NewsMessage<Message> message = this.createMessage();
        message.setEncrypted(true);

        // 2) create the annex and add it to the message
        message.getAnnexList().add(this.createAnnex());

        // 3) send the message and retrieve the response ID
        String messageId = this.sendMessage(message);
        Assert.assertNotNull("Message ID should not be null", messageId);

        // 4) wait a few seconds so that the system can process the message
        EhboxTestUtilities.waitForProcessing();

        // 5) retrieve the message and check that there is indeed no annex
        NewsMessage<GetFullMessageResponse> inboxMessage = this.retrieveMessageInInbox(messageId);
        this.verifyInboxMessage(inboxMessage);
        this.verifyInboxMessageAnnex(inboxMessage);
    }

    @AfterClass
    public static void tearDown() {
        KeyDepotManagerFactory.getKeyDepotManager().setKeyDepotService(new KeyDepotServiceImpl());
        Session.getInstance().getSession().setEncryptionCredential(null);
        Session.getInstance().unloadSession();
    }

}
