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

import static org.junit.Assert.fail;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import be.ehealth.technicalconnector.config.ConfigFactory;
import be.ehealth.technicalconnector.config.Configuration;
import be.ehealth.technicalconnector.exception.TechnicalConnectorException;
import be.fgov.ehealth.technicalconnector.tests.utils.LoggingUtils;


/**
 * test for the {@link ConfigurationImpl} class.
 *
 * @author EHP
 */

public class ConfigurationImplTest {

    private static final String OTHER_VALUE = "otherValue";

    /**
     * config containing the following properties and values: test.reference.filledProperty=filledProperty
     * test.reference.filledProperty2=another test.reference.emptyProperty=
     * test.reference.copyOfFilledProperty=${test.reference.filledProperty}
     * test.reference.copyOfEmptyProperty=${test.reference.emptyProperty}
     * test.reference.useFilledPropertyInComposition=prefix${test.reference.filledProperty}suffix
     * test.reference.useFilledPropertyInCompositionNoPrefix=${test.reference.filledProperty}suffix
     * test.reference.useFilledPropertyInCompositionNoSuffix=prefix${test.reference.filledProperty}
     * test.reference.useMultipleInCompositionAndCascading=prefix${test.reference.useFilledPropertyInComposition}
     * test.reference.circularDependency1=11111$${test.reference.circularDependency2}
     * test.reference.circularDependency2=22222${test.reference.circularDependency3}
     * test.reference.circularDependency3=33333${test.reference.circularDependency1}
     */
    private static ConfigurationImpl config;

    private static final String FILLED = "test.reference.filledProperty";

    private static final String FILLED2 = "test.reference.filledProperty2";

    private static final String FILLED_VALUE = "filledProperty";

    private static final String FILLED2_VALUE = "another";

    private static final String EMPTY = "test.reference.emptyProperty";

    private static final String NOT_EXISTING = "non.existing.value";

    private static final String COPY_FILLED = "test.reference.copyOfFilledProperty";

    private static final String COPY_EMPTY = "test.reference.copyOfEmptyProperty";

    private static final String COMPOSITION_WITH_PREFIX_SUFFIX = "test.reference.useFilledPropertyInComposition";

    private static final String COMPOSITION_WITH_SUFFIX = "test.reference.useFilledPropertyInCompositionNoPrefix";

    private static final String COMPOSITION_WITH_PREFIX = "test.reference.useFilledPropertyInCompositionNoSuffix";

    private static final String COMPOSITION_WITH_PREFIX_SUFFIX_AND_CASCADING = "test.reference.useMultipleInCompositionAndCascading";

    private static final String CIR_DEP_1 = "test.reference.circularDependency1";

    private static final String CIR_DEP_2 = "test.reference.circularDependency2";

    private static final String CIR_DEP_3 = "test.reference.circularDependency3";

    private static final String COPY_NON_EXISTING = "copy.non.existing.value";

    private static final String PRE = "prefix";

    private static final String SUF = "suffix";


    @BeforeClass
    public static void loadConfig() throws TechnicalConnectorException {
        LoggingUtils.bootstrap();
        ConfigFactory.setConfigLocation("/be.ehealth.technicalconnector.properties");
        Configuration currentConfig = null;
        try {
            currentConfig = ConfigFactory.getConfigValidator().getCurrentConfig();
            config = (ConfigurationImpl) currentConfig;
            config.getProperties().setProperty(EMPTY, "");
            config.getProperties().setProperty(FILLED, FILLED_VALUE);
            config.getProperties().setProperty(FILLED2, "another${test.reference.emptyProperty}");
            config.getProperties().setProperty(COPY_FILLED, "${test.reference.filledProperty}");
            config.getProperties().setProperty(COPY_EMPTY, "${test.reference.emptyProperty}");
            config.getProperties().setProperty(COMPOSITION_WITH_PREFIX_SUFFIX, "prefix${test.reference.filledProperty}suffix");
            config.getProperties().setProperty(COMPOSITION_WITH_SUFFIX, "${test.reference.filledProperty}suffix");
            config.getProperties().setProperty(COMPOSITION_WITH_PREFIX, "prefix${test.reference.filledProperty}");
            config.getProperties().setProperty(COMPOSITION_WITH_PREFIX_SUFFIX_AND_CASCADING, "prefix${test.reference.useFilledPropertyInComposition}");
            config.getProperties().setProperty(CIR_DEP_1, "11111$${test.reference.circularDependency2}");
            config.getProperties().setProperty(CIR_DEP_2, "22222${test.reference.circularDependency3}");
            config.getProperties().setProperty(CIR_DEP_3, "33333${test.reference.circularDependency1}");
        } catch (ClassCastException e) {
            fail("could not cast ConfigFactory.getConfigValidator().getCurrentConfig() with class " + currentConfig + " to ConfigurationImpl");
        }
    }

    @Test
    public void testConfigLoaded() throws Exception {

        Assert.assertNotNull(config);
    }

