/*
 * 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.ide.test.impl.helpers;

import static org.junit.Assert.fail;

import java.util.Collections;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import org.apache.sling.ide.eclipse.core.internal.Activator;
import org.apache.sling.ide.transport.CommandExecutionProperties;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;

/**
 * The <tt>AbstractFailOnUnexpectedEventsRule</tt> implements the plumbing needed for rules to react on events
 * 
 */
public abstract class AbstractFailOnUnexpectedEventsRule implements EventHandler, TestRule {

    private static final int SETTLE_TIMEOUT_MILLIS = 500;
    private ServiceRegistration<EventHandler> registration;
    private final List<Event> unexpectedEvents = new CopyOnWriteArrayList<Event>();

    public Statement apply(Statement base, Description description) {
        return statement(base);
    }

    private Statement statement(final Statement base) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                before();
                try {
                    base.evaluate();
                } finally {
                    after();
                }
            }
        };
    }

    protected void before() {
    
        Dictionary<String, Object> props = new Hashtable<String, Object>();
        props.put("event.topics", "org/apache/sling/ide/transport");
        registration = Activator.getDefault().getBundle().getBundleContext()
                .registerService(EventHandler.class, this, props);
    
    }

    protected void after() throws InterruptedException {
    
        if (registration != null) {
            registration.unregister();
        }
    
        waitForEventsToSettle();
    
        if (unexpectedEvents.isEmpty()) {
            return;
        }
    
        StringBuilder desc = new StringBuilder();
        desc.append(getClass().getSimpleName() + " : " + unexpectedEvents.size() + " unexpected events captured:");
        for (Event event : unexpectedEvents) {
    
            String flags = (String) event.getProperty(CommandExecutionProperties.ACTION_FLAGS);
    
            desc.append('\n');
            desc.append(event.getProperty(CommandExecutionProperties.ACTION_TYPE));
            if (flags != null && flags.length() > 0) {
                desc.append(" (").append(flags).append(")");
            }
            desc.append(" -> ");
            desc.append(event.getProperty(CommandExecutionProperties.ACTION_TARGET));
            desc.append(" : ");
            desc.append(event.getProperty(CommandExecutionProperties.RESULT_TEXT));
        }
    
        fail(desc.toString());
    }

    /**
     * Clears the list of unexpected events after the event firing settles
     * 
     * <p>
     * This can be useful for instance when you want to validate that no import events take place after a certain point
     * in time.
     * </p>
     * 
     * <p>
     * Event firing settling is defined as no unexpected events being recorded for {@value #SETTLE_TIMEOUT_MILLIS}
     * milliseconds
     * </p>
     */
    public void clearUnexpectedEventsAfterSettling() throws InterruptedException {
    
        waitForEventsToSettle();
    
        unexpectedEvents.clear();
    }

    protected void addUnexpectedEvent(Event event) {
        unexpectedEvents.add(event);
    }

    protected List<Event> getUnexpectedEvents() {
        return Collections.unmodifiableList(unexpectedEvents);
    }

    private void waitForEventsToSettle() throws InterruptedException {
    
        int currentSize;
        do {
            currentSize = unexpectedEvents.size();
            Thread.sleep(SETTLE_TIMEOUT_MILLIS);
        } while (currentSize != unexpectedEvents.size());
    }

}