/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.sling.installer.it;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;

import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.sling.installer.api.InstallableResource;
import org.apache.sling.installer.api.event.InstallationEvent;
import org.apache.sling.installer.api.event.InstallationListener;
import org.apache.sling.installer.api.tasks.ResourceState;
import org.apache.sling.installer.api.tasks.ResourceTransformer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.PaxExam;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.cm.ConfigurationEvent;
import org.osgi.service.cm.ConfigurationListener;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;

@RunWith(PaxExam.class)

public class ConfigInstallTest extends OsgiInstallerTestBase implements ConfigurationListener {

    private final List<ConfigurationEvent> events = new LinkedList<ConfigurationEvent>();
    private final List<ServiceRegistration<?>> serviceRegistrations = new ArrayList<ServiceRegistration<?>>();
    private volatile int installationEvents = 0;
    private static final AtomicInteger counter = new AtomicInteger();

    @org.ops4j.pax.exam.Configuration
    public Option[] config() {
        return defaultConfiguration();
    }

    @Before
    public void setUp() {
        installationEvents = 0;
        setupInstaller();
        events.clear();
        serviceRegistrations.clear();
        serviceRegistrations.add(bundleContext.registerService(ConfigurationListener.class.getName(), this, null));

        final InstallationListener il = new InstallationListener() {
            @Override
            public void onEvent(InstallationEvent event) {
                installationEvents++;
            }
        };
        serviceRegistrations.add(bundleContext.registerService(InstallationListener.class.getName(), il, null));
    }

    @Override
    @After
    public void tearDown() {
        super.tearDown();
        for(ServiceRegistration<?> reg : serviceRegistrations) {
        	reg.unregister();
        }
        serviceRegistrations.clear();
    }

    private String uniqueID() {
        return counter.incrementAndGet() + "_" + System.currentTimeMillis();
    }

    /**
     * @see org.osgi.service.cm.ConfigurationListener#configurationEvent(org.osgi.service.cm.ConfigurationEvent)
     */
    @Override
    public void configurationEvent(final ConfigurationEvent e) {
        if ( e.getType() == ConfigurationEvent.CM_DELETED || e.getType() == ConfigurationEvent.CM_UPDATED) {
            synchronized ( events ) {
                events.add(e);
            }
        }
	}

    @Test
    public void testInstallConfigWindowsPath() throws Exception {
        final Dictionary<String, Object> cfgData = new Hashtable<String, Object>();
        cfgData.put("foo", "bar");
        final String cfgPid = getClass().getSimpleName() + "." + uniqueID();
        assertNull("Config " + cfgPid + " must not be found before test", findConfiguration(cfgPid));

        // install configs
        //Following patterns work fine. Problem occurs one with windows seprator
        // - "c:/foo/bar/"
        // - "/foo/bar/"
        final String uri = "c:\\foo\bar\\";
        final InstallableResource result = new MockInstallableResource(uri + cfgPid, copy(cfgData), null, null, 100);
        final InstallableResource[] rsrc = new InstallableResource[] {result};
        installer.updateResources(URL_SCHEME, rsrc, null);

        Configuration cfg = waitForConfiguration("After installing", cfgPid, true);
        assertEquals("Config value must match", "bar", cfg.getProperties().get("foo"));

        // remove again
        installer.updateResources(URL_SCHEME, null, new String[] {rsrc[0].getId()});
        waitForConfiguration("After removing for the second time", cfgPid, false);
    }

