/*
 * 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 java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import static org.junit.Assert.*;
import org.apache.sling.installer.api.InstallableResource;
import org.apache.sling.installer.api.OsgiInstaller;
import org.apache.sling.installer.api.event.InstallationEvent;
import org.apache.sling.installer.api.event.InstallationListener;
import org.apache.sling.installer.api.info.InfoProvider;
import org.apache.sling.installer.api.info.InstallationState;
import org.apache.sling.installer.api.info.Resource;
import org.apache.sling.installer.api.info.ResourceGroup;
import org.apache.sling.installer.api.tasks.ResourceState;
import org.apache.sling.installer.api.tasks.ResourceTransformer;
import org.apache.sling.installer.api.tasks.TaskResource;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.util.tracker.ServiceTracker;

/**
 * Utility methods for {@link ConfigUpdateTest}.
 */
public class ConfigUpdateTestUtil {

    static private final String GROUP_ID = "org.apache.sling";
    static private final String ARTIFACT_ID = "org.apache.sling.installer.factory.configuration";
    static private final String OLD_VERSION = "1.1.2";

    public static final String FACTORY_PID = "org.apache.sling.factory.test.installer";
    public static final String MANUAL_FACTORY_PID = "org.apache.sling.factory.test.manual";

    public static final String NAME_1 = "myname1";

    public static final String SCHEME = "myscheme";

    public static final String OVERLAY_SCHEME = "overlay";

    private final BundleContext bundleContext;

    private ConfigurationAdmin configAdmin;

    private InfoProvider infoProvider;

    private OsgiInstaller installer;

    public ConfigUpdateTestUtil(final BundleContext ctx) throws Exception {
        this.bundleContext = ctx;
        // we need the old config factory first
        final Bundle b = getConfigFactoryBundle();
        b.stop();
        final String urlString = org.ops4j.pax.exam.CoreOptions.mavenBundle(GROUP_ID, ARTIFACT_ID, OLD_VERSION).getURL();
        final URL url = new URL(urlString);
        try ( final InputStream is = url.openStream()) {
            b.update(is);
        }
        b.start();
    }

    public void init(final ConfigurationAdmin configAdmin,
            final OsgiInstaller installer,
            final InfoProvider infoProvider) {
        this.configAdmin = configAdmin;
        this.installer = installer;
        this.infoProvider = infoProvider;
    }

    /**
     * Helper method for sleeping.
     */
    private void sleep(long msec) {
        try {
            Thread.sleep(msec);
        } catch(InterruptedException ignored) {
        }
    }

    private Bundle getConfigFactoryBundle() {
        for(final Bundle b : this.bundleContext.getBundles()) {
            if ( ARTIFACT_ID.equals(b.getSymbolicName())) {
                return b;
            }
        }
        throw new IllegalStateException("Config factory bundle not found");
    }

    public void updateConfigFactoryBundle() throws Exception {
        final Bundle b = getConfigFactoryBundle();
        b.stop();
        final String urlString = org.ops4j.pax.exam.CoreOptions.mavenBundle(GROUP_ID, ARTIFACT_ID, OsgiInstallerTestBase.CONFIG_VERSION).getURL();
        final URL url = new URL(urlString);
        try ( final InputStream is = url.openStream()) {
            b.update(is);
        }
        b.start();
        // wait for resource transformer  to be registered
        final ServiceTracker<ResourceTransformer, ResourceTransformer> tracker = new ServiceTracker<>(bundleContext, 
                bundleContext.createFilter("(&(" + Constants.OBJECTCLASS + "=" + ResourceTransformer.class.getName() + ")" +
                         "(" + ResourceTransformer.NAME + "=org.osgi.service.cm))"),
                null);
        tracker.open();
        tracker.waitForService(10000);
        tracker.close();
    }

    public InstallableResource[] createTestConfigResources() {
        return createTestConfigResources(null);
    }

    public InstallableResource[] createTestConfigResources(final Integer prio) {
        final Dictionary<String, Object> props = new Hashtable<>();
        props.put("key", "value");
        props.put("id", NAME_1);

        // we need to specify a path as config factory < 1.2.0 has a bug in handling the id if a path is missing
        final InstallableResource rsrc = new InstallableResource("configs/" + FACTORY_PID + "-" + NAME_1 + ".cfg",
                null, props, "1", InstallableResource.TYPE_CONFIG, prio);

        return new InstallableResource[] {rsrc};
    }

