/*
 * Copyright (c) eHealth
 */
package be.ehealth.businessconnector.therlink.mappers;

import java.io.InputStream;

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

import be.ehealth.business.common.domain.Patient;
import be.ehealth.businessconnector.therlink.builders.ProofBuilder;
import be.ehealth.businessconnector.therlink.builders.RequestObjectBuilder;
import be.ehealth.businessconnector.therlink.builders.RequestObjectBuilderFactory;
import be.ehealth.businessconnector.therlink.domain.HcParty;
import be.ehealth.businessconnector.therlink.domain.Proof;
import be.ehealth.businessconnector.therlink.domain.TherapeuticLink;
import be.ehealth.businessconnector.therlink.domain.requests.GetTherapeuticLinkRequest;
import be.ehealth.businessconnector.therlink.domain.requests.PutTherapeuticLinkRequest;
import be.ehealth.businessconnector.therlink.domain.requests.RevokeTherapeuticLinkRequest;
import be.ehealth.businessconnector.therlink.domain.requests.TherapeuticLinkStatus;
import be.ehealth.businessconnector.therlink.exception.TherLinkBusinessConnectorException;
import be.ehealth.technicalconnector.config.ConfigFactory;
import be.ehealth.technicalconnector.config.ConfigValidator;
import be.ehealth.technicalconnector.idgenerator.IdGeneratorFactory;
import be.ehealth.technicalconnector.session.Session;
import be.ehealth.technicalconnector.utils.ConnectorIOUtils;
import be.fgov.ehealth.technicalconnector.tests.session.SessionInitializer;
import be.fgov.ehealth.technicalconnector.tests.utils.TestPropertiesLoader;
import be.fgov.ehealth.technicalconnector.tests.utils.XmlAsserter;


/**
 * Unit test {@link RequestObjectMapper}
 * 
 * @author EHP
 * 
 */
public class RequestObjectMapperTest {

    private static final String THERLINK_TYPE = "gpconsultation";

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

    private static ConfigValidator configValidator;


    @BeforeClass
    public static void init() throws Exception {
        // only integration tests need to run for all professionTypes
        Assume.assumeTrue("persphysician".equals(TestPropertiesLoader.getProperties("/be.ehealth.businessconnector.therlink.test.properties").getProperty("session.professionType")));
        SessionInitializer.init("/be.ehealth.businessconnector.therlink.test.properties", false);
        IdGeneratorFactory.invalidateCachedInstance();
        configValidator = ConfigFactory.getConfigValidator();
        configValidator.setProperty("user.firstname", "");
        configValidator.setProperty("user.lastname", "");
        configValidator.setProperty("user.inss", "82051234978");
        configValidator.setProperty("user.nihii", "19996351001");
    }

    @Test
    public void testMapPutTherapeuticLinkRequest() throws Exception {
        // Building and mapping request
        Patient patient = createPatient();
        HcParty concernedHealthCareProfessionel = createHcParty();
        RequestObjectBuilder requestObjectBuilder = RequestObjectBuilderFactory.getRequestObjectBuilder();
        ProofBuilder proofBuilder = RequestObjectBuilderFactory.getProofBuilder();

        PutTherapeuticLinkRequest request = requestObjectBuilder.createPutTherapeuticLinkRequest(null, patient, concernedHealthCareProfessionel, THERLINK_TYPE, null, proofBuilder.createProofForEidReading());
        String actual = MapperFactory.getRequestObjectMapper().mapPutTherapeuticLinkToXML(request);

        // Loading file
        InputStream xmlFile = ConnectorIOUtils.getResourceAsStream("/examples/requests/putTherapeuticLink.xml");
        String expected = new String(ConnectorIOUtils.getBytes(xmlFile));
        XmlAsserter.assertSimilar(expected, actual);
    }

    private HcParty createHcParty() throws TherLinkBusinessConnectorException {
        return new HcParty.Builder().withNihii("16601747004").withInss("67060405711").withType("persphysician").build();
    }