	@Test
    public void testInstallAndRemoveConfig() throws Exception {
        final Dictionary<String, Object> cfgData = new Hashtable<String, Object>();
        cfgData.put("foo", "bar");
        final String cfgPid = getClass().getSimpleName() + "." + uniqueID();
        assertNull("Config " + cfgPid + " must not be found before test", findConfiguration(cfgPid));

        // install config
        final InstallableResource[] rsrc = getInstallableResource(cfgPid, cfgData);
        installer.updateResources(URL_SCHEME, rsrc, null);

        Configuration cfg = waitForConfiguration("After installing", cfgPid, true);
        assertEquals("Config value must match", "bar", cfg.getProperties().get("foo"));

        // remove resource
        installer.updateResources(URL_SCHEME, null, new String[] {rsrc[0].getId()});
        waitForConfiguration("After removing", cfgPid, false);

        // Reinstalling with same digest must work
        installer.updateResources(URL_SCHEME, rsrc, null);
        cfg = waitForConfiguration("After reinstalling", cfgPid, true);
        assertEquals("Config value must match", "bar", cfg.getProperties().get("foo"));

        // remove again
        installer.updateResources(URL_SCHEME, null, new String[] {rsrc[0].getId()});
        waitForConfiguration("After removing for the second time", cfgPid, false);
    }

    @Test
    public void testInstallUpdateRemoveConfigResource() throws Exception {
        final Dictionary<String, Object> cfgData = new Hashtable<String, Object>();
        cfgData.put("foo", "bar");
        final String cfgPid = getClass().getSimpleName() + "." + uniqueID();

        // install config
        final InstallableResource rsrc = new InstallableResource("/configA/" + cfgPid,
                null, cfgData, null, InstallableResource.TYPE_PROPERTIES, 10);
        installer.updateResources(URL_SCHEME, new InstallableResource[] {rsrc}, null);

        // get config
        waitForConfigValue("After installing", cfgPid, "foo", "bar");

        // create second configuration
        final Dictionary<String, Object> secondData = new Hashtable<String, Object>();
        secondData.put("foo", "bla");
        final InstallableResource rsrc2 = new InstallableResource("/configB/" + cfgPid,
                null, secondData, null, InstallableResource.TYPE_PROPERTIES, 20);
        installer.updateResources(URL_SCHEME, new InstallableResource[] {rsrc2}, null);

        // get updated config
        waitForConfigValue("After updating", cfgPid, "foo", "bla");

        // remove config
        installer.updateResources(URL_SCHEME, null, new String[] {"/configB/" + cfgPid});

        waitForConfigValue("After deleting", cfgPid, "foo", "bar");
    }

    @Test
    public void testInstallUpdateRemoveTemplateConfigResource() throws Exception {
        final Dictionary<String, Object> cfgData = new Hashtable<String, Object>();
        cfgData.put("foo", "bar");
        cfgData.put(InstallableResource.RESOURCE_IS_TEMPLATE, "true");
        final String cfgPid = getClass().getSimpleName() + "." + uniqueID();

        // install config
        final InstallableResource rsrc = new InstallableResource("/configA/" + cfgPid,
                null, cfgData, null, InstallableResource.TYPE_PROPERTIES, 10);
        installer.updateResources(URL_SCHEME, new InstallableResource[] {rsrc}, null);

        // get config
        waitForConfigValue("After installing", cfgPid, "foo", "bar");

        // create second configuration
        final Dictionary<String, Object> secondData = new Hashtable<String, Object>();
        secondData.put("foo", "bla");
        final InstallableResource rsrc2 = new InstallableResource("/configB/" + cfgPid,
                null, secondData, null, InstallableResource.TYPE_PROPERTIES, 20);
        installer.updateResources(URL_SCHEME, new InstallableResource[] {rsrc2}, null);

        // get updated config
        waitForConfigValue("After updating", cfgPid, "foo", "bla");

        // remove config
        installer.updateResources(URL_SCHEME, null, new String[] {"/configB/" + cfgPid});

        waitForConfiguration("After deleting", cfgPid, false);
    }

