/*
 * 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.fail;
import static org.ops4j.pax.exam.CoreOptions.frameworkProperty;
import static org.ops4j.pax.exam.CoreOptions.junitBundles;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import static org.ops4j.pax.exam.CoreOptions.options;
import static org.ops4j.pax.exam.CoreOptions.provision;
import static org.ops4j.pax.exam.CoreOptions.systemProperty;
import static org.ops4j.pax.exam.CoreOptions.when;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;

import javax.inject.Inject;

import org.apache.sling.installer.api.InstallableResource;
import org.apache.sling.installer.api.OsgiInstaller;
import org.apache.sling.installer.api.ResourceChangeListener;
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.junit.Before;
import org.ops4j.pax.exam.Option;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.FrameworkEvent;
import org.osgi.framework.FrameworkListener;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.SynchronousBundleListener;
import org.osgi.framework.Version;
import org.osgi.framework.namespace.PackageNamespace;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.log.LogService;
import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.util.tracker.ServiceTracker;

/** Base class for OsgiInstaller testing */
public class OsgiInstallerTestBase implements FrameworkListener {
	private final static String POM_VERSION = System.getProperty("osgi.installer.pom.version", "POM_VERSION_NOT_SET");
    private final static String CONFIG_VERSION = System.getProperty("installer.configuration.version", "INSTALLER_VERSION_NOT_SET");

	public final static String JAR_EXT = ".jar";
	private volatile int packageRefreshEventsCount;
	private volatile ServiceTracker configAdminTracker;

	protected volatile OsgiInstaller installer;

    protected volatile ResourceChangeListener resourceChangeListener;

    protected volatile InfoProvider infoProvider;

    private final static long WAIT_FOR_CHANGE_TIMEOUT = 5000L;

    public static final long WAIT_FOR_ACTION_TIMEOUT_MSEC = 6000;
    public static final String BUNDLE_BASE_NAME = "org.apache.sling.installer.it-" + POM_VERSION;

    @Inject
    protected BundleContext bundleContext;

    public static final String URL_SCHEME = "OsgiInstallerTest";

    static abstract class Condition {
    	abstract boolean isTrue() throws Exception;
    	String additionalInfo() { return null; }
    	void onFailure() { }
    	long getMsecBetweenEvaluations() { return 100L; }
    }

    /**
     * Helper method to get a service of the given type
     */
    @SuppressWarnings("unchecked")
	protected <T> T getService(Class<T> clazz) {
    	final ServiceReference ref = bundleContext.getServiceReference(clazz.getName());
    	assertNotNull("getService(" + clazz.getName() + ") must find ServiceReference", ref);
    	final T result = (T)(bundleContext.getService(ref));
    	assertNotNull("getService(" + clazz.getName() + ") must find service", result);
    	return result;
    }

    /** Set up the installer service. */
    protected void setupInstaller() {
        installer = getService(OsgiInstaller.class);
        resourceChangeListener = getService(ResourceChangeListener.class);
        infoProvider = getService(InfoProvider.class);
    }

    @Before
    public void setup() {
        configAdminTracker = new ServiceTracker(bundleContext, ConfigurationAdmin.class.getName(), null);
        configAdminTracker.open();
    }

    /** Tear down everything. */
    public void tearDown() {
        synchronized (this) {
            if (configAdminTracker != null) {
                configAdminTracker.close();
                configAdminTracker = null;
            }
        }
    }

    /**
     * Restart the installer.
     */
    protected void restartInstaller() throws BundleException {
        final String symbolicName = "org.apache.sling.installer.core";
        final Bundle b = findBundle(symbolicName);
        if (b == null) {
            fail("Bundle " + symbolicName + " not found");
        }
        log(LogService.LOG_INFO, "Restarting " + symbolicName + " bundle");
        b.stop();
        b.start();
        setupInstaller();
    }

    protected void generateBundleEvent() throws Exception {
        // install a bundle manually to generate a bundle event
        final File f = getTestBundle("org.apache.sling.installer.it-" + POM_VERSION + "-testbundle-1.0.jar");
        final InputStream is = new FileInputStream(f);
        Bundle b = null;
        try {
            b = bundleContext.installBundle(getClass().getName(), is);
            b.start();
            final long timeout = System.currentTimeMillis() + 2000L;
            while(b.getState() != Bundle.ACTIVE && System.currentTimeMillis() < timeout) {
                sleep(10L);
            }
        } finally {
            is.close();
            if (b != null) {
                b.uninstall();
            }
        }
    }

