/*
 * Copyright (c) eHealth
 */
package be.ehealth.technicalconnector.ws;

import java.io.File;
import java.util.concurrent.TimeUnit;

import javax.activation.DataHandler;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.bouncycastle.util.encoders.Base64;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;

import be.ehealth.technicalconnector.enumeration.Charset;
import be.ehealth.technicalconnector.utils.*;
import be.ehealth.technicalconnector.ws.domain.GenericRequest;
import be.ehealth.technicalconnector.ws.domain.GenericResponse;
import be.ehealth.technicalconnector.ws.domain.TokenType;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.GetFullMessageRequest;
import be.fgov.ehealth.ehbox.consultation.protocol.v3.GetFullMessageResponse;
import be.fgov.ehealth.ehbox.core.v3.BoxIdType;
import be.fgov.ehealth.ehbox.publication.protocol.v3.*;
import be.fgov.ehealth.technicalconnector.tests.junit.rule.SessionRule;
import be.fgov.ehealth.technicalconnector.tests.utils.AssumeTools;


/**
 * Integration Test of the {@link GenericWsSender} to test SOAPWithAttachments.
 *
 * @author EHP
 */
public class GenericWsUserIntegrationTest {

    private static final String ATTACH_FILE_LOCATION = "https://www.ehealth.fgov.be/sites/default/files/assets/nl/pdf/form_revocatieaanvraag_v3_nl.pdf";

    private static final String EHBOX_PROFESSION = "DOCTOR";

    private static final String ENDPOINT_EHBOX_PUBL = "https://services-acpt.ehealth.fgov.be/ehBoxPublication/v3";

    private static final String ENDPOINT_EHBOX_CONS = "https://services-acpt.ehealth.fgov.be/ehBoxConsultation/v3";

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

    @ClassRule
    public static SessionRule rule = SessionRule.withActiveSession()
                                                .build();

    @BeforeClass
    public static void bootstrap() throws Exception {
        AssumeTools.isPersPhysician();
    }

    @Test
    public void testSwaRefSendJaxb() throws Exception {
        invokeSwaRefJaxb();
    }

    @Test
    public void testSwaRefSendDom() throws Exception {
        invokeSwaRefDom();
    }

    @Test
    public void testSwaRefConsultationJaxb() throws Exception {
        GenericResponse resp = invokeConsultation(invokeSwaRefDom());
        GetFullMessageResponse fullResp = resp.asObject(GetFullMessageResponse.class);
        DataHandler handler = fullResp.getMessage()
                                      .getContentContext()
                                      .getContent()
                                      .getDocument()
                                      .getEncryptableBinaryContent();
        File targetFile = File.createTempFile(fullResp.getMessage()
                                                      .getContentContext()
                                                      .getContent()
                                                      .getDocument()
                                                      .getDownloadFileName(), generateId());
        FileUtils.writeByteArrayToFile(targetFile, base64decoding(handler));
    }

    @Test
    public void testSwaRefConsultationDom() throws Exception {
        GenericResponse resp = invokeConsultation(invokeSwaRefDom());
        Element el = (Element) resp.asNode();
        String cid = el.getElementsByTagNameNS("*", "EncryptableBinaryContent")
                       .item(0)
                       .getTextContent();
        String downloadFileName = el.getElementsByTagNameNS("*", "DownloadFileName")
                                    .item(0)
                                    .getTextContent();
        byte[] expecteds = ConnectorIOUtils.getBytes(ConnectorIOUtils.getResourceAsStream(ATTACH_FILE_LOCATION));
        byte[] actuals = resp.getAttachment(cid);
        Assert.assertArrayEquals(expecteds, actuals);
        File targetFile = File.createTempFile(downloadFileName, "");
        targetFile.deleteOnExit();
        FileUtils.writeByteArrayToFile(targetFile, ConnectorIOUtils.base64Decode(actuals, false));
    }

    private String invokeSwaRefDom() throws Exception {
        GenericRequest request = new GenericRequest();
        String swarefRefid = "d5609f90-1bd9-11e4-8c21-0800200c9a66@ehealth.fgov.be";
        byte[] pdfBytes = ConnectorIOUtils.getBytes(ConnectorIOUtils.getResourceAsStream(ATTACH_FILE_LOCATION));
        String digest = new String(Base64.encode(ConnectorCryptoUtils.calculateDigest("SHA-256", pdfBytes)));
        request.addDataHandler(swarefRefid, pdfBytes);
        String payload = ConnectorIOUtils.toString(ConnectorIOUtils.getBytes(ConnectorIOUtils.getResourceAsStream("/examples/GenericWsUserInteregratinTest.ehbox.v3.swaref.xml")), Charset.UTF_8);
        payload = payload.replace("${user.inss}", SessionUtil.getNiss());
        payload = payload.replace("${user.profession}", EHBOX_PROFESSION);
        payload = payload.replace("${publicationid}", generateId());
        payload = payload.replace("${digest}", digest);
        request.setPayload(payload);
        return invokePublication(request);
    }