    private Patient createPatient() throws TherLinkBusinessConnectorException {
        return new Patient.Builder().withInss("82110533949").withFamilyName("Patient family name").withFirstName("Patient first name").withEid("591490945802").build();
    }

    @Test
    public void testMapRevokeTherapeuticLinkRequest() throws Exception {
        // Building and mapping request
        Patient patient = createPatient();
        HcParty concernedHealthCareProfessionel = createHcParty();
        RequestObjectMapper requestObjectMapper = MapperFactory.getRequestObjectMapper();
        RequestObjectBuilder requestObjectBuilder = RequestObjectBuilderFactory.getRequestObjectBuilder();

        RevokeTherapeuticLinkRequest request = requestObjectBuilder.createRevokeTherapeuticLinkRequest(new DateTime(2012, 8, 10, 0, 0, 0, 0), new DateTime(2012, 8, 10, 0, 0, 0, 0), patient, concernedHealthCareProfessionel, THERLINK_TYPE, null, (Proof) null);

        String actual = requestObjectMapper.mapRevokeTherapeuticLinkToXML(request);

        // Loading file
        InputStream xmlFile = ConnectorIOUtils.getResourceAsStream("/examples/requests/revokeTherapeuticLink.xml");
        String expected = new String(ConnectorIOUtils.getBytes(xmlFile));
        XmlAsserter.assertSimilar(expected, actual);
    }

    /**
     * @throws Exception
     */
    @Test
    public void testMapGetTherapeuticLinkRequest() throws Exception {
        // Building and mapping request
        Patient patient = createPatient();
        TherapeuticLink query = createTherapeuticLink(patient);
        RequestObjectBuilder requestObjectBuilder = RequestObjectBuilderFactory.getRequestObjectBuilder();
        RequestObjectMapper requestObjectMapper = MapperFactory.getRequestObjectMapper();
        GetTherapeuticLinkRequest request = requestObjectBuilder.createGetTherapeuticLinkRequest(query, 999, (Proof[]) null);
        String actual = requestObjectMapper.mapGetTherapeuticLinkToXml(request);

        // Loading file
        InputStream xmlFile = ConnectorIOUtils.getResourceAsStream("/examples/requests/getTherapeuticLink.xml");
        String expected = new String(ConnectorIOUtils.getBytes(xmlFile));

        LOG.debug(actual);
        XmlAsserter.assertSimilar(expected, actual);
    }

    /**
     * @throws Exception
     */
    @Test
    public void testErrorECHON1162ClassCastExceptionWhenPatientHasNoFirstOrLastName() throws Exception {
        // Building and mapping request
        Patient patient = createPatient();
        patient.setFirstName(null);
        patient.setLastName(null);
        TherapeuticLink query = createTherapeuticLink(patient);
        RequestObjectBuilder requestObjectBuilder = RequestObjectBuilderFactory.getRequestObjectBuilder();
        RequestObjectMapper requestObjectMapper = MapperFactory.getRequestObjectMapper();
        GetTherapeuticLinkRequest request = requestObjectBuilder.createGetTherapeuticLinkRequest(query, 999, (Proof[]) null);
        String actual = requestObjectMapper.mapGetTherapeuticLinkToXml(request);

        // Loading file
        InputStream xmlFile = ConnectorIOUtils.getResourceAsStream("/examples/requests/getTherapeuticLinkWithoutPatientName.xml");
        String expected = new String(ConnectorIOUtils.getBytes(xmlFile));

        LOG.debug(actual);
        XmlAsserter.assertSimilar(expected, actual);
    }

    /**
     * @param patient
     * @return
     */
    private TherapeuticLink createTherapeuticLink(Patient patient) {
        TherapeuticLink query = new TherapeuticLink.Builder().withPatient(patient).withStatus(TherapeuticLinkStatus.ALL).build();
        return query;
    }

    @AfterClass
    public static void tearDown() {
        IdGeneratorFactory.invalidateCachedInstance();
        ConfigFactory.invalidate();
        Session.getInstance().unloadSession();
    }


}
