/*
 * Copyright (c) eHealth
 */
package be.ehealth.business.kmehrcommons;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;

import org.apache.commons.lang.StringUtils;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import be.ehealth.business.kmehrcommons.builders.HcPartyBuilder;
import be.ehealth.technicalconnector.config.ConfigFactory;
import be.ehealth.technicalconnector.exception.TechnicalConnectorException;
import be.ehealth.technicalconnector.session.Session;
import be.ehealth.technicalconnector.utils.ConnectorIOUtils;
import be.ehealth.technicalconnector.utils.ConnectorXmlUtils;
import be.fgov.ehealth.standards.kmehr.cd.v1.CDHCPARTY;
import be.fgov.ehealth.standards.kmehr.cd.v1.CDHCPARTYschemes;
import be.fgov.ehealth.standards.kmehr.id.v1.IDHCPARTY;
import be.fgov.ehealth.standards.kmehr.id.v1.IDHCPARTYschemes;
import be.fgov.ehealth.standards.kmehr.id.v1.IDKMEHR;
import be.fgov.ehealth.standards.kmehr.schema.v1.AuthorType;
import be.fgov.ehealth.standards.kmehr.schema.v1.HcpartyType;
import be.fgov.ehealth.technicalconnector.tests.session.SessionInitializer;
import be.fgov.ehealth.technicalconnector.tests.utils.XmlAsserter;


/**
 * Used to test HcPartyUtil
 * 
 * @author EHP
 * 
 */

public class HcPartyUtilsTest {

    private static Properties props;

    @BeforeClass
    public static void init() throws Exception {
        SessionInitializer.init("/be.ehealth.businessconnector.kmehrcommons.test.properties", false);


        props = new Properties();
        props.load(ConnectorIOUtils.getResourceAsStream("/be.ehealth.businessconnector.kmehrcommons.test.properties"));

        for (Object key : props.keySet()) {
            if (key.toString().startsWith("kmehr")) {
                ConfigFactory.getConfigValidator().setProperty(key.toString(), props.getProperty(key.toString()));
            }
        }
    }

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

    @Test
    public void testHcPartyBuilderInssFromSession() throws Exception {
        HcPartyBuilder builder = new HcPartyBuilder();
        builder.idFromSessionNiss("1.0");

        // // To pass the final validation
        builder.localCd("x", "1.1", "sl");

        HcpartyType hcparty = builder.build();
        Assert.assertEquals(1, hcparty.getIds().size());
    }

    @Test
    public void testHcPartyBuilderNihiiFromSession() throws Exception {
        HcPartyBuilder builder = new HcPartyBuilder();
        builder.idFromSessionNihii("1.0");

        // To pass the final validation
        builder.localCd("x", "1.1", "sl");

        HcpartyType hcparty = builder.build();
        Assert.assertEquals(1, hcparty.getIds().size());
    }

