/*
 * 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 st = new ServiceTracker(bundleContext,
                ResourceTransformer.class.getName(), new ServiceTrackerCustomizer() {

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

            @Override
            public void modifiedService(ServiceReference reference, Object service) {
            }

            @Override
            public Object addingService(ServiceReference 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);
    }
}