    @Test
    public void testInstallUpdateRemoveConfigFactoryResource() throws Exception {
        final Dictionary<String, Object> cfgData = new Hashtable<String, Object>();
        cfgData.put("foo", "bar");
        final String cfgFactoryPid = getClass().getSimpleName() + "." + uniqueID();
        final String alias = "alias" + uniqueID();

        // install factory config
        final InstallableResource rsrc = new InstallableResource("/configA/" + cfgFactoryPid + "-" + alias,
                null, cfgData, null, InstallableResource.TYPE_PROPERTIES, 10);
        installer.updateResources(URL_SCHEME, new InstallableResource[] {rsrc}, null);

        // get factory config
        waitForFactoryConfigValue("After installing", cfgFactoryPid, "foo", "bar");

        // create second factory configuration with same alias
        final Dictionary<String, Object> secondData = new Hashtable<String, Object>();
        secondData.put("foo", "bla");
        final InstallableResource rsrc2 = new InstallableResource("/configB/" + cfgFactoryPid + "-" + alias,
                null, secondData, null, InstallableResource.TYPE_PROPERTIES, 20);
        installer.updateResources(URL_SCHEME, new InstallableResource[] {rsrc2}, null);

        // get updated factory config
        waitForFactoryConfigValue("After updating", cfgFactoryPid, "foo", "bla");

        // remove factory config
        installer.updateResources(URL_SCHEME, null, new String[] {"/configB/" + cfgFactoryPid + "-" + alias});

        waitForFactoryConfigValue("After updating", cfgFactoryPid, "foo", "bar");
    }

    @Test
    public void testInstallUpdateRemoveTemplateConfigFactoryResource() throws Exception {
        final Dictionary<String, Object> cfgData = new Hashtable<String, Object>();
        cfgData.put("foo", "bar");
        cfgData.put(InstallableResource.RESOURCE_IS_TEMPLATE, "true");
        final String cfgFactoryPid = getClass().getSimpleName() + "." + uniqueID();
        final String alias = "alias" + uniqueID();

        // install factory config
        final InstallableResource rsrc = new InstallableResource("/configA/" + cfgFactoryPid + "-" + alias,
                null, cfgData, null, InstallableResource.TYPE_PROPERTIES, 10);
        installer.updateResources(URL_SCHEME, new InstallableResource[] {rsrc}, null);

        // get factory config
        waitForFactoryConfigValue("After installing", cfgFactoryPid, "foo", "bar");

        // create second factory configuration
        final Dictionary<String, Object> secondData = new Hashtable<String, Object>();
        secondData.put("foo", "bla");
        final InstallableResource rsrc2 = new InstallableResource("/configB/" + cfgFactoryPid + "-" + alias,
                null, secondData, null, InstallableResource.TYPE_PROPERTIES, 20);
        installer.updateResources(URL_SCHEME, new InstallableResource[] {rsrc2}, null);

        // get updated factory config
        waitForFactoryConfigValue("After updating", cfgFactoryPid, "foo", "bla");

        // remove config
        installer.updateResources(URL_SCHEME, null, new String[] {"/configB/" + cfgFactoryPid + "-" + alias});

        waitForFactoryConfiguration("After deleting", cfgFactoryPid, false);
    }

    @Test
    public void testInstallUpdateRemoveConfig() throws Exception {
        final Dictionary<String, Object> cfgData = new Hashtable<String, Object>();
        cfgData.put("foo", "bar");
        final String cfgPid = getClass().getSimpleName() + "." + uniqueID();

        // install config
        final InstallableResource rsrc = new InstallableResource("/configA/" + cfgPid,
                null, cfgData, null, InstallableResource.TYPE_PROPERTIES, 10);
        installer.updateResources(URL_SCHEME, new InstallableResource[] {rsrc}, null);

        // get config
        final Configuration cfg = waitForConfigValue("After installing", cfgPid, "foo", "bar");

        // update configuration
        final Dictionary<String, Object> secondData = new Hashtable<String, Object>();
        secondData.put("foo", "bla");
        cfg.update(secondData);

        waitForResource(URL_SCHEME + ":/configA/" + cfgPid, ResourceState.IGNORED);

        // get updated config
        final Configuration secondCfg = waitForConfigValue("After updating", cfgPid, "foo", "bla");

        // remove config
        secondCfg.delete();

        waitForResource(URL_SCHEME + ":/configA/" + cfgPid, ResourceState.INSTALLED);

        waitForConfigValue("After deleting", cfgPid, "foo", "bar");
    }

