/*
 * 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.eventadmin.perftests;

import static org.ops4j.pax.exam.Constants.START_LEVEL_SYSTEM_BUNDLES;
import static org.ops4j.pax.exam.CoreOptions.bundle;
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.vmOption;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

import javax.inject.Inject;

import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.CoreOptions;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.options.AbstractDelegateProvisionOption;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
import org.osgi.service.event.EventHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@RunWith(PaxExam.class)
public class PerformanceTestIT {
    // the name of the system property providing the bundle file to be installed and tested
    private static final String BUNDLE_JAR_SYS_PROP = "project.bundle.file";

    /** The logger. */
    protected static final Logger logger = LoggerFactory.getLogger(PerformanceTestIT.class);
    private static final int RUNS = 5;
    public static final int BATCH_SIZE = 500000;

    @Inject
    protected BundleContext bundleContext;

    /** Event admin reference. */
    private ServiceReference<EventAdmin> eventAdminReference;

    /** Event admin. */
    private EventAdmin eventAdmin;

    final AtomicLong counter = new AtomicLong();

    Collection<Listener> listeners = new ArrayList<Listener>();

    @Configuration
    public static Option[] configuration() {
        final String bundleFileName = System.getProperty( BUNDLE_JAR_SYS_PROP );
        logger.info("Bundle jar at :"+bundleFileName);
        final File bundleFile = new File( bundleFileName );
        if ( !bundleFile.canRead() ) {
            throw new IllegalArgumentException( "Cannot read from bundle file " + bundleFileName + " specified in the "
                    + BUNDLE_JAR_SYS_PROP + " system property" );
        }
        return options(
                vmOption("-Xms1024m"),
//                vmOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"),
                provision(
                        mavenBundle( "org.ops4j.pax.tinybundles", "tinybundles", "1.0.0" ),
                        mavenBundle("org.apache.sling", "org.apache.sling.commons.log", "2.1.2"),
                        mavenBundle("org.apache.felix", "org.apache.felix.configadmin", "1.2.8"),
                        mavenBundle("org.apache.felix", "org.apache.felix.metatype", "1.0.4"),
                        CoreOptions.bundle(bundleFile.toURI().toString()),
                        mavenBundle("org.ops4j.pax.url", "pax-url-mvn", "1.3.5")
                ),
                // below is instead of normal Pax Exam junitBundles() to deal
                // with build server issue
                new DirectURLJUnitBundlesOption(),
                systemProperty("pax.exam.invoker").value("junit"),
                bundle("link:classpath:META-INF/links/org.ops4j.pax.exam.invoker.junit.link")
        );
    }

    protected EventAdmin loadEventAdmin() {
        if ( eventAdminReference == null || eventAdminReference.getBundle() == null ) {
            eventAdmin = null;
            eventAdminReference = bundleContext.getServiceReference(EventAdmin.class);
        }
        if ( eventAdmin == null && eventAdminReference != null ) {
            eventAdmin = bundleContext.getService(eventAdminReference);
        }
        return eventAdmin;
    }

    public void addListener(Listener listener, String... topics) {
        listener.register(bundleContext,topics);
        listeners.add(listener);
    }

    private void removeListener(Listener listener) {
        listener.unregister();
    }


    protected void send(String topic, Dictionary<String, Object> properties, boolean sync) {
        final Event event = new Event(topic, properties);
        if ( sync ) {
            eventAdmin.sendEvent(event);
        } else {
            eventAdmin.postEvent(event);
        }
    }


    @Test
    public void measureThroughputSend() {
        loadEventAdmin();
        addListener(new Listener() {
            @Override
            public void handleEvent(Event event) {
                long calledTimes = counter.incrementAndGet();
                if (calledTimes == BATCH_SIZE ) {
                    synchronized (counter) {
                        counter.notify();
                    }
                }

            }
        }, "topic");

        // Warm-up
        Hashtable<String, Object> properties = new Hashtable<String, Object>();
        for (int i= 0;i < BATCH_SIZE;i++) {
            properties.put("key",i);
            send("topic", properties, false);
        }
        int average =0;
        for (int runs = 0; runs < RUNS;runs ++) {

            final CountDownLatch latch = new CountDownLatch(BATCH_SIZE);
            addListener(new Listener() {
                @Override
                public void handleEvent(Event event) {
                    latch.countDown();
                }
            }, "topic" + runs);

            ArrayBlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<Runnable>(BATCH_SIZE+1);
            ThreadPoolExecutor executor = new ThreadPoolExecutor(1,
                    1,
                    1000,
                    TimeUnit.MILLISECONDS, workQueue);


            for (int i = 0; i < BATCH_SIZE; i++) {
                final String topicString = "topic"+runs;
                final Hashtable<String,Object> localProperties = new Hashtable<String, Object>();
                localProperties.put(topicString,i);
                workQueue.add(new Runnable() {
                    @Override
                    public void run() {
                        send(topicString, localProperties, true);
                    }
                });
            }

            long startTime = System.nanoTime();
            executor.prestartAllCoreThreads();

            try {
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            long endTime = System.nanoTime();
            long milliseconds = (endTime - startTime) / 1000000;
            logger.info("Post Run "+runs+" Elapsed :" + milliseconds);
            average += milliseconds;
        }

        logger.info("Send Avg: "+average / RUNS);
    }

    @Test
    public void measureThroughputPost() {
        loadEventAdmin();
        addListener(new Listener() {
            @Override
            public void handleEvent(Event event) {
                long calledTimes = counter.incrementAndGet();
                if (calledTimes == BATCH_SIZE ) {
                    synchronized (counter) {
                        counter.notify();
                    }
                }

            }
        }, "topic");

        // Warm-up
        Hashtable<String, Object> properties = new Hashtable<String, Object>();
        for (int i= 0;i < BATCH_SIZE;i++) {
            properties.put("key",i);
            send("topic", properties, false);
        }
        int average =0;
        for (int runs = 0; runs < RUNS;runs ++) {

            final CountDownLatch latch = new CountDownLatch(BATCH_SIZE);
            addListener(new Listener() {
                @Override
                public void handleEvent(Event event) {
                    latch.countDown();
                }
            }, "topic" + runs);

            ArrayBlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<Runnable>(BATCH_SIZE+1);
            ThreadPoolExecutor executor = new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(),
                    Runtime.getRuntime().availableProcessors(),
                    1000,
                    TimeUnit.MILLISECONDS, workQueue);


            for (int i = 0; i < BATCH_SIZE; i++) {
                final String topicString = "topic"+runs;
                final Hashtable<String,Object> localProperties = new Hashtable<String, Object>();
                localProperties.put(topicString,i);
                workQueue.add(new Runnable() {
                    @Override
                    public void run() {
                        send(topicString, localProperties, false);
                    }
                });
            }

            long startTime = System.nanoTime();
            executor.prestartAllCoreThreads();

            try {
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            long endTime = System.nanoTime();
            long milliseconds = (endTime - startTime) / 1000000;
            logger.info("Post Run "+runs+" Elapsed :" + milliseconds);
            average += milliseconds;
        }

        logger.info("Post Avg: "+average / RUNS);
    }

    @After
    public void tearDown() {
        for (Listener listener : listeners) {
            removeListener(listener);
        }
    }



    private static abstract class Listener implements EventHandler {
        private ServiceRegistration<EventHandler> registration;

        protected Listener() {
        }

        public void register(BundleContext bundleContext, String...topics) {
            final Dictionary<String, Object> props = new Hashtable<String, Object>();
            if ( topics != null ) {
                props.put("event.topics", topics);
            } else {
                props.put("event.topics", "*");
            }
            this.registration = bundleContext.registerService(EventHandler.class, this, props);
        }

        public void unregister() {
            registration.unregister();
        }
    }


    private static class DirectURLJUnitBundlesOption
            extends AbstractDelegateProvisionOption<DirectURLJUnitBundlesOption> {

        /**
         * Constructor.
         */
        public DirectURLJUnitBundlesOption(){
            super(
                    bundle("http://repository.springsource.com/ivy/bundles/external/org.junit/com.springsource.org.junit/4.9.0/com.springsource.org.junit-4.9.0.jar")
            );
            noUpdate();
            startLevel(START_LEVEL_SYSTEM_BUNDLES);
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public String toString() {
            return String.format("DirectURLJUnitBundlesOption{url=%s}", getURL());
        }

        /**
         * {@inheritDoc}
         */
        @Override
        protected DirectURLJUnitBundlesOption itself() {
            return this;
        }

    }
}