    /**
     * Test method for {@link be.ehealth.technicalconnector.config.impl.ConfigurationImpl#getProperty(java.lang.String, java.lang.String)}.
     */
    @Test
    public void testGetProperties() {
        Assert.assertEquals(FILLED_VALUE, config.getProperty(FILLED));
        Assert.assertEquals(FILLED_VALUE, config.getProperty(FILLED, OTHER_VALUE));
        Assert.assertEquals(FILLED2_VALUE, config.getProperty(FILLED2));
        Assert.assertEquals(FILLED2_VALUE, config.getProperty(FILLED2, OTHER_VALUE));
        Assert.assertEquals("", config.getProperty(EMPTY));
        Assert.assertEquals("", config.getProperty(EMPTY, OTHER_VALUE));
        Assert.assertEquals(null, config.getProperty(NOT_EXISTING));
        Assert.assertEquals(OTHER_VALUE, config.getProperty(NOT_EXISTING, OTHER_VALUE));
    }

    @Test
    public void testReplacementWithDefaultValueForEmptyReference() throws Exception {
    }

    /**
     * Test method for {@link be.ehealth.technicalconnector.config.impl.ConfigurationImpl#getProperty(java.lang.String, java.lang.String)}.
     */
    @Test
    public void testGetPropertiesWithReferencesCopyOfAnotherProperty() {
        Assert.assertEquals(FILLED_VALUE, config.getProperty(COPY_FILLED));
        Assert.assertEquals(FILLED_VALUE, config.getProperty(COPY_FILLED, OTHER_VALUE));
        Assert.assertEquals("", config.getProperty(COPY_EMPTY));
        Assert.assertEquals("", config.getProperty(COPY_EMPTY, OTHER_VALUE));
        Assert.assertEquals(null, config.getProperty(COPY_NON_EXISTING));
        Assert.assertEquals(null, config.getProperty(COPY_NON_EXISTING, null));
    }

    @Test
    public void testRetrieveValueFromReferenceWhichDoesNotExistWithDefault() throws Exception {
        Assert.assertEquals(OTHER_VALUE, config.getProperty(COPY_NON_EXISTING, OTHER_VALUE));
    }

    @Test
    public void testGetPropertiesWithReferencesNewBehaviour() throws Exception {
        // old return : ${non.existing.value}
        Assert.assertEquals(null, config.getProperty(COPY_NON_EXISTING));

        // old return : ${non.existing.value}
        Assert.assertEquals(OTHER_VALUE, config.getProperty(COPY_NON_EXISTING, OTHER_VALUE));
    }

    /**
     * Test method for {@link be.ehealth.technicalconnector.config.impl.ConfigurationImpl#getProperty(java.lang.String)}.
     */
    @Test
    public void testGetPropertiesWithReferencesCombinationOfProperties() {
        Assert.assertEquals(PRE + FILLED_VALUE + SUF, config.getProperty(COMPOSITION_WITH_PREFIX_SUFFIX));
        Assert.assertEquals(PRE + FILLED_VALUE + SUF, config.getProperty(COMPOSITION_WITH_PREFIX_SUFFIX, OTHER_VALUE));
        Assert.assertEquals(PRE + FILLED_VALUE, config.getProperty(COMPOSITION_WITH_PREFIX));
        Assert.assertEquals(PRE + FILLED_VALUE, config.getProperty(COMPOSITION_WITH_PREFIX, OTHER_VALUE));
        Assert.assertEquals(FILLED_VALUE + SUF, config.getProperty(COMPOSITION_WITH_SUFFIX));
        Assert.assertEquals(FILLED_VALUE + SUF, config.getProperty(COMPOSITION_WITH_SUFFIX, OTHER_VALUE));

    }

    @Test
    public void testGetPropertiesWithReferencesCombinationOfPropertiesNewBehaviour() throws Exception {
        Assert.assertEquals(PRE + PRE + FILLED_VALUE + SUF, config.getProperty(COMPOSITION_WITH_PREFIX_SUFFIX_AND_CASCADING));
        Assert.assertEquals(PRE + PRE + FILLED_VALUE + SUF, config.getProperty(COMPOSITION_WITH_PREFIX_SUFFIX_AND_CASCADING, OTHER_VALUE));
    }

    @Test
    public void testUddiPropertiesWithoutEnvironment() {
        config.setProperty("environment", "");
        config.setProperty("endpoint.sts", "$uddi{uddi:ehealth-fgov-be:business:iamsecuritytokenservice:v1}");
        Assert.assertEquals("https://services.ehealth.fgov.be/IAM/SecurityTokenService/v1", config.getProperty("endpoint.sts"));
    }

    @Test
    public void testUddiPropertiesWithEnvironment() {
        config.setProperty("environment", "acc");
        config.setProperty("endpoint.sts", "$uddi{uddi:ehealth-fgov-be:business:iamsecuritytokenservice:v1}");
        Assert.assertEquals("https://services-acpt.ehealth.fgov.be/IAM/SecurityTokenService/v1", config.getProperty("endpoint.sts"));
    }

    @Test
    public void testUddiPropertiesNotPresent() {
        Assert.assertEquals("https://services-acpt.ehealth.fgov.be/IAM/SecurityTokenService/v1", config.getProperty("endpoint.unknown", "$uddi{uddi:ehealth-fgov-be:business:iamsecuritytokenservice:v1}"));

    }

    @Test(expected = RuntimeException.class)
    public void testCircularDependenciesCase1() throws Exception {
        config.getProperty(CIR_DEP_1);
    }

    @Test(expected = RuntimeException.class)
    public void testCircularDependenciesCase2() throws Exception {
        config.getProperty(CIR_DEP_2);
    }


    @Test(expected = RuntimeException.class)
    public void testCircularDependenciesCase3() throws Exception {
        config.getProperty(CIR_DEP_3);
    }


}