    @Test
    public void testInstallUpdateRemoveTemplateConfig() throws Exception {
        final Dictionary<String, Object> cfgData = new Hashtable<String, Object>();
        cfgData.put("foo", "bar");
        cfgData.put(InstallableResource.RESOURCE_IS_TEMPLATE, "true");
        final String cfgPid = getClass().getSimpleName() + "." + uniqueID();

        // install config
        final InstallableResource rsrc = new InstallableResource("/configA/" + cfgPid,
                null, cfgData, null, InstallableResource.TYPE_PROPERTIES, 10);
        installer.updateResources(URL_SCHEME, new InstallableResource[] {rsrc}, null);

        // get config
        final Configuration cfg = waitForConfigValue("After installing", cfgPid, "foo", "bar");

        // update configuration
        final Dictionary<String, Object> secondData = new Hashtable<String, Object>();
        secondData.put("foo", "bla");
        cfg.update(secondData);

        waitForResource(URL_SCHEME + ":/configA/" + cfgPid, ResourceState.IGNORED);

        // get updated config
        final Configuration secondCfg = waitForConfigValue("After updating", cfgPid, "foo", "bla");

        // remove config
        secondCfg.delete();

        sleep(200); // we have to wait here as no state change is happening
        waitForResource(URL_SCHEME + ":/configA/" + cfgPid, ResourceState.IGNORED);

        waitForConfiguration("After deleting", cfgPid, false);
    }

    @Test
    public void testInstallUpdateRemoveConfigFactory() throws Exception {
        final Dictionary<String, Object> cfgData = new Hashtable<String, Object>();
        cfgData.put("foo", "bar");
        final String cfgFactoryPid = getClass().getSimpleName() + "." + uniqueID();
        final String alias = "alias" + uniqueID();

        // install factory config
        final InstallableResource rsrc = new InstallableResource("/configA/" + cfgFactoryPid + "-" + alias,
                null, cfgData, null, InstallableResource.TYPE_PROPERTIES, 10);
        installer.updateResources(URL_SCHEME, new InstallableResource[] {rsrc}, null);

        // get factory config
        final Configuration cfg = waitForFactoryConfigValue("After installing", cfgFactoryPid, "foo", "bar");

        // update configuration
        final Dictionary<String, Object> secondData = new Hashtable<String, Object>();
        secondData.put("foo", "bla");
        cfg.update(secondData);

        waitForResource(URL_SCHEME + ":/configA/" + cfgFactoryPid + "-" + alias, ResourceState.IGNORED);

        // get updated factory config
        final Configuration secondCfg = waitForFactoryConfigValue("After updating", cfgFactoryPid, "foo", "bla");

        // remove factory config
        secondCfg.delete();
        waitForResource(URL_SCHEME + ":/configA/" + cfgFactoryPid + "-" + alias, ResourceState.INSTALLED);

        waitForFactoryConfigValue("After deleting", cfgFactoryPid, "foo", "bar");
    }

    @Test
    public void testInstallUpdateRemoveTemplateConfigFactory() throws Exception {
        final Dictionary<String, Object> cfgData = new Hashtable<String, Object>();
        cfgData.put("foo", "bar");
        cfgData.put(InstallableResource.RESOURCE_IS_TEMPLATE, "true");
        final String cfgFactoryPid = getClass().getSimpleName() + "." + uniqueID();
        final String alias = "alias" + uniqueID();

        // install factory config
        final InstallableResource rsrc = new InstallableResource("/configA/" + cfgFactoryPid + "-" + alias,
                null, cfgData, null, InstallableResource.TYPE_PROPERTIES, 10);
        installer.updateResources(URL_SCHEME, new InstallableResource[] {rsrc}, null);

        // get factory config
        final Configuration cfg = waitForFactoryConfigValue("After installing", cfgFactoryPid, "foo", "bar");

        // update configuration
        final Dictionary<String, Object> secondData = new Hashtable<String, Object>();
        secondData.put("foo", "bla");
        cfg.update(secondData);

        waitForResource(URL_SCHEME + ":/configA/" + cfgFactoryPid + "-" + alias, ResourceState.IGNORED);

        // get updated factory config
        final Configuration secondCfg = waitForFactoryConfigValue("After updating", cfgFactoryPid, "foo", "bla");

        // remove config
        secondCfg.delete();
        sleep(200); // we have to wait here as no state change is happening

        waitForResource(URL_SCHEME + ":/configA/" + cfgFactoryPid + "-" + alias, ResourceState.IGNORED);
        waitForFactoryConfiguration("After deleting", cfgFactoryPid, false);
    }

