/*
 * 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.felix.http.itest;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.ops4j.pax.exam.Constants.START_LEVEL_SYSTEM_BUNDLES;
import static org.ops4j.pax.exam.Constants.START_LEVEL_TEST_BUNDLE;
import static org.ops4j.pax.exam.CoreOptions.frameworkStartLevel;
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.systemProperty;
import static org.ops4j.pax.exam.CoreOptions.when;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collection;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;

import javax.inject.Inject;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.junit.After;
import org.junit.Before;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.Option;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.NamespaceException;
import org.osgi.util.tracker.ServiceTracker;

/**
 * Base class for integration tests.
 *
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
public abstract class BaseIntegrationTest
{
    protected static class TestFilter implements Filter
    {
        private final CountDownLatch m_initLatch;
        private final CountDownLatch m_destroyLatch;

        public TestFilter()
        {
            this(null, null);
        }

        public TestFilter(CountDownLatch initLatch, CountDownLatch destroyLatch)
        {
            m_initLatch = initLatch;
            m_destroyLatch = destroyLatch;
        }

        @Override
        public void destroy()
        {
            if (m_destroyLatch != null)
            {
                m_destroyLatch.countDown();
            }
        }

        @Override
        public final void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException
        {
            filter((HttpServletRequest) req, (HttpServletResponse) resp, chain);
        }

        @Override
        public void init(FilterConfig config) throws ServletException
        {
            if (m_initLatch != null)
            {
                m_initLatch.countDown();
            }
        }

        protected void filter(HttpServletRequest req, HttpServletResponse resp, FilterChain chain) throws IOException, ServletException
        {
            resp.setStatus(HttpServletResponse.SC_OK);
        }
    }

    protected static class TestServlet extends HttpServlet
    {
        private static final long serialVersionUID = 1L;

        private final CountDownLatch m_initLatch;
        private final CountDownLatch m_destroyLatch;

        public TestServlet()
        {
            this(null, null);
        }

        public TestServlet(CountDownLatch initLatch, CountDownLatch destroyLatch)
        {
            m_initLatch = initLatch;
            m_destroyLatch = destroyLatch;
        }

        @Override
        public void destroy()
        {
            super.destroy();
            if (m_destroyLatch != null)
            {
                m_destroyLatch.countDown();
            }
        }

        @Override
        public void init() throws ServletException
        {
            super.init();
            if (m_initLatch != null)
            {
                m_initLatch.countDown();
            }
        }

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
        {
            resp.setStatus(HttpServletResponse.SC_OK);
        }
    }

    protected static final int DEFAULT_TIMEOUT = 10000;

    private static final String ORG_APACHE_FELIX_HTTP_JETTY = "org.apache.felix.http.jetty";

    protected static void assertContent(int expectedRC, String expected, URL url) throws IOException
    {
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();

        int rc = conn.getResponseCode();
        assertEquals("Unexpected response code,", expectedRC, rc);

        if (rc >= 200 && rc < 500)
        {
            InputStream is = null;
            try
            {
                is = conn.getInputStream();
                assertEquals(expected, slurpAsString(is));
            }
            finally
            {
                close(is);
                conn.disconnect();
            }
        }
        else
        {
            InputStream is = null;
            try
            {
                is = conn.getErrorStream();
                assertEquals(expected, slurpAsString(is));
            }
            finally
            {
                close(is);
                conn.disconnect();
            }
        }
    }

    protected static void assertContent(String expected, URL url) throws IOException
    {
        assertContent(200, expected, url);
    }

    protected static void assertResponseCode(int expected, URL url) throws IOException
    {
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        try
        {
            assertEquals(expected, conn.getResponseCode());
        }
        finally
        {
            conn.disconnect();
        }
    }

    protected static void close(Closeable resource)
    {
        if (resource != null)
        {
            try
            {
                resource.close();
            }
            catch (IOException e)
            {
                // Ignore...
            }
        }
    }

    protected static Dictionary<String, ?> createDictionary(Object... entries)
    {
        Dictionary<String, Object> props = new Hashtable<>();
        for (int i = 0; i < entries.length; i += 2)
        {
            String key = (String) entries[i];
            Object value = entries[i + 1];
            props.put(key, value);
        }
        return props;
    }

    protected static URL createURL(String path)
    {
        if (path == null)
        {
            path = "";
        }
        while (path.startsWith("/"))
        {
            path = path.substring(1);
        }
        int port = Integer.getInteger("org.osgi.service.http.port", 8080);
        try
        {
            return new URL(String.format("http://localhost:%d/%s", port, path));
        }
        catch (MalformedURLException e)
        {
            throw new RuntimeException(e);
        }
    }

    protected static String slurpAsString(InputStream is) throws IOException
    {
        // See <weblogs.java.net/blog/pat/archive/2004/10/stupid_scanner_1.html>
        Scanner scanner = new Scanner(is, "UTF-8");
        try
        {
            scanner.useDelimiter("\\A");

            return scanner.hasNext() ? scanner.next() : null;
        }
        finally
        {
            try
            {
                scanner.close();
            }
            catch (Exception e)
            {
                // Ignore...
            }
        }
    }

    @Inject
    protected volatile BundleContext m_context;

    @Configuration
    public Option[] config()
    {
        final String localRepo = System.getProperty("maven.repo.local", "");

        return options(
                when( localRepo.length() > 0 ).useOptions(
                        systemProperty("org.ops4j.pax.url.mvn.localRepository").value(localRepo)
                        ),
                //            CoreOptions.vmOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8787"),

                // scavenge sessions every 10 seconds (10 minutes is default in 9.4.x)
                systemProperty("org.eclipse.jetty.servlet.SessionScavengingInterval").value("10"),
                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.sling", "org.apache.sling.commons.log", "4.0.0"),
                mavenBundle("org.apache.sling", "org.apache.sling.commons.logservice", "1.0.2"),

                mavenBundle("org.apache.geronimo.specs", "geronimo-json_1.0_spec", "1.0-alpha-1").startLevel(START_LEVEL_SYSTEM_BUNDLES),
                mavenBundle("org.apache.johnzon", "johnzon-core", "1.0.0").startLevel(START_LEVEL_SYSTEM_BUNDLES),

                mavenBundle("org.apache.felix", "org.apache.felix.configadmin").version("1.8.14").startLevel(START_LEVEL_SYSTEM_BUNDLES),
                mavenBundle("org.apache.felix", "org.apache.felix.http.servlet-api", System.getProperty("http.servlet.api.version")).startLevel(START_LEVEL_SYSTEM_BUNDLES),
                mavenBundle("org.apache.felix", ORG_APACHE_FELIX_HTTP_JETTY, System.getProperty("http.jetty.version")).startLevel(START_LEVEL_SYSTEM_BUNDLES),
                mavenBundle("org.apache.felix", "org.apache.felix.http.whiteboard", "4.0.0").startLevel(START_LEVEL_SYSTEM_BUNDLES),

                mavenBundle("org.apache.httpcomponents", "httpcore-osgi", "4.4.6").startLevel(START_LEVEL_SYSTEM_BUNDLES),
                mavenBundle("org.apache.httpcomponents", "httpclient-osgi", "4.5.3").startLevel(START_LEVEL_SYSTEM_BUNDLES),
                mavenBundle("org.mockito", "mockito-all", "1.10.19").startLevel(START_LEVEL_SYSTEM_BUNDLES),
                mavenBundle("org.objenesis", "objenesis", "2.6").startLevel(START_LEVEL_SYSTEM_BUNDLES),

                junitBundles(),
                frameworkStartLevel(START_LEVEL_TEST_BUNDLE));
    }

    private final Map<String, ServiceTracker<?, ?>> trackers = new HashMap<>();

    @Before
    public void setUp() throws Exception
    {
        assertNotNull("No bundle context?!", m_context);
    }

    @After
    public void tearDown() throws Exception
    {
        synchronized ( trackers )
        {
            for(final Map.Entry<String, ServiceTracker<?, ?>> entry : trackers.entrySet())
            {
                entry.getValue().close();
            }
            trackers.clear();
        }
        Bundle bundle = getHttpJettyBundle();
        // Restart the HTTP-service to clean all registrations...
        if (bundle.getState() == Bundle.ACTIVE)
        {
            bundle.stop();
            bundle.start();
        }
    }

    /**
     * Waits for a service to become available in certain time interval.
     * @param serviceName
     * @return
     * @throws Exception
     */
    protected <T> T awaitService(String serviceName) throws Exception
    {
        ServiceTracker<T, T> tracker = null;
        tracker = getTracker(serviceName);
        return tracker.waitForService(DEFAULT_TIMEOUT);
    }

    /**
     * Return an array of {@code ServiceReference}s for all services for the
     * given serviceName
     * @param serviceName
     * @return Array of {@code ServiceReference}s or {@code null} if no services
     *         are being tracked.
     */
    protected <T> ServiceReference<T>[] getServiceReferences(String serviceName)
    {
        ServiceTracker<T, T> tracker = getTracker(serviceName);
        return tracker.getServiceReferences();
    }

    private <T> ServiceTracker<T, T> getTracker(String serviceName)
    {
        synchronized ( this.trackers )
        {
            ServiceTracker<?, ?> tracker = trackers.get(serviceName);
            if ( tracker == null )
            {
                tracker = new ServiceTracker<T, T>(m_context, serviceName, null);
                trackers.put(serviceName, tracker);
                tracker.open();
            }
            return (ServiceTracker<T, T>) tracker;
        }
    }

    protected void configureHttpService(Dictionary<String, ?> props) throws Exception
    {
        final String pid = "org.apache.felix.http";

        final Collection<ServiceReference<ManagedService>> serviceRefs = m_context.getServiceReferences(ManagedService.class, String.format("(%s=%s)", Constants.SERVICE_PID, pid));
        assertNotNull("Unable to obtain managed configuration for " + pid, serviceRefs);
        assertFalse("Unable to obtain managed configuration for " + pid, serviceRefs.isEmpty());

        for (final ServiceReference<ManagedService> serviceRef : serviceRefs)
        {
            ManagedService service = m_context.getService(serviceRef);
            try
            {
                service.updated(props);
            }
            catch (ConfigurationException ex)
            {
                fail("Invalid configuration provisioned: " + ex.getMessage());
            }
            finally
            {
                m_context.ungetService(serviceRef);
            }
        }
    }

    /**
     * @param bsn
     * @return
     */
    protected Bundle findBundle(String bsn)
    {
        for (Bundle bundle : m_context.getBundles())
        {
            if (bsn.equals(bundle.getSymbolicName()))
            {
                return bundle;
            }
        }
        return null;
    }

    protected Bundle getHttpJettyBundle()
    {
        Bundle b = findBundle(ORG_APACHE_FELIX_HTTP_JETTY);
        assertNotNull("Filestore bundle not found?!", b);
        return b;
    }

    protected HttpService getHttpService()
    {
        return getService(HttpService.class.getName());
    }

    /**
     * Obtains a service without waiting for it to become available.
     * @param serviceName
     * @return
     */
    protected <T> T getService(final String serviceName)
    {
        ServiceTracker<?, ?> tracker = null;
        synchronized ( this.trackers )
        {
            tracker = trackers.get(serviceName);
            if ( tracker == null )
            {
                tracker = new ServiceTracker(m_context, serviceName, null);
                trackers.put(serviceName, tracker);
                tracker.open();
            }
        }
        return (T) tracker.getService();
    }

    protected void register(String alias, Servlet servlet) throws ServletException, NamespaceException
    {
        register(alias, servlet, null);
    }

    protected void register(String alias, Servlet servlet, HttpContext context) throws ServletException, NamespaceException
    {
        getHttpService().registerServlet(alias, servlet, null, context);
    }

    protected void register(String alias, String name) throws ServletException, NamespaceException
    {
        register(alias, name, null);
    }

    protected void register(String alias, String name, HttpContext context) throws ServletException, NamespaceException
    {
        getHttpService().registerResources(alias, name, context);
    }


    protected void unregister(String alias) throws ServletException, NamespaceException
    {
        getHttpService().unregister(alias);
    }
}