    /**
     * @see org.osgi.framework.FrameworkListener#frameworkEvent(org.osgi.framework.FrameworkEvent)
     */
    @Override
    public void frameworkEvent(FrameworkEvent event) {
        if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) {
            packageRefreshEventsCount++;
        }
    }

    protected void refreshPackages() {
        bundleContext.addFrameworkListener(this);
        final int MAX_REFRESH_PACKAGES_WAIT_SECONDS = 5;
        final int targetEventCount = packageRefreshEventsCount + 1;
        final long timeout = System.currentTimeMillis() + MAX_REFRESH_PACKAGES_WAIT_SECONDS * 1000L;

        final PackageAdmin pa = getService(PackageAdmin.class);
        pa.refreshPackages(null);

        try {
            while(true) {
                if(System.currentTimeMillis() > timeout) {
                    break;
                }
                if(packageRefreshEventsCount >= targetEventCount) {
                    break;
                }
                sleep(250L);
            }
        } finally {
            bundleContext.removeFrameworkListener(this);
        }
    }

    /**
     * Encode the value for the ldap filter: \, *, (, and ) should be escaped.
     */
    private static String encode(final String value) {
        return value.replace("\\", "\\\\")
                .replace("*", "\\*")
                .replace("(", "\\(")
                .replace(")", "\\)");
    }

    /**
     * Find the configuration with the given pid.
     */
    protected Configuration findConfiguration(final String pid) throws Exception {
    	final ConfigurationAdmin ca = this.waitForConfigAdmin(true);
    	if (ca != null) {
	    	final Configuration[] cfgs = ca.listConfigurations("(" + Constants.SERVICE_PID + "=" + encode(pid) + ")");
	    	if (cfgs != null && cfgs.length > 0 ) {
                if ( cfgs.length == 1 ) {
                    return cfgs[0];
                }
                throw new IllegalStateException("More than one configuration for " + pid);
	    	}
    	}
    	return null;
    }

    /**
     * Find the configuration with the given factory pid.
     */
    protected Configuration findFactoryConfiguration(final String factoryPid) throws Exception {
        final ConfigurationAdmin ca = this.waitForConfigAdmin(true);
        if (ca != null) {
            final Configuration[] cfgs = ca.listConfigurations("("
                    + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + encode(factoryPid) + ")");
            if (cfgs != null && cfgs.length > 0 ) {
                if ( cfgs.length == 1 ) {
                    return cfgs[0];
                }
                throw new IllegalStateException("More than one factory configuration for " + factoryPid);
            }
        }
        return null;
    }

    protected void waitForCondition(String info, Condition c) throws Exception {
        this.waitForCondition(info, c, WAIT_FOR_CHANGE_TIMEOUT);
    }

    protected void waitForCondition(String info, Condition c, final long timeOut) throws Exception {
        final long end = System.currentTimeMillis() + timeOut;
        do {
            if(c.isTrue()) {
                return;
            }
            sleep(c.getMsecBetweenEvaluations());
        } while(System.currentTimeMillis() < end);

        if(c.additionalInfo() != null) {
            info += " " + c.additionalInfo();
        }

        c.onFailure();
        fail("WaitForCondition failed: " + info);
    }

    protected Configuration waitForFactoryConfigValue(final String info,
            final String factoryPid,
            final String key,
            final String value)
    throws Exception {
        final long end = System.currentTimeMillis() + WAIT_FOR_CHANGE_TIMEOUT;
        do {
            final Configuration c = waitForFactoryConfiguration(info, factoryPid, true);
            if (value.equals(c.getProperties().get(key))) {
                return c;
            }
            sleep(100L);
        } while(System.currentTimeMillis() < end);
        fail("Did not get " + key + "=" + value + " for factory config " + factoryPid);
        return null;
    }

    protected Configuration waitForConfigValue(final String info,
            final String pid,
            final String key,
            final String value)
    throws Exception {
        final long end = System.currentTimeMillis() + WAIT_FOR_CHANGE_TIMEOUT;
        do {
        	final Configuration c = waitForConfiguration(info, pid, true);
        	if (value.equals(c.getProperties().get(key))) {
        		return c;
        	}
        	sleep(100L);
        } while(System.currentTimeMillis() < end);
        fail("Did not get " + key + "=" + value + " for config " + pid);
        return null;
    }

    /**
     * Wait for a configuration.
     */
    protected Configuration waitForConfiguration(final String info,
            final String pid,
            final boolean shouldBePresent)
    throws Exception {
        return this.waitForConfiguration(info, pid,  null, shouldBePresent);
    }

    /**
     * Wait for a factory configuration.
     */
    protected Configuration waitForFactoryConfiguration(final String info,
            final String factoryPid,
            final boolean shouldBePresent)
    throws Exception {
        return this.waitForConfiguration(info, null,  factoryPid, shouldBePresent);
    }

    /**
     * Internal method to wait for a configuration
     */
    private Configuration waitForConfiguration(final String info,
            final String pid,
            final String factoryPid,
            final boolean shouldBePresent)
    throws Exception {
        final String logKey = factoryPid == null ? "config" : "factory config";
        String msg;
        if (info == null) {
            msg = "";
        } else {
            msg = info + ": ";
        }

        Configuration result = null;
        final long start = System.currentTimeMillis();
        final long end = start + WAIT_FOR_CHANGE_TIMEOUT;
        log(LogService.LOG_DEBUG, "Starting " + logKey + " check at " + start + "; ending by " + end);
        do {
            if ( factoryPid != null ) {
                result = findFactoryConfiguration(factoryPid);
            } else {
                result = findConfiguration(pid);
            }
            if ((shouldBePresent && result != null) ||
                    (!shouldBePresent && result == null)) {
                break;
            }
            log(LogService.LOG_DEBUG, logKey + " check failed at " + System.currentTimeMillis() + "; sleeping");
            sleep(25);
        } while(System.currentTimeMillis() < end);

        if (shouldBePresent && result == null) {
            fail(msg + logKey + " not found (" + (factoryPid != null ? factoryPid : pid) + ")");
        } else if (!shouldBePresent && result != null) {
            fail(msg + logKey + " is still present (" + (factoryPid != null ? factoryPid : pid) + ")");
        }
        return result;
    }

    protected Bundle findBundle(String symbolicName) {
    	for(Bundle b : bundleContext.getBundles()) {
    		if (symbolicName.equals(b.getSymbolicName())) {
    			return b;
    		}
    	}
    	return null;
    }

    protected Bundle assertBundle(String info, String symbolicName, String version, int state) {
        final Bundle b = findBundle(symbolicName);
        if(info == null) {
            info = "";
        } else {
            info += ": ";
        }
        assertNotNull(info + "Expected bundle " + symbolicName + " to be installed", b);
        if(version != null) {
            assertEquals(info + "Expected bundle " + symbolicName + " to be version " + version,
                    version, b.getHeaders().get(Constants.BUNDLE_VERSION));
        }
        if(state >= 0) {
            assertEquals(info + "Expected bundle " + symbolicName + " to be in state " + state,
                    state, b.getState());
        }
        return b;
    }

    protected File getTestBundle(String bundleName) {
    	return new File(System.getProperty("osgi.installer.base.dir"), bundleName);
    }

    protected InstallableResource[] getInstallableResource(File testBundle) throws IOException {
        return getInstallableResource(testBundle, null);
    }

    protected String[] getNonInstallableResourceUrl(File testBundle) throws IOException {
    	return new String[] {testBundle.getAbsolutePath()};
    }

    protected InstallableResource[] getInstallableResource(File testBundle, String digest) throws IOException {
        return getInstallableResource(testBundle, digest, InstallableResource.DEFAULT_PRIORITY);
    }

    protected InstallableResource[] getInstallableResource(File testBundle, String digest, int priority) throws IOException {
        final String url = testBundle.getAbsolutePath();
        if (digest == null) {
            digest = String.valueOf(testBundle.lastModified());
        }
        final InstallableResource result = new MockInstallableResource(url, new FileInputStream(testBundle), digest, null, priority);
        return new InstallableResource[] {result};
    }

    protected InstallableResource[] getInstallableResource(String configPid, Dictionary<String, Object> data) {
        return getInstallableResource(configPid, copy(data), InstallableResource.DEFAULT_PRIORITY);
    }

    protected InstallableResource[] getInstallableResource(String configPid, Dictionary<String, Object> data, int priority) {
        final InstallableResource result = new MockInstallableResource("/" + configPid, copy(data), null, null, priority);
        return new InstallableResource[] {result};
    }

    protected Dictionary<String, Object> copy(Dictionary<String, Object> data) {
        final Dictionary<String, Object> copy = new Hashtable<String, Object>();
        final Enumeration<String> keys = data.keys();
        while(keys.hasMoreElements()) {
            final String key = keys.nextElement();
            copy.put(key, data.get(key));
        }
        return copy;
    }

    protected ConfigurationAdmin waitForConfigAdmin(final boolean shouldBePresent) {
    	ConfigurationAdmin result = null;

        final int timeout = 5;
    	final long waitUntil = System.currentTimeMillis() + (timeout * 1000L);
    	boolean isPresent;
    	do {
    		result = (ConfigurationAdmin)configAdminTracker.getService();
    		isPresent = result != null;
    		if ( shouldBePresent == isPresent ) {
    		    return result;
    		}
    	} while(System.currentTimeMillis() < waitUntil);

        assertEquals("Expected ConfigurationAdmin to be " + (shouldBePresent ? "present" : "absent"),
                shouldBePresent, isPresent);
    	return result;
    }

    protected Bundle getConfigAdminBundle() {
        this.waitForConfigAdmin(true);
        return this.configAdminTracker.getServiceReference().getBundle();
    }

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

    protected void log(int level, String msg) {
    	final LogService log = getService(LogService.class);
    	log.log(level, msg);
    }

    protected String requiredServices() {
        return "resourcetransformer:org.osgi.service.cm,installtaskfactory:org.osgi.service.cm";
    }

    protected Option[] defaultConfiguration() {
    	String vmOpt = "-Dosgi.installer.testing";

    	// This runs in the VM that runs the build, but the tests run in another one.
    	// Make all osgi.installer.* system properties available to OSGi framework VM
    	for(Object o : System.getProperties().keySet()) {
    		final String key = (String)o;
    		if(key.startsWith("osgi.installer.")) {
    			vmOpt += " -D" + key + "=" + System.getProperty(key);
    		}
    	}

    	// optional debugging
    	final String paxDebugLevel = System.getProperty("pax.exam.log.level", "INFO");

    	String localRepo = System.getProperty("maven.repo.local", "");

    	return options(

                junitBundles(),
                when( localRepo.length() > 0 ).useOptions(
                        systemProperty("org.ops4j.pax.url.mvn.localRepository").value(localRepo)
                ),
                systemProperty( "org.ops4j.pax.logging.DefaultServiceLog.level" ).value(paxDebugLevel),
                frameworkProperty("sling.installer.requiredservices").value(requiredServices()),
                provision(
                        mavenBundle("org.apache.sling", "org.apache.sling.commons.log", "4.0.6"),
                        mavenBundle("org.apache.sling", "org.apache.sling.commons.logservice", "1.0.6"),

                        mavenBundle("org.slf4j", "slf4j-api", "1.7.5"),
                        mavenBundle("org.slf4j", "jcl-over-slf4j", "1.7.5"),
                        mavenBundle("org.slf4j", "log4j-over-slf4j", "1.7.5"),

        	            mavenBundle("org.apache.felix", "org.apache.felix.scr", "2.0.6"),
        	            mavenBundle("org.apache.felix", "org.apache.felix.configadmin", "1.8.12"),
                        mavenBundle("org.apache.felix", "org.apache.felix.metatype", "1.1.2"),
        	        	mavenBundle("org.apache.sling", "org.apache.sling.installer.core", POM_VERSION).startLevel(5),
                        mavenBundle("org.apache.sling", "org.apache.sling.installer.factory.configuration", CONFIG_VERSION).startLevel(5)
        		)
        );
    }

    protected Object startObservingBundleEvents() {
        final BundleEventListener listener = new BundleEventListener();
        this.bundleContext.addBundleListener(listener);
        return listener;
    }

    public static final class BundleEvent {
        public final String symbolicName;
        public final Version version;
        public final int    state;

        public BundleEvent(final String sn, final String v, final int s) {
            this.symbolicName = sn;
            this.version = (v == null ? null : Version.parseVersion(v));
            this.state = s;
        }

        public BundleEvent(final String sn, final int s) {
            this(sn, null, s);
        }

        @Override
        public String toString() {
            return "BundleEvent " + symbolicName + ", version=" + version + ", state="+state;
        }
    }

    protected void waitForBundleEvents(final String msg, final Object l, BundleEvent... events)
    throws Exception {
        final BundleEventListener listener = (BundleEventListener)l;
        try {
            listener.wait(msg, events, WAIT_FOR_ACTION_TIMEOUT_MSEC);
        } finally {
            this.bundleContext.removeBundleListener(listener);
        }
    }

    protected void waitForBundleEvents(final String msg, final Object l, long timeout, BundleEvent... events)
    throws Exception {
        final BundleEventListener listener = (BundleEventListener)l;
        try {
            listener.wait(msg, events, timeout);
        } finally {
            this.bundleContext.removeBundleListener(listener);
        }
    }

    protected void assertNoBundleEvents(final String msg, final Object l, final String symbolicName) {
        final BundleEventListener listener = (BundleEventListener)l;
        try {
            listener.assertNoBundleEvents(msg, symbolicName);
        } finally {
            this.bundleContext.removeBundleListener(listener);
        }
    }

    protected boolean isPackageExported(Bundle b, String packageName) {
        final BundleWiring wiring = b.adapt(BundleWiring.class);
        assertNotNull("Expecting non-null BundleWiring for bundle " + b, wiring);
        for(BundleCapability c : wiring.getCapabilities(PackageNamespace.PACKAGE_NAMESPACE)) {
            if(packageName.equals(c.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE))) {
                return true;
            }
        }
        return false;
    }

    public void logInstalledBundles() {
        for(Bundle b : bundleContext.getBundles()) {
            log(LogService.LOG_DEBUG, "Installed bundle: " + b.getSymbolicName());
        }
    }

    protected Resource waitForResource(final String url,
            final ResourceState state) {
        final long start = System.currentTimeMillis();
        final long end = start + WAIT_FOR_CHANGE_TIMEOUT;

        do {
            final InstallationState is = this.infoProvider.getInstallationState();
            for(final ResourceGroup rg : (state == ResourceState.INSTALL || state == ResourceState.UNINSTALL ? is.getActiveResources() : is.getInstalledResources())) {
                for(final Resource rsrc : rg.getResources()) {
                    if ( url.equals(rsrc.getURL()) ) {
                        if ( rsrc.getState() == state ) {
                            return rsrc;
                        }
                    }
                }
            }
            sleep(50);
        } while ( System.currentTimeMillis() < end);
        fail("Resource " + url + " not found with state " + state + " : " + this.infoProvider.getInstallationState());
        return null;
    }

    private final class BundleEventListener implements SynchronousBundleListener {

        private final List<BundleEvent> events = new ArrayList<BundleEvent>();

        @Override
        public void bundleChanged(org.osgi.framework.BundleEvent event) {
            synchronized ( this ) {
                events.add(new BundleEvent(event.getBundle().getSymbolicName(), event.getBundle().getVersion().toString(), event.getType()));
            }
        }

        public void wait(final String msg, final BundleEvent[] checkEvents, final long timeoutMsec)
        throws Exception {
            if ( checkEvents == null || checkEvents.length == 0 ) {
                return;
            }
            final long start = System.currentTimeMillis();
            final long end = start + timeoutMsec;
            log(LogService.LOG_DEBUG, "Starting event check at " + start + "; ending by " + end);
            while ( System.currentTimeMillis() < end ) {
                synchronized ( this) {
                    if ( this.events.size() >= checkEvents.length ) {
                        int found = 0;
                        for(final BundleEvent e : checkEvents ) {
                            int startIndex = 0;
                            final int oldFound = found;
                            while ( oldFound == found && startIndex < this.events.size() ) {
                                final BundleEvent bundleEvent = this.events.get(startIndex);
                                // first check symbolic name
                                if ( e.symbolicName == null || e.symbolicName.equals(bundleEvent.symbolicName) ) {
                                    if ( e.version == null || e.version.equals(bundleEvent.version) ) {
                                        if ( e.state == bundleEvent.state ) {
                                            found++;
                                        }
                                    }
                                }
                                if ( oldFound == found ) {
                                    startIndex++;
                                }
                            }
                        }
                        if ( found == checkEvents.length ) {
                            return;
                        }
                    }
                }
                sleep(100);
            }
            logInstalledBundles();
            final StringBuilder sb = new StringBuilder();
            sb.append(msg);
            sb.append(" : Expected events=[\n");
            for(final BundleEvent be : checkEvents) {
                sb.append(be);
                sb.append("\n");
            }
            sb.append("]\nreceived events=[\n");
            for(final BundleEvent be : this.events) {
                sb.append(be);
                sb.append("\n");
            }
            sb.append("]\n");
            fail(sb.toString());
        }

        public void assertNoBundleEvents(final String msg, final String symbolicName) {
            boolean found = false;
            synchronized ( this ) {
                if ( symbolicName == null ) {
                    found = this.events.size() > 0;
                } else {
                    for(BundleEvent e : this.events ) {
                        if ( symbolicName.equals(e.symbolicName) ) {
                            found = true;
                            break;
                        }
                    }
                }
            }
            if ( found ) {
                fail(msg + " : Expected to receive no bundle events for bundle " + symbolicName);
            }
        }
    }
}