    @Test
    public void testDeferredConfigInstall() throws Exception {
        // get config admin bundle and wait for service
    	final Bundle configAdmin = this.getConfigAdminBundle();
    	assertNotNull("ConfigAdmin bundle must be found", configAdmin);
    	waitForConfigAdmin(true);

    	// check that configuration is not available
        final String cfgPid = getClass().getSimpleName() + ".deferred." + uniqueID();
        assertNull("Config " + cfgPid + " must not be found before test", findConfiguration(cfgPid));
    	// create new configuration object
    	final Dictionary<String, Object> cfgData = new Hashtable<String, Object>();
    	cfgData.put("foo", "bar");

    	// Configuration installs must be deferred if ConfigAdmin service is stopped
        configAdmin.stop();
    	waitForConfigAdmin(false);

    	// add new configuration
        final InstallableResource[] rsrc = getInstallableResource(cfgPid, cfgData);
        installationEvents = 0;
        installer.updateResources(URL_SCHEME, rsrc, null);
        waitForInstallationEvents(2);
        configAdmin.start();
    	waitForConfigAdmin(true);
        waitForConfiguration("Config must be installed once ConfigurationAdmin restarts",
                cfgPid, true);

        // Remove config and check
        installer.updateResources(URL_SCHEME, null, new String[] {rsrc[0].getId()});
        waitForConfiguration("Config must be removed once ConfigurationAdmin restarts",
                cfgPid, false);
    }

    @Test
    public void testDeferredConfigRemove() throws Exception {
        final AtomicInteger transformerCount = new AtomicInteger();

        final ServiceTracker<ResourceTransformer, ResourceTransformer> st = new ServiceTracker<ResourceTransformer, ResourceTransformer>(bundleContext,
                ResourceTransformer.class, new ServiceTrackerCustomizer<ResourceTransformer, ResourceTransformer>() {

            @Override
            public void removedService(ServiceReference<ResourceTransformer> reference, ResourceTransformer service) {
                bundleContext.ungetService(reference);
                transformerCount.decrementAndGet();
            }

            @Override
            public void modifiedService(ServiceReference<ResourceTransformer> reference, ResourceTransformer service) {
            }

            @Override
            public ResourceTransformer addingService(ServiceReference<ResourceTransformer> reference) {
                transformerCount.incrementAndGet();
                return bundleContext.getService(reference);
            }
        });
        st.open();

        final AtomicInteger expectedCount = new AtomicInteger();
        final Condition cond = new Condition() {

            @Override
            boolean isTrue() throws Exception {
                return transformerCount.get() == expectedCount.get();
            }

            @Override
            String additionalInfo() {
                return "Resource transformer count is " + String.valueOf(transformerCount.get()) +
                       ", should be " + String.valueOf(expectedCount.get());
            }

        };

        // get config admin bundle and wait for service
        final Bundle configAdmin = this.getConfigAdminBundle();
        assertNotNull("ConfigAdmin bundle must be found", configAdmin);
        waitForConfigAdmin(true);

        // when everything is up and running, we have two factories
        expectedCount.set(2);
        waitForCondition(null, cond);

        // check that configuration is not available
        final String cfgPid = getClass().getSimpleName() + ".deferred." + uniqueID();
        assertNull("Config " + cfgPid + " must not be found before test", findConfiguration(cfgPid));

        // create and install new configuration object, verify
        final Dictionary<String, Object> cfgData = new Hashtable<String, Object>();
        cfgData.put("foo", "bar");
        final InstallableResource[] rsrc = getInstallableResource(cfgPid, cfgData);
        installer.updateResources(URL_SCHEME, rsrc, null);
        waitForConfiguration("Config must be installed before stopping ConfigurationAdmin",
                cfgPid, true);
        this.waitForResource(URL_SCHEME + ":" + rsrc[0].getId(), ResourceState.INSTALLED);

        // Configuration uninstalls must be deferred if ConfigAdmin service is stopped
        configAdmin.stop();
        waitForConfigAdmin(false);

        // only bundle transformer
        expectedCount.set(1);
        waitForCondition(null, cond);

        // remove configuration
        installationEvents = 0;
        installer.updateResources(URL_SCHEME, null, new String[] {rsrc[0].getId()});
        waitForInstallationEvents(2);
        this.waitForResource(URL_SCHEME + ":" + rsrc[0].getId(), ResourceState.UNINSTALL);

        configAdmin.start();
        waitForConfigAdmin(true);

        // when everything is up and running, we have two transformers again
        expectedCount.set(2);
        waitForCondition(null, cond);

        waitForConfiguration("Config must be removed once ConfigurationAdmin restarts",
                cfgPid, false);

        st.close();
    }

