/*
 * Copyright (c) eHealth
 */
package be.ehealth.businessconnector.dmg.builders;

import java.io.File;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.joda.time.DateTime;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import be.ehealth.businessconnector.dmg.domain.DmgBuilderResponse;
import be.ehealth.technicalconnector.config.ConfigFactory;
import be.ehealth.technicalconnector.exception.TechnicalConnectorException;
import be.ehealth.technicalconnector.service.etee.CertificateChecker;
import be.ehealth.technicalconnector.session.Session;
import be.ehealth.technicalconnector.utils.ConnectorIOUtils;
import be.ehealth.technicalconnector.utils.MarshallerHelper;
import be.fgov.ehealth.globalmedicalfile.protocol.v1.ConsultGlobalMedicalFileResponse;
import be.fgov.ehealth.globalmedicalfile.protocol.v1.NotifyGlobalMedicalFileResponse;
import be.fgov.ehealth.messageservices.core.v1.RetrieveTransactionResponse;
import be.fgov.ehealth.messageservices.core.v1.SendTransactionResponse;
import be.fgov.ehealth.technicalconnector.signature.domain.SignatureVerificationError;
import be.fgov.ehealth.technicalconnector.signature.domain.SignatureVerificationResult;
import be.fgov.ehealth.technicalconnector.tests.session.SessionInitializer;


/**
 * tests the ResponseObjectBuilder.
 * 
 * @author EHP
 * 
 */
public class ResponseObjectBuilderTest {


    /**
     * {@link CertificateChecker} that internally 'validates' the certificate.
     * 
     * @author EHP
     */
    public static class CertificateCheckerDummy implements CertificateChecker {

        @Override
        public boolean isCertificateRevoked(File certFile) throws TechnicalConnectorException {
            return false;
        }

        @Override
        public boolean isCertificateRevoked(File certFile, DateTime validOn) throws TechnicalConnectorException {
            return false;
        }

        @Override
        public boolean isCertificateRevoked(X509Certificate cert, DateTime validOn) throws TechnicalConnectorException {
            return false;
        }

        @Override
        public boolean isCertificateRevoked(X509Certificate cert) throws TechnicalConnectorException {
            return false;
        }

        @Override
        public boolean isValidCertificateChain(List<X509Certificate> certificateChain) throws TechnicalConnectorException {
            return true;
        }


    }

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


    @BeforeClass
    public static void init() throws Exception {
        SessionInitializer.init("/be.ehealth.businessconnector.dmg.test.properties", false);
        ConfigFactory.getConfigValidator().setProperty("crypto.certificatechecker.classname", CertificateCheckerDummy.class.getName());
    }

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

    @Test
    public void testMockResponseConsultGlobalMedicalFileResponse() throws Exception {
        MarshallerHelper<ConsultGlobalMedicalFileResponse, ConsultGlobalMedicalFileResponse> helper = new MarshallerHelper<ConsultGlobalMedicalFileResponse, ConsultGlobalMedicalFileResponse>(ConsultGlobalMedicalFileResponse.class, ConsultGlobalMedicalFileResponse.class);

        ConsultGlobalMedicalFileResponse actualResponse = helper.toObject(ConnectorIOUtils.getResourceAsStream("/examples/mock.consult.response.xml"));

        DmgBuilderResponse response = ResponseObjectBuilderFactory.getResponseObjectBuilder().handleSendResponseType(actualResponse);

        Map<String, Object> result = response.getResult();
        Set<String> keyset = result.keySet();

        for (String key : keyset) {
            LOG.debug(key + ":" + result.get(key));
        }
        Assert.assertNotNull(result.get(DmgBuilderResponse.RESULT_AS_BYTE));
        Object responseObject = result.get(DmgBuilderResponse.RESULT_AS_OBJ_RETRIEVE);
        Assert.assertNotNull(responseObject);
        if (responseObject instanceof IllegalArgumentException) {
            IllegalArgumentException e = (IllegalArgumentException) responseObject;
            Assert.fail("error while retrieving response : " + e.getMessage());
        }
        Assert.assertTrue(responseObject instanceof RetrieveTransactionResponse);
        Assert.assertNotNull(result.get(DmgBuilderResponse.RESULT_EHEALTH_STATUS));
        Assert.assertNotNull(result.get(DmgBuilderResponse.RESULT_HAS_SIGNATURE));
        Assert.assertNotNull(result.get(DmgBuilderResponse.RESULT_ORGINAL));
        Assert.assertNull(result.get(DmgBuilderResponse.RESULT_SIGINATURE_VERIFICATION));
        Assert.assertEquals("200", result.get(DmgBuilderResponse.RESULT_EHEALTH_STATUS));
        Assert.assertEquals(false, result.get(DmgBuilderResponse.RESULT_HAS_SIGNATURE));
    }

    @Test
    public void testMockResponseNotifyGlobalMedicalFileResponse() throws Exception {
        MarshallerHelper<NotifyGlobalMedicalFileResponse, NotifyGlobalMedicalFileResponse> helper = new MarshallerHelper<NotifyGlobalMedicalFileResponse, NotifyGlobalMedicalFileResponse>(NotifyGlobalMedicalFileResponse.class, NotifyGlobalMedicalFileResponse.class);

        NotifyGlobalMedicalFileResponse actualResponse = helper.toObject(ConnectorIOUtils.getResourceAsStream("/examples/mock.notify.response.expiredcertificate.xml"));

        DmgBuilderResponse response = ResponseObjectBuilderFactory.getResponseObjectBuilder().handleSendResponseType(actualResponse);

        Map<String, Object> result = response.getResult();
        Set<String> keyset = result.keySet();

        for (String key : keyset) {
            LOG.debug(key + ":" + result.get(key));
        }
        Assert.assertNotNull(result.get(DmgBuilderResponse.RESULT_AS_BYTE));
        Object responseObject = result.get(DmgBuilderResponse.RESULT_AS_OBJ_SEND);
        Assert.assertNotNull(responseObject);
        if (responseObject instanceof IllegalArgumentException) {
            IllegalArgumentException e = (IllegalArgumentException) responseObject;
            Assert.fail("error while retrieving response : " + e.getMessage());
        }
        Assert.assertTrue(responseObject instanceof SendTransactionResponse);
        Assert.assertNotNull(result.get(DmgBuilderResponse.RESULT_EHEALTH_STATUS));
        Assert.assertNotNull(result.get(DmgBuilderResponse.RESULT_HAS_SIGNATURE));
        Assert.assertNotNull(result.get(DmgBuilderResponse.RESULT_ORGINAL));
        Assert.assertNotNull(result.get(DmgBuilderResponse.RESULT_SIGINATURE_VERIFICATION));
        Assert.assertEquals("200", result.get(DmgBuilderResponse.RESULT_EHEALTH_STATUS));
        Assert.assertEquals(true, result.get(DmgBuilderResponse.RESULT_HAS_SIGNATURE));

        SignatureVerificationResult verificationResult = (SignatureVerificationResult) result.get(DmgBuilderResponse.RESULT_SIGINATURE_VERIFICATION);
        // xml has an expired certificate
        Assert.assertEquals(false, verificationResult.isValid());
        Assert.assertEquals(1, verificationResult.getErrors().size());
        SignatureVerificationError error = verificationResult.getErrors().iterator().next();
        Assert.assertEquals("Error indicating that signing certificate is expired.", error.getMessage());


    }

}