    private static String generateId() {
        return Long.toString(System.nanoTime(), Character.MAX_RADIX)
                   .toUpperCase();
    }

    private String invokeSwaRefJaxb() throws Exception {
        SendMessageRequest payload = new SendMessageRequest();
        payload.setPublicationId(generateId());
        payload.setContentContext(new ContentContextType());
        DestinationContextType addr = new DestinationContextType();
        addr.setId(SessionUtil.getNiss());
        addr.setType(IdentifierType.SSIN.getType(IdentifierType.EHBOX));
        addr.setQuality(EHBOX_PROFESSION);
        payload.getDestinationContexts()
               .add(addr);

        payload.getContentContext()
               .setContentSpecification(new ContentSpecificationType());
        payload.getContentContext()
               .getContentSpecification()
               .setApplicationName("ehealth-swaref");
        payload.getContentContext()
               .getContentSpecification()
               .setContentType("DOCUMENT");

        payload.getContentContext()
               .setContent(new PublicationContentType());
        PublicationDocumentType doc = new PublicationDocumentType();
        payload.getContentContext()
               .getContent()
               .setDocument(doc);

        byte[] pdfBytes = ConnectorIOUtils.getBytes(ConnectorIOUtils.getResourceAsStream(ATTACH_FILE_LOCATION));
        ByteArrayDatasource pdf = new ByteArrayDatasource(pdfBytes, "application/pdf");
        doc.setEncryptableBinaryContent(new DataHandler(pdf));
        doc.setTitle("form_recovatieaanvraag_v3_nl");
        doc.setMimeType(pdf.getContentType());
        doc.setDigest(new String(Base64.encode(ConnectorCryptoUtils.calculateDigest("SHA-256", pdfBytes))));
        doc.setDownloadFileName("form_recovatieaanvraag_v3_nl.pdf");

        GenericRequest request = new GenericRequest();
        request.setPayload(payload);
        return invokePublication(request);
    }

    private String invokePublication(GenericRequest request) throws Exception {
        request.setSoapAction("urn:be:fgov:ehealth:ehbox:publication:protocol:v3:sendMessage");
        request.setEndpoint(ENDPOINT_EHBOX_PUBL);
        request.setCredential(null, TokenType.SAML);
        request.setDefaultHandlerChain();
        SendMessageResponse sendMessageResponse = ServiceFactory.getGenericWsSender()
                                                                .send(request)
                                                                .asObject(SendMessageResponse.class);
        return sendMessageResponse.getId();
    }


    private GenericResponse invokeConsultation(String messageId) throws Exception {
        LOG.debug("Waiting for 30 seconds, in order to be sure that message is publised....");
        TimeUnit.SECONDS.sleep(30);

        GetFullMessageRequest fullMsgRequest = new GetFullMessageRequest();
        fullMsgRequest.setSource("INBOX");
        fullMsgRequest.setBoxId(new BoxIdType());
        fullMsgRequest.getBoxId()
                      .setId(SessionUtil.getNiss());
        fullMsgRequest.getBoxId()
                      .setType(IdentifierType.SSIN.getType(IdentifierType.EHBOX));
        fullMsgRequest.getBoxId()
                      .setQuality(EHBOX_PROFESSION);
        fullMsgRequest.setMessageId(messageId);

        GenericRequest request = new GenericRequest();
        request.setPayload(fullMsgRequest);
        request.setSoapAction("urn:be:fgov:ehealth:ehbox:consultation:protocol:v3:getFullMessage");
        request.setEndpoint(ENDPOINT_EHBOX_CONS);
        request.setCredential(null, TokenType.SAML);
        return ServiceFactory.getGenericWsSender()
                             .send(request);

    }


    private byte[] base64decoding(DataHandler dataHandler) throws Exception {
        if (dataHandler == null || dataHandler.getContent() == null) {
            return null;
        }
        IOUtils.toByteArray(dataHandler.getInputStream());
        return ConnectorIOUtils.base64Decode(ConnectorIOUtils.getBytes(dataHandler.getInputStream()), false);
    }

}
