/**
 * 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.cxf.dosgi.itests.multi;

import static org.ops4j.pax.exam.CoreOptions.composite;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import static org.ops4j.pax.exam.CoreOptions.systemProperty;
import static org.ops4j.pax.exam.cm.ConfigurationAdminOptions.newConfiguration;

import java.io.File;
import java.io.IOException;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
import java.util.Collection;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeoutException;

import javax.inject.Inject;

import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.ops4j.pax.exam.CoreOptions;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.cm.ConfigurationAdminOptions;
import org.ops4j.pax.exam.options.MavenArtifactProvisionOption;
import org.ops4j.pax.exam.options.extra.VMOption;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.ServiceReference;

public class AbstractDosgiTest {
    static final int ZK_PORT = 35101;
    static final int HTTP_PORT = 8989;
    static final String HTTP_HOST = "localhost"; // can specify specific bound IP
    static final String HTTP_BASE_URI = "http://" + HTTP_HOST + ":" + HTTP_PORT;
    private static final int TIMEOUT = 20;
    
    @Inject
    BundleContext bundleContext;
    
    @BeforeClass
    public static void log() {
        System.out.println("-----------------------------------------------------------------");
    }
    
    public <T> T tryTo(String message, Callable<T> func) throws TimeoutException {
        return tryTo(message, func, 5000);
    }
    
    public <T> T tryTo(String message, Callable<T> func, long timeout) throws TimeoutException {
        Throwable lastException = null;
        long startTime = System.currentTimeMillis();
        while (System.currentTimeMillis() - startTime < timeout) {
            try {
                T result = func.call();
                if (result != null) {
                    return result;
                }
                lastException = null;
            } catch (Throwable e) {
                lastException = e;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                continue;
            }
        }
        TimeoutException ex = new TimeoutException("Timeout while trying to " + message);
        if (lastException != null) {
            ex.addSuppressed(lastException);
        }
        throw ex;
    }
    

    /**
     * Sleeps for a short interval, throwing an exception if timeout has been reached. Used to facilitate a
     * retry interval with timeout when used in a loop.
     *
     * @param startTime the start time of the entire operation in milliseconds
     * @param timeout the timeout duration for the entire operation in seconds
     * @param message the error message to use when timeout occurs
     * @throws InterruptedException if interrupted while sleeping
     */
    private static void sleepOrTimeout(long startTime, long timeout, String message)
        throws InterruptedException, TimeoutException {
        timeout *= 1000; // seconds to millis
        long elapsed = System.currentTimeMillis() - startTime;
        long remaining = timeout - elapsed;
        if (remaining <= 0) {
            throw new TimeoutException(message);
        }
        long interval = Math.min(remaining, 1000);
        Thread.sleep(interval);
    }

    @SuppressWarnings({
                       "rawtypes", "unchecked"
    })
    protected ServiceReference waitService(BundleContext bc, Class cls, String filter, int timeout)
        throws Exception {
        System.out.println("Waiting for service: " + cls + " " + filter);
        long startTime = System.currentTimeMillis();
        while (true) {
            Collection refs = bc.getServiceReferences(cls, filter);
            if (refs != null && refs.size() > 0) {
                return (ServiceReference)refs.iterator().next();
            }
            sleepOrTimeout(startTime, timeout, "Service not found: " + cls + " " + filter);
        }
    }

    protected void waitPort(int port) throws Exception {
        System.out.println("Waiting for server to appear on port: " + port);
        long startTime = System.currentTimeMillis();
        while (true) {
            Socket s = null;
            try {
                s = new Socket((String)null, port);
                // yep, its available
                System.out.println("Port: " + port + " is listening now");
                return;
            } catch (IOException e) {
                sleepOrTimeout(startTime, TIMEOUT, "Timeout waiting for port " + port);
            } finally {
                if (s != null) {
                    try {
                        s.close();
                    } catch (IOException e) {
                        // ignore
                    }
                }
            }
        }
    }

    protected Bundle getBundleByName(BundleContext bc, String name) {
        for (Bundle bundle : bc.getBundles()) {
            if (bundle.getSymbolicName().equals(name)) {
                return bundle;
            }
        }
        return null;
    }

    protected static int getFreePort() {
        try (ServerSocket socket = new ServerSocket()) {
            socket.setReuseAddress(true); // enables quickly reopening socket on same port
            socket.bind(new InetSocketAddress(0)); // zero finds a free port
            return socket.getLocalPort();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    protected void waitWebPage(String urlSt) throws InterruptedException, TimeoutException {
        System.out.println("Waiting for url " + urlSt);
        HttpURLConnection con = null;
        long startTime = System.currentTimeMillis();
        while (true) {
            try {
                URL url = new URL(urlSt);
                con = (HttpURLConnection)url.openConnection();
                int status = con.getResponseCode();
                if (status == 200) {
                    return;
                }
            } catch (ConnectException e) {
                // Ignore connection refused
            } catch (MalformedURLException e) {
                throw new RuntimeException(e.getMessage(), e);
            } catch (IOException e) {
                throw new RuntimeException(e.getMessage(), e);
            } finally {
                if (con != null) {
                    con.disconnect();
                }
            }
            sleepOrTimeout(startTime, TIMEOUT, "Timeout waiting for web page " + urlSt);
        }
    }

    protected void assertBundlesStarted() {
        for (Bundle bundle : bundleContext.getBundles()) {
            System.out
                .println(bundle.getSymbolicName() + ":" + bundle.getVersion() + ": " + bundle.getState());
            if (bundle.getState() != Bundle.ACTIVE) {
                try {
                    bundle.start();
                } catch (BundleException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    protected ZooKeeper createZookeeperClient() throws Exception {
        waitPort(ZK_PORT);
        return new ZooKeeper("localhost:" + ZK_PORT, 1000, null);
    }

    protected void assertNodeExists(ZooKeeper zk, String zNode, int timeout) {
        long endTime = System.currentTimeMillis() + timeout;
        Stat stat = null;
        while (stat == null && System.currentTimeMillis() < endTime) {
            try {
                stat = zk.exists(zNode, null);
                Thread.sleep(200);
            } catch (Exception e) {
                // Ignore
            }
        }
        Assert.assertNotNull("ZooKeeper node " + zNode + " was not found", stat);
    }

    protected static Option configHttpService(String host, int port) {
        return newConfiguration("org.ops4j.pax.web")
            .put("org.osgi.service.http.port", "" + port)
            .put("org.ops4j.pax.web.listening.addresses", host)
            .asOption();
    }

    protected static Option configZKConsumer() {
        return newConfiguration("org.apache.aries.rsa.discovery.zookeeper") //
            .put("zookeeper.host", "127.0.0.1") //
            .put("zookeeper.port", "" + ZK_PORT).asOption();
    }

    protected static Option configZKServer() {
        return newConfiguration("org.apache.aries.rsa.discovery.zookeeper.server")
            .put("clientPort", "" + ZK_PORT) //
            .asOption();
    }
    
    protected static Option configLogging() {
        return ConfigurationAdminOptions.configurationFolder(new File("src/test/resources/cfg"));
    }
    

    protected static MavenArtifactProvisionOption taskServiceAPI() {
        return mavenBundle().groupId("org.apache.cxf.dosgi.samples")
            .artifactId("cxf-dosgi-samples-soap-api").versionAsInProject();
    }
    
    protected static MavenArtifactProvisionOption taskServiceImpl() {
        return mavenBundle().groupId("org.apache.cxf.dosgi.samples")
            .artifactId("cxf-dosgi-samples-soap-impl").versionAsInProject();
    }


    protected static MavenArtifactProvisionOption taskRESTAPI() {
        return mavenBundle().groupId("org.apache.cxf.dosgi.samples")
            .artifactId("cxf-dosgi-samples-rest-api").versionAsInProject();
    }


    protected static MavenArtifactProvisionOption taskRESTImpl() {
        return mavenBundle().groupId("org.apache.cxf.dosgi.samples")
            .artifactId("cxf-dosgi-samples-rest-impl").versionAsInProject();
    }


    protected static Option basicTestOptions() throws Exception {
        return composite(CoreOptions.junitBundles(), //
                         MultiBundleTools.getDistro(), //
                         
                         systemProperty("org.osgi.service.http.port").value("" + HTTP_PORT),
                         systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("INFO"), //
                         systemProperty("pax.exam.osgi.unresolved.fail").value("true"), //
                         systemProperty("org.apache.cxf.stax.allowInsecureParser").value("true"), //
                         systemProperty("rsa.export.policy.filter").value("(name=cxf)"), //
                         configHttpService(HTTP_HOST, HTTP_PORT),
                         configLogging()
        );
    }

    protected static VMOption debug() {
        return CoreOptions.vmOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005");
    }

}