    @Test
    public void testFull() throws Exception {
        List<String> expectedResult = new ArrayList<String>();
        expectedResult.add("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><HcpartyType xmlns=\"http://www.ehealth.fgov.be/standards/kmehr/schema/v1\" xmlns:ns2=\"http://www.ehealth.fgov.be/standards/kmehr/schema/v1\"><ns2:id SV=\"1.0\" S=\"ID-HCPARTY\">71071801</ns2:id><ns2:cd SV=\"1.1\" S=\"CD-HCPARTY\">orghospital</ns2:cd><ns2:name>Hôpital civil de Charleroi</ns2:name></HcpartyType>");
        expectedResult.add("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><HcpartyType xmlns=\"http://www.ehealth.fgov.be/standards/kmehr/schema/v1\" xmlns:ns2=\"http://www.ehealth.fgov.be/standards/kmehr/schema/v1\"><ns2:cd SV=\"1.1\" S=\"CD-HCPARTY\">application</ns2:cd><ns2:name>application name</ns2:name></HcpartyType>");
        expectedResult.add("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><HcpartyType xmlns=\"http://www.ehealth.fgov.be/standards/kmehr/schema/v1\" xmlns:ns2=\"http://www.ehealth.fgov.be/standards/kmehr/schema/v1\"><ns2:cd SV=\"1.1\" S=\"CD-HCPARTY\">deptgynecology</ns2:cd></HcpartyType>");
        expectedResult.add("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><HcpartyType xmlns=\"http://www.ehealth.fgov.be/standards/kmehr/schema/v1\" xmlns:ns2=\"http://www.ehealth.fgov.be/standards/kmehr/schema/v1\"><ns2:id SV=\"1.0\" S=\"ID-HCPARTY\">10082555045</ns2:id><ns2:id SV=\"1.0\" S=\"INSS\">52020845721</ns2:id><ns2:cd SV=\"1.1\" S=\"CD-HCPARTY\">persphysician</ns2:cd><ns2:firstname>Jan</ns2:firstname><ns2:familyname>Modaal</ns2:familyname></HcpartyType>");
        expectedResult.add("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><HcpartyType xmlns=\"http://www.ehealth.fgov.be/standards/kmehr/schema/v1\" xmlns:ns2=\"http://www.ehealth.fgov.be/standards/kmehr/id/v1\"><id SV=\"1.0\" S=\"ID-HCPARTY\">59120729443</id><cd SV=\"1.1\" S=\"CD-HCPARTY\">persadministrative</cd><firstname>Jeanne</firstname><familyname>Dupont</familyname><address><cd SV=\"1.0\" S=\"CD-ADDRESS\">careaddress</cd><country><cd SV=\"1.0\" S=\"CD-COUNTRY\">Belgium</cd></country><zip>4680</zip><nis>21004</nis><city>Oupeye</city><district>test</district><street>rue werihet</street><postboxnumber>a</postboxnumber></address></HcpartyType>");
        baseTest("testfull", expectedResult);

    }

    @Test
    public void testRetrieveMainAuthorIdReturnsValue() throws Exception {
        Assert.assertFalse(StringUtils.isEmpty(HcPartyUtil.retrieveMainAuthorId("default")));
    }

    @Test(expected = TechnicalConnectorException.class)
    public void testNullList() throws Exception {

        List<String> expectedResult = new ArrayList<String>();
        baseTest("testnulllist", expectedResult);

    }

    @Test(expected = TechnicalConnectorException.class)
    public void testMissingParty() throws Exception {
        List<String> expectedResult = new ArrayList<String>();
        baseTest("testmissingparty", expectedResult);

    }

    @Test
    public void testUseDefault() throws Exception {
        List<String> expectedResult = new ArrayList<String>();
        expectedResult.add("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><HcpartyType xmlns=\"http://www.ehealth.fgov.be/standards/kmehr/schema/v1\" xmlns:ns2=\"http://www.ehealth.fgov.be/standards/kmehr/schema/v1\"><ns2:id SL=\"application_ID\" SV=\"1.0\" S=\"LOCAL\">1990000332</ns2:id><ns2:cd SV=\"1.1\" S=\"CD-HCPARTY\">application</ns2:cd><ns2:name>Physician software name</ns2:name></HcpartyType>");
        baseTest("testusedefault", expectedResult);

    }

    @Test
    public void testByDefault() throws Exception {
        List<String> expectedResult = new ArrayList<String>();
        expectedResult.add("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><HcpartyType xmlns=\"http://www.ehealth.fgov.be/standards/kmehr/schema/v1\" xmlns:ns2=\"http://www.ehealth.fgov.be/standards/kmehr/schema/v1\"><ns2:id SL=\"application_ID\" SV=\"1.0\" S=\"LOCAL\">1990000332</ns2:id><ns2:cd SV=\"1.1\" S=\"CD-HCPARTY\">application</ns2:cd><ns2:name>Physician software name</ns2:name></HcpartyType>");
        baseTest("testbydefault", expectedResult);

    }

    @Test(expected = TechnicalConnectorException.class)
    public void testMissingCd() throws Exception {
        List<String> expectedResult = new ArrayList<String>();
        baseTest("testmissingcd", expectedResult);

    }