    public void installTestConfigs() {
        final InstallableResource[] resources = createTestConfigResources();
        final ResourceInstallationListener listener = new ResourceInstallationListener(resources.length);
        final ServiceRegistration<InstallationListener> reg = this.bundleContext.registerService(InstallationListener.class, listener, null);
        try {
            installer.registerResources(SCHEME, resources);

            listener.waitForInstall();
        } finally {
            reg.unregister();
        }
    }

    public void installOverlayTestConfigs() {
        final InstallableResource[] resources = createTestConfigResources(200);
        for(final InstallableResource rsrc : resources) {
            rsrc.getDictionary().put("overlay", Boolean.TRUE);
        }
        final ResourceInstallationListener listener = new ResourceInstallationListener(OVERLAY_SCHEME, resources.length);
        final ServiceRegistration<InstallationListener> reg = this.bundleContext.registerService(InstallationListener.class, listener, null);
        try {
            installer.registerResources(OVERLAY_SCHEME, resources);

            listener.waitForInstall();
        } finally {
            reg.unregister();
        }
    }

    public void installModifiedTestConfigs(final boolean useRegister) {
        final InstallableResource[] resources = createTestConfigResources();
        for(final InstallableResource rsrc : resources) {
            rsrc.getDictionary().put("modified", Boolean.TRUE);
        }
        final ResourceInstallationListener listener = new ResourceInstallationListener(resources.length);
        final ServiceRegistration<InstallationListener> reg = this.bundleContext.registerService(InstallationListener.class, listener, null);
        try {
            if ( useRegister) {
                installer.registerResources(SCHEME, resources);
            } else {
                installer.updateResources(SCHEME, resources, null);
            }
            listener.waitForInstall();
        } finally {
            reg.unregister();
        }
    }

    public Configuration assertTestConfig(final String name, final boolean checkNew) throws Exception {
        return assertTestConfig(name, checkNew, checkNew);
    }

    public Configuration assertTestConfig(final String name, final boolean checkNew, final boolean modifiedExists) throws Exception {
        final Configuration[] cfgs = this.configAdmin.listConfigurations("(&(" + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + FACTORY_PID + ")" +
            "(id=" + name + "))");
        assertNotNull(cfgs);
        assertEquals(1, cfgs.length);
        final Configuration c = cfgs[0];
        assertEquals("value", c.getProperties().get("key"));
        assertEquals(name, c.getProperties().get("id"));

        if ( !checkNew) {
            assertFalse(c.getPid().equals(FACTORY_PID + "~" + name));
            final Configuration[] cfgs1 = this.configAdmin.listConfigurations("(" + Constants.SERVICE_PID + "=" + FACTORY_PID + "~" + name + ")");
            assertTrue(cfgs1 == null || cfgs1.length == 0);
        }
        if ( checkNew) {
            final Configuration[] cfgs1 = this.configAdmin.listConfigurations("(" + Constants.SERVICE_PID + "=" + FACTORY_PID + "~" + name + ")");
            assertNotNull(cfgs1);
            assertEquals(1, cfgs1.length);
            final Configuration c1 = cfgs1[0];
            assertEquals("value", c1.getProperties().get("key"));
            assertEquals(name, c1.getProperties().get("id"));
            assertEquals(FACTORY_PID, c1.getFactoryPid());
            assertEquals(c.getPid(), c1.getPid());
        }
        if ( modifiedExists ) {
            assertEquals(Boolean.TRUE, c.getProperties().get("modified"));
        } else {
            assertNull(c.getProperties().get("modified"));
        }
        return c;
    }

    public void assertOverlayInstallerState(final String name,
            final boolean checkNew,
            final ResourceState expectedState) throws Exception {
        ResourceGroup found = null;
        final InstallationState state = this.infoProvider.getInstallationState();
        for(final ResourceGroup group : state.getInstalledResources()) {
            for(final Resource rsrc : group.getResources()) {
                if ( rsrc.getScheme().equals(SCHEME) && rsrc.getURL().equals(SCHEME + ":" + "configs/" + FACTORY_PID + "-" + name + ".cfg")) {
                    found = group;
                    break;
                }
            }
            if ( found != null ) {
                break;
            }
        }
        assertNotNull(found);
        assertEquals(2, found.getResources().size());
        final Resource r = found.getResources().get(0);
        if ( checkNew ) {
            assertEquals("config:" + FACTORY_PID + "~" + name, r.getEntityId());
        } else {
            assertEquals("config:" + FACTORY_PID + "." + name, r.getEntityId());
        }
        assertEquals(expectedState, r.getState());
        assertEquals(OVERLAY_SCHEME, r.getScheme());
    }

