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

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

import org.bouncycastle.cms.CMSException;
import org.bouncycastle.util.Arrays;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.unitils.UnitilsJUnit4TestClassRunner;

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.exception.EhboxBusinessConnectorException;
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.ConnectorException;
import be.ehealth.technicalconnector.exception.TechnicalConnectorException;
import be.ehealth.technicalconnector.exception.UnsealConnectorException;
import be.ehealth.technicalconnector.idgenerator.IdGeneratorFactory;
import be.ehealth.technicalconnector.session.Session;
import be.ehealth.technicalconnector.utils.ConnectorIOUtils;
import be.ehealth.technicalconnector.utils.IdentifierType;
import be.fgov.ehealth.commons.core.v1.LocalisedString;
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.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;


/**
 * tests problem with endoding of content and special characters. all encoding should remain in UTF-8
 * 
 * @author EHP
 * 
 */
@RunWith(UnitilsJUnit4TestClassRunner.class)
public class ContentEncodingIntegrationTest {

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

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


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

    private static final String FILE_WITH_SPECIAL_CHARS_UTF_8 = "/examples/specialCharactersUtf8Encoded.txt";

    private static final String FILE_WITH_SPECIAL_CHARS_NOT_UTF_8 = "/examples/specialCharactersNotUtf8Encoded.txt";

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


    /**
     * @throws Exception
     */
    @Test
    public void testSendDocumentWithAnnexDocumentContentInUtf8() throws Exception {

        executeTestWithSpecialCharacters(true);

    }

    /**
     * @throws Exception
     */
    @Test
    public void testSendDocumentWithAnnexDocumentContentNotInUtf8() throws Exception {

        executeTestWithSpecialCharacters(false);

    }

    /**
     * @param testFile
     * @throws TechnicalConnectorException
     * @throws IOException
     * @throws EhboxBusinessConnectorException
     * @throws CMSException
     * @throws ConnectorException
     * @throws InterruptedException
     * @throws UnsealConnectorException
     */
    private void executeTestWithSpecialCharacters(boolean fileIsUtf8) throws TechnicalConnectorException, IOException, EhboxBusinessConnectorException, CMSException, ConnectorException, InterruptedException, UnsealConnectorException {
        /*
         * Create the parameters of the new message
         */

        String testFile;
        if (fileIsUtf8) {
            testFile = FILE_WITH_SPECIAL_CHARS_UTF_8;
        } else {
            testFile = FILE_WITH_SPECIAL_CHARS_NOT_UTF_8;
        }
        SendMessageBuilder builder = BuilderFactory.getSendMessageBuilder();

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

        documentMsg.setFreeText("freeé@èçà:" + UUID.randomUUID());
        documentMsg.setPatientInss(EhboxTestDataBuilder.getInssUser1());
        documentMsg.setId(IdGeneratorFactory.getIdGenerator().generateId());


        Document doc = new Document();
        doc.setTitle("tîtleé@èçà " + new Date());
        doc.setContent(ContentEncodingIntegrationTest.class.getResourceAsStream(testFile));
        doc.setMimeType("text/plain");
        doc.setFilename("ébè@");
        documentMsg.setDocument(doc);

        Document annex = new Document();
        annex.setTitle("tîtleé@èçà");
        annex.setContent(ContentEncodingIntegrationTest.class.getResourceAsStream(testFile));
        annex.setFilename("ébè@");
        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());
        for (LocalisedString localisedString : response.getStatus().getMessages()) {
            LOG.debug("statusMessage" + localisedString.getValue());
        }
        Assert.assertTrue(response.getStatus().getMessages().size() == 1);
        Assert.assertEquals(response.getStatus().getMessages().get(0).getValue(), "SUCCESS");
        EhboxTestUtilities.waitForProcessing();
        GetFullMessageRequest getFullMessageRequest = BuilderFactory.getRequestBuilder().createGetFullMessageRequest(response.getId());
        setBoxId(request, getFullMessageRequest);
        GetFullMessageResponse fullMessageResponse = service.getFullMessage(getFullMessageRequest);
        be.ehealth.businessconnector.ehbox.api.domain.Message<GetFullMessageResponse> fullMessage = BuilderFactory.getConsultationMessageBuilder().buildFullMessage(fullMessageResponse);
        EhboxTestUtilities.logFullMessage(fullMessage);
        LOG.debug("testSendDocumentWithAnnex : ");
        Assert.assertNotNull("fullMessage.getMessage() is null", fullMessage);
        Assert.assertTrue(fullMessage instanceof DocumentMessage);
        DocumentMessage<GetFullMessageResponse> fullDocumentMessage = (DocumentMessage<GetFullMessageResponse>) fullMessage;
        Assert.assertEquals(doc.getFilename(), fullDocumentMessage.getDocument().getFilename());
        Assert.assertEquals(doc.getTitle(), fullDocumentMessage.getDocumentTitle());
        byte[] contentFromOriginalDoc = doc.getContent();
        byte[] encryptableTextContent = fullDocumentMessage.getDocument().getContent();
        byte[] utf8Bytes = ConnectorIOUtils.getBytes(ContentEncodingIntegrationTest.class.getResourceAsStream(FILE_WITH_SPECIAL_CHARS_UTF_8));
        if (!fileIsUtf8) {
            Assert.assertFalse("output not equal to utf 8", Arrays.areEqual(utf8Bytes, encryptableTextContent));
        } else {
            Assert.assertTrue("output not should be equal to utf 8", Arrays.areEqual(utf8Bytes, encryptableTextContent));
        }
        Assert.assertTrue("input and output should be equal", Arrays.areEqual(contentFromOriginalDoc, encryptableTextContent));
        Assert.assertNotNull(fullDocumentMessage.getAnnexList());
        Document retrievedAnnex = fullDocumentMessage.getAnnexList().get(0);
        Assert.assertNotNull(retrievedAnnex);
        Assert.assertEquals(annex.getFilename(), retrievedAnnex.getFilename());
        Assert.assertEquals(annex.getTitle(), retrievedAnnex.getTitle());
        Assert.assertTrue(Arrays.areEqual(annex.getContent(), retrievedAnnex.getContent()));
    }

    /**
     * Returns the destination
     * 
     * @return
     */
    private List<Addressee> getDestination() {
        List<Addressee> addresseeList = new ArrayList<Addressee>();
        Addressee addressee = new Addressee(IdentifierType.SSIN);
        addressee.setId(EhboxTestDataBuilder.getInssUser1());
        addressee.setQuality(QualityType.DOCTOR_SSIN);
        addresseeList.add(addressee);

        return addresseeList;
    }

    /**
     * @param request
     * @param getFullMessageRequest
     */
    private void setBoxId(SendMessageRequest request, GetFullMessageRequest getFullMessageRequest) {
        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());
        getFullMessageRequest.setBoxId(boxId);
    }


}