    @Test
    public void testReinstallSameConfig() throws Exception {
    	final Dictionary<String, Object> cfgData = new Hashtable<String, Object>();
    	cfgData.put("foo", "bar");
    	final String cfgPid = getClass().getSimpleName() + ".reinstall." + uniqueID();
    	assertNull("Config " + cfgPid + " must not be found before test", findConfiguration(cfgPid));

    	// Install config directly
    	ConfigurationAdmin ca = waitForConfigAdmin(true);
    	final Configuration c = ca.getConfiguration(cfgPid);
    	c.update(cfgData);
        waitForConfigValue("After manual installation", cfgPid, "foo", "bar");
        waitForCondition("Expected one ConfigurationEvents since beginning of test", new ConfigCondition(cfgPid, 1));

        installer.updateResources(URL_SCHEME, getInstallableResource(cfgPid, cfgData), null);

    	// Reinstalling with a change must be executed
        cfgData.put("foo", "changed");
        installer.updateResources(URL_SCHEME, getInstallableResource(cfgPid, cfgData), null);
        waitForConfigValue("After changing value", cfgPid, "foo", "changed");
        waitForCondition("Expected two ConfigurationEvents since beginning of test", new ConfigCondition(cfgPid, 2));
    }

    protected final class ConfigCondition extends Condition {

        private final String pid;

        private final int maxCount;

        public ConfigCondition(final String pid, final int count) {
            this.pid = pid;
            this.maxCount = count;
        }

        @Override
        boolean isTrue() throws Exception {
            int count = 0;
            synchronized ( events ) {
                for(final ConfigurationEvent e : events) {
                    if ( pid.equals(e.getPid()) ) {
                        count++;
                    }
                }
            }
            return count == maxCount;
        }

        @Override
        String additionalInfo() {
            final StringBuilder sb = new StringBuilder("Expected ");
            sb.append(maxCount);
            sb.append(" events for ");
            sb.append(pid);
            sb.append(". Received events: [");
            boolean first = true;
            synchronized ( events ) {
                for(final ConfigurationEvent e : events) {
                    if ( !first) {
                        sb.append(", ");
                    }
                    first = false;
                    sb.append(e.getPid());
                    sb.append(':');
                    sb.append(e.getType());
                }
            }
            sb.append("]");
            return sb.toString();
        }
    }

    private void waitForInstallationEvents(final int howMany) throws Exception {
        final Condition c = new Condition() {
            @Override
            boolean isTrue() throws Exception {
                return installationEvents >= howMany;
            }
        };
        waitForCondition("Wait for " + howMany + " installation events", c);
    }
}