    public void assertInstallerState(final String name,
            final boolean checkNew,
            final ResourceState expectedState) throws Exception {
        // make sure there is only one state in the OSGi installer
        ResourceGroup found = null;
        final InstallationState state = this.infoProvider.getInstallationState();
        for(final ResourceGroup group : state.getInstalledResources()) {
            for(final Resource rsrc : group.getResources()) {
                if ( rsrc.getScheme().equals(SCHEME) && rsrc.getURL().equals(SCHEME + ":" + "configs/" + FACTORY_PID + "-" + name + ".cfg")) {
                    found = group;
                    break;
                }
            }
            if ( found != null ) {
                break;
            }
        }
        assertNotNull(found);
        assertEquals(1, found.getResources().size());
        final Resource r = found.getResources().get(0);
        if ( checkNew ) {
            assertEquals("config:" + FACTORY_PID + "~" + name, r.getEntityId());
        } else {
            assertEquals("config:" + FACTORY_PID + "." + name, r.getEntityId());
        }
        assertEquals(expectedState, r.getState());
    }

    public void assertInstallerState(final String factoryPID, final int count) throws Exception {
        int c = 0;
        final InstallationState state = this.infoProvider.getInstallationState();
        for(final ResourceGroup group : state.getInstalledResources()) {
            for(final Resource rsrc : group.getResources()) {
                // contains is not precise but should be could enough
                if (rsrc.getEntityId().startsWith("config:") && rsrc.getEntityId().contains(factoryPID) ) {
                    c++;
                }
            }
        }
        assertEquals(count, c);
    }

    public void tearDown() {
        try {
            // stop configuration factory
            getConfigFactoryBundle().stop();

            // remove all configurations
            final Configuration[] cfgs = this.configAdmin.listConfigurations(null);
            if ( cfgs != null ) {
                for(final Configuration c : cfgs) {
                    c.delete();
                }
            }
        } catch ( final IOException | BundleException | InvalidSyntaxException ignore) {
            // ignore
        }
    }


    private class ResourceInstallationListener implements InstallationListener {

        private final AtomicInteger processedBundles = new AtomicInteger(0);
        private final AtomicBoolean doneProcessing = new AtomicBoolean(false);

        private final int count;

        private final String scheme;

        public ResourceInstallationListener(final int count) {
            this(SCHEME, count);
        }

        public ResourceInstallationListener(final String scheme, final int count) {
            this.scheme = scheme;
            this.count = count;
        }

        @Override
        public void onEvent(final InstallationEvent event) {
            if ( event.getType() == InstallationEvent.TYPE.PROCESSED ) {
                final TaskResource rsrc = (TaskResource) event.getSource();
                if ( rsrc.getScheme().equals(this.scheme) ) {
                    if ( rsrc.getState() == ResourceState.IGNORED || rsrc.getState() == ResourceState.INSTALLED ) {
                        processedBundles.incrementAndGet();
                    }
                }
            } else if ( event.getType() == InstallationEvent.TYPE.SUSPENDED && processedBundles.get() > 0 ) {
                doneProcessing.set(true);
            }

        }

        public void waitForInstall() {
            final long startTime = System.currentTimeMillis();
            while ( !doneProcessing.get() && startTime + 10000 > System.currentTimeMillis() ) {
                sleep(200);
            }
            if ( processedBundles.get() < count ) {
                int bundlesCount = 0;
                while ( bundlesCount < count ) {
                    bundlesCount = 0;
                    final InstallationState state = infoProvider.getInstallationState();
                    for(final ResourceGroup group : state.getInstalledResources()) {
                        for(final Resource rsrc : group.getResources()) {
                            if ( rsrc.getScheme().equals(this.scheme) ) {
                                bundlesCount++;
                            }
                        }
                    }
                    for(final ResourceGroup group : state.getActiveResources()) {
                        for(final Resource rsrc : group.getResources()) {
                            if ( rsrc.getScheme().equals(this.scheme) ) {
                                bundlesCount++;
                            }
                        }
                    }
                    sleep(200);
                }
            }
        }
    }
}
