/*
 * 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.ace.it;

import static java.util.concurrent.TimeUnit.SECONDS;
import static org.apache.ace.test.utils.Util.properties;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import junit.framework.TestCase;

import org.apache.felix.dm.Component;
import org.apache.felix.dm.ComponentDependencyDeclaration;
import org.apache.felix.dm.ComponentStateListener;
import org.apache.felix.dm.DependencyManager;
import org.apache.felix.dm.ServiceDependency;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.util.tracker.ServiceTracker;

import aQute.bnd.annotation.ConsumerType;

/**
 * Base class for integration tests. There is no technical reason to use this, but it might make
 * your life easier.<br>
 * <br>
 * {@link org.apache.ace.it.ExampleTest} shows a minimal example of an integration test.
 *
 */
@ConsumerType
public class IntegrationTestBase extends TestCase {
    private static class ComponentCounter implements ComponentStateListener {
        private final List<Component> m_components = new ArrayList<Component>();
        private final CountDownLatch m_latch;

        public ComponentCounter(Component[] components) {
            m_components.addAll(Arrays.asList(components));
            m_latch = new CountDownLatch(components.length);
        }

        public String componentsString() {
            StringBuilder result = new StringBuilder();
            for (Component component : m_components) {
                result.append(component).append('\n');
                for (ComponentDependencyDeclaration dependency : (List<ComponentDependencyDeclaration>) component.getDependencies()) {
                    result.append("  ")
                            .append(dependency.toString())
                            .append(" ")
                            .append(ComponentDependencyDeclaration.STATE_NAMES[dependency.getState()])
                            .append('\n');
                }
                result.append('\n');
            }
            return result.toString();
        }

        public void started(Component component) {
            m_components.remove(component);
            m_latch.countDown();
        }

        public void starting(Component component) {
        }

        public void stopped(Component component) {
        }

        public void stopping(Component component) {
        }

        public boolean waitForEmpty(long timeout, TimeUnit unit) throws InterruptedException {
            return m_latch.await(timeout, unit);
        }
    }
    
    /**
     * If we have to wait for a service, wait this amount of seconds.
     */
    private static final int SERVICE_TIMEOUT = 5;
    protected BundleContext m_bundleContext;

    protected DependencyManager m_dependencyManager;

    /**
     * The 'after' callback will be called after all components from {@link #getDependencies} have been
     * started.<br>
     * <br>
     * The {@link #after} callback is most useful for configuring additional services after all mandatory 
     * services are resolved.
     */
    protected void configureAdditionalServices() throws Exception {}

    /**
     * The 'before' callback will be called after the components from {@link #getDependencies} have been
     * added, but you cannot necessarily rely on injected members here. You can use the {@link #configure} and
     * {@link #configureFactory} methods, as well as the {@link #getService} methods.<br>
     * <br>
     * The {@link #before} callback is most useful for configuring services that have been provisioned
     * in the 'configuration' method.
     */
    protected void configureProvisionedServices() throws Exception {}

    /**
     * Write configuration for a single service. For example,
     * <pre>
     *   configure("org.apache.felix.http",
     *     "org.osgi.service.http.port", "1234");
     * </pre>
     */
    protected void configure(String pid, String... configuration) throws IOException {
        Properties props = properties(configuration);
        Configuration config = getConfiguration(pid);
        config.update(props);
    }

    /**
     * Creates a factory configuration with the given properties, just like {@link #configure}.
     * @return The PID of newly created configuration.
     */
    protected String configureFactory(String factoryPid, String... configuration) throws IOException {
        Properties props = properties(configuration);
        Configuration config = createFactoryConfiguration(factoryPid);
        config.update(props);
        return config.getPid();
    }
    
    /**
     * Bridge method for dependency manager.
     * 
     * @return a new {@link Component}.
     */
    protected Component createComponent() {
        return m_dependencyManager.createComponent();
    }
    
    /**
     * Creates a new factory configuration.
     * 
     * @param factoryPid the PID of the factory to create a new configuration for.
     * @return a new {@link Configuration} object, never <code>null</code>.
     * @throws IOException if access to the persistent storage failed.
     */
    protected Configuration createFactoryConfiguration(String factoryPid) throws IOException {
        ConfigurationAdmin admin = getService(ConfigurationAdmin.class);
        return admin.createFactoryConfiguration(factoryPid, null);
    }

    /**
     * Bridge method for dependency manager.
     * 
     * @return a new {@link ServiceDependency}.
     */
    protected ServiceDependency createServiceDependency() {
        return m_dependencyManager.createServiceDependency();
    }