    @Test(expected = TechnicalConnectorException.class)
    public void testBadLocalSingleNo1Type() throws Exception {
        List<String> expectedResult = new ArrayList<String>();
        baseTest("testbadlocalsingleno1type", expectedResult);
    }

    @Test(expected = TechnicalConnectorException.class)
    public void testBadLocalSingleNo1Value() throws Exception {
        List<String> expectedResult = new ArrayList<String>();
        baseTest("testbadlocalsingleno1value", expectedResult);
    }

    @Test
    public void testPhysician() throws Exception {
        List<String> expectedResult = new ArrayList<String>();
        expectedResult.add("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><HcpartyType  xmlns=\"http://www.ehealth.fgov.be/standards/kmehr/schema/v1\" xmlns:ns2=\"http://www.ehealth.fgov.be/standards/kmehr/schema/v1\"><ns2:id SL=\"application_ID\" SV=\"1.0\" S=\"LOCAL\">1990000332</ns2:id><ns2:cd SV=\"1.1\" S=\"CD-HCPARTY\">application</ns2:cd><ns2:name>Physician software name</ns2:name></HcpartyType>");
        expectedResult.add("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><HcpartyType xmlns=\"http://www.ehealth.fgov.be/standards/kmehr/schema/v1\" xmlns:ns2=\"http://www.ehealth.fgov.be/standards/kmehr/schema/v1\"><ns2:id SV=\"1.0\" S=\"ID-HCPARTY\">10998315001</ns2:id><ns2:id SV=\"1.0\" S=\"INSS\">52020845721</ns2:id><ns2:cd SV=\"1.1\" S=\"CD-HCPARTY\">persphysician</ns2:cd></HcpartyType>");
        baseTest("testphys", expectedResult);
    }


    private void baseTest(String projectName, List<String> expectedResult) throws Exception {
        List<HcpartyType> results = HcPartyUtil.createAuthorHcParties(projectName);

        Assert.assertEquals(expectedResult.size(), results.size());

        for (HcpartyType hcparty : results) {
            String actualXml = ConnectorXmlUtils.flatten(new String(ConnectorXmlUtils.toByteArray(hcparty), "UTF-8"));
            boolean expected = false;
            for (String expectedXml : expectedResult) {
                if (XmlAsserter.isSimilar(expectedXml, actualXml)) {
                    expected = true;
                }
            }
            Assert.assertTrue(expected);
        }
    }

    // SPECIFIED TEST

    @Test
    public void testMethodGetAuthorKmehrQuality() throws Exception {
        String authorKmehrQuality = HcPartyUtil.getAuthorKmehrQuality();
        Assert.assertEquals("persphysician", authorKmehrQuality);
    }

    @Test
    public void testMethodCreateSoftwareIdentifier() throws Exception {
        HcpartyType createSoftwareIdentifier = HcPartyUtil.createSoftwareIdentifier("Ehealth application", "1");
        Assert.assertEquals("Ehealth application", createSoftwareIdentifier.getName());
        Assert.assertEquals("1", createSoftwareIdentifier.getIds().get(0).getValue());
    }

    @Test
    public void testMethodCreateProfessionalParty() throws Exception {
        HcpartyType createProfessionalParty = HcPartyUtil.createProfessionalParty("52020845721", "10998315001", "persphysician");
        Assert.assertEquals("52020845721", createProfessionalParty.getIds().get(0).getValue());
        Assert.assertEquals("10998315001", createProfessionalParty.getIds().get(1).getValue());
        Assert.assertEquals("persphysician", createProfessionalParty.getCds().get(0).getValue());
    }

    @Test
    public void testMethodCreateKmehrIdStringWithSuffix() throws Exception {
        String createKmehrIdString = HcPartyUtil.createKmehrIdString("testphys", "kmehr");
        Assert.assertEquals("10998315001.kmehr", createKmehrIdString);
    }