    /**
     * Gets an existing configuration or creates a new one, in case it does not exist.
     * 
     * @param pid the PID of the configuration to return.
     * @return a {@link Configuration} instance, never <code>null</code>.
     * @throws IOException if access to the persistent storage failed.
     */
    protected Configuration getConfiguration(String pid) throws IOException {
        ConfigurationAdmin admin = getService(ConfigurationAdmin.class);
        return admin.getConfiguration(pid, null);
    }

    /**
     * Gets a list of components that must be started before the test is started; this useful to
     * (a) add additional services, e.g. services that should be picked up by the service under
     * test, or (b) to declare 'this' as a component, and get services injected.
     */
    protected Component[] getDependencies() {
        return new Component[0];
    }

    /**
     * Returns a list of strings representing the result of the given request URL.
     * 
     * @param requestURL the URL to access and return the response as strings.
     * @return a list of strings, never <code>null</code>.
     * @throws IOException in case accessing the requested URL failed.
     */
    protected List<String> getResponse(String requestURL) throws IOException {
    	return getResponse(new URL(requestURL));
    }

    /**
     * Returns a list of strings representing the result of the given request URL.
     * 
     * @param requestURL the URL to access and return the response as strings.
     * @return a list of strings, never <code>null</code>.
     * @throws IOException in case accessing the requested URL failed.
     */
    protected List<String> getResponse(URL requestURL) throws IOException {
        List<String> result = new ArrayList<String>();
        InputStream in = null;
        try {
            in = requestURL.openConnection().getInputStream();
            byte[] response = new byte[in.available()];
            in.read(response);

            final StringBuilder element = new StringBuilder();
            for (byte b : response) {
                switch(b) {
                    case '\n' :
                        result.add(element.toString());
                        element.delete(0, element.length());
                        break;
                    default :
                        element.append((char) b);
                }
            }
            if (element.length() > 0) {
            	result.add(element.toString());
            }
        }
        finally {
            try {
                in.close();
            }
            catch (Exception e) {
                // no problem.
            }
        }
        return result;
    }

    /**
     * Convenience method to return an OSGi service.
     * 
     * @param serviceClass the service class to return.
     * @return a service instance, can be <code>null</code>.
     */
    protected <T> T getService(Class<T> serviceClass) {
        try {
            return getService(serviceClass, null);
        }
        catch (InvalidSyntaxException e) {
            return null;
            // Will not happen, since we don't pass in a filter.
        }
    }

    /**
     * Convenience method to return an OSGi service.
     * 
     * @param serviceClass the service class to return;
     * @param filterString the (optional) filter string, can be <code>null</code>.
     * @return a service instance, can be <code>null</code>.
     */
    @SuppressWarnings("unchecked")
    protected <T> T getService(Class<T> serviceClass, String filterString) throws InvalidSyntaxException {
        T serviceInstance = null;

        ServiceTracker serviceTracker;
        if (filterString == null) {
            serviceTracker = new ServiceTracker(m_bundleContext, serviceClass.getName(), null);
        }
        else {
            String classFilter = "(" + Constants.OBJECTCLASS + "=" + serviceClass.getName() + ")";
            filterString = "(&" + classFilter + filterString + ")";
            serviceTracker = new ServiceTracker(m_bundleContext, m_bundleContext.createFilter(filterString), null);
        }
        serviceTracker.open();
        try {
            serviceInstance = (T) serviceTracker.waitForService(SERVICE_TIMEOUT * 1000);

            if (serviceInstance == null) {
                fail(serviceClass + " service not found.");
            }
            else {
                return serviceInstance;
            }
        }
        catch (InterruptedException e) {
            e.printStackTrace();
            fail(serviceClass + " service not available: " + e.toString());
        }

        return serviceInstance;
    }

    /**
     * Set up of this test case.
     */
    protected final void setUp() throws Exception {
    	m_bundleContext = FrameworkUtil.getBundle(getClass()).getBundleContext();
        m_dependencyManager = new DependencyManager(m_bundleContext);

        Component[] components = getDependencies();
        ComponentCounter listener = new ComponentCounter(components);

        // Register our listener for all the services...
        for (Component component : components) {
            component.addStateListener(listener);
        }

        // Then give them to the dependency manager...
        for (Component component : components) {
            m_dependencyManager.add(component);
        }

		// Call back the implementation...
		configureProvisionedServices();

        // And wait for all components to come online.
        try {
            if (!listener.waitForEmpty(SERVICE_TIMEOUT, SECONDS)) {
                fail("Not all components were started. Still missing the following:\n" + listener.componentsString());
            }
            
        	configureAdditionalServices();
        	
            // Wait for CM to settle or we may get "socket closed" due to HTTP service restarts
            System.out.println("Sleeping...");
            Thread.sleep(2000);
        }
        catch (InterruptedException e) {
            fail("Interrupted while waiting for services to get started.");
        }
    }
}