    @Test
    public void testMethodCreateKmehrIdStringWithoutSuffix() throws Exception {
        String createKmehrIdString = HcPartyUtil.createKmehrIdString("testphys");
        StringTokenizer st = new StringTokenizer(createKmehrIdString);
        Assert.assertEquals("10998315001", st.nextToken("."));
    }

    @Test
    public void testMethodCreateKmehrId() throws Exception {
        IDKMEHR createKmehrId = HcPartyUtil.createKmehrId("testphys", "kmehr");
        Assert.assertEquals("10998315001.kmehr", createKmehrId.getValue());
    }

    @Test
    public void testMethodCreateInssId() {
        IDHCPARTY createInssId = HcPartyUtil.createInssId("91121208397");
        Assert.assertEquals("91121208397", createInssId.getValue());
        Assert.assertEquals(IDHCPARTYschemes.INSS, createInssId.getS());
    }

    @Test
    public void testMethodCreateNihiiId() {
        IDHCPARTY createNihiiId = HcPartyUtil.createNihiiId("10998315001");
        Assert.assertEquals("10998315001", createNihiiId.getValue());
        Assert.assertEquals(IDHCPARTYschemes.ID_HCPARTY, createNihiiId.getS());
    }

    @Test
    public void testMethodCreateCbeId() {
        IDHCPARTY createCbeId = HcPartyUtil.createCbeId("10998315001");
        Assert.assertEquals("10998315001", createCbeId.getValue());
        Assert.assertEquals(IDHCPARTYschemes.ID_HCPARTY, createCbeId.getS());
    }

    @Test
    public void testMethodCreateApplicationId() {
        IDHCPARTY createApplicationId = HcPartyUtil.createApplicationId("1");
        Assert.assertEquals("1", createApplicationId.getValue());
        Assert.assertEquals(IDHCPARTYschemes.LOCAL, createApplicationId.getS());
        Assert.assertEquals("application_ID", createApplicationId.getSL());
    }

    @Test
    public void testMethodCreateEhpId() {
        IDHCPARTY createEhpId = HcPartyUtil.createEhpId("10998315001");
        Assert.assertEquals("10998315001", createEhpId.getValue());
        Assert.assertEquals(IDHCPARTYschemes.ID_HCPARTY, createEhpId.getS());
    }

    @Test
    public void testMethodCreateAuthor() throws Exception {
        AuthorType createAuthor = HcPartyUtil.createAuthor("testphys");
        Assert.assertNotEquals(0, createAuthor.getHcparties().size());
    }

    @Test
    public void testMethodBuildIdWithValueAndSl() {
        IDHCPARTY buildId = HcPartyUtil.buildId("1", IDHCPARTYschemes.LOCAL);
        Assert.assertEquals("1", buildId.getValue());
        Assert.assertEquals(IDHCPARTYschemes.LOCAL, buildId.getS());
    }

    @Test
    public void testMethodBuildCdWithSvValueSchemeSl() {
        CDHCPARTY buildCd = HcPartyUtil.buildCd("1.0", "1", CDHCPARTYschemes.LOCAL, "1.1");
        Assert.assertEquals("1", buildCd.getValue());
        Assert.assertEquals(CDHCPARTYschemes.LOCAL, buildCd.getS());
        Assert.assertEquals("1.0", buildCd.getSV());
        Assert.assertEquals("1.1", buildCd.getSL());
    }

    @Test
    public void testMethodBuildCdWithSvValueSchemeSlDnL() {
        CDHCPARTY buildCd = HcPartyUtil.buildCd("1.0", "1", CDHCPARTYschemes.LOCAL, "1.1", "1.2", "1.3");
        Assert.assertEquals("1", buildCd.getValue());
        Assert.assertEquals(CDHCPARTYschemes.LOCAL, buildCd.getS());
        Assert.assertEquals("1.0", buildCd.getSV());
        Assert.assertEquals("1.1", buildCd.getSL());
        Assert.assertEquals("1.2", buildCd.getDN());
        Assert.assertEquals("1.3", buildCd.getL());
    }

}
