/*
 * 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 test;

import java.io.PrintStream;

import org.junit.Assert;

/**
 * Helper class to make sure that steps in a test happen in the correct order. Instantiate
 * this class and subsequently invoke <code>step(nr)</code> with steps starting at 1. You
 * can also have threads wait until you arrive at a certain step.
 * 
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
public class Ensure {
    private final boolean DEBUG;
    private static long INSTANCE = 0;
    private static final int RESOLUTION = 100;
    private static PrintStream STREAM = System.out;
    int step = 0;
    private Throwable m_throwable;
	private boolean previousStepFailed;
    
    public Ensure() {
        this(true);
    }
    
    public Ensure(boolean debug) {
        DEBUG = debug;
        if (DEBUG) {
            INSTANCE++;
        }
    }

    public static void setStream(PrintStream output) {
        STREAM = output;
    }
    
    /**
     * Mark this point as step <code>nr</code>.
     * 
     * @param nr the step we are in
     */
    public synchronized void step(int nr) {
    	if (previousStepFailed) {
    		throw new RuntimeException("can not enter into step " + nr + " (some previous steps failed)");
    	}
        step++;
        try {
        	Assert.assertEquals(nr, step);
        } catch (Throwable e) {
        	previousStepFailed = true;
        	throw e;
        }
        if (DEBUG) {
            String info = getLineInfo(3);
            STREAM.println("[Ensure " + INSTANCE + "] step " + step + " [" + currentThread() + "] " + info);
        }
        notifyAll();
    }

    private String getLineInfo(int depth) {
        StackTraceElement[] trace = Thread.currentThread().getStackTrace();
        String info = trace[depth].getClassName() + "." + trace[depth].getMethodName() + ":" + trace[depth].getLineNumber();
        return info;
    }
    
    /**
     * Mark this point as the next step.
     */
    public synchronized void step() {
    	if (previousStepFailed) {
    		throw new RuntimeException("can not enter into step " + (step+1) + " (some previous steps failed)");
    	}
        step++;
        if (DEBUG) {
            String info = getLineInfo(3);
            STREAM.println("[Ensure " + INSTANCE + "] next step " + step + " [" + currentThread() + "] " + info);
        }
        notifyAll();
    }

    /**
     * Wait until we arrive at least at step <code>nr</code> in the process, or fail if that
     * takes more than <code>timeout</code> milliseconds. If you invoke wait on a thread,
     * you are effectively assuming some other thread will invoke the <code>step(nr)</code>
     * method.
     * 
     * @param nr the step to wait for
     * @param timeout the number of milliseconds to wait
     */
    public synchronized void waitForStep(int nr, int timeout) {
        final int initialTimeout = timeout;
        if (DEBUG) {
            String info = getLineInfo(3);
            STREAM.println("[Ensure " + INSTANCE + "] waiting for step " + nr + " [" + currentThread() + "] " + info);
        }
        while (step < nr && timeout > 0) {
            try {
                wait(RESOLUTION);
                timeout -= RESOLUTION;
            }
            catch (InterruptedException e) {}
        }
        if (step < nr) {
            throw new IllegalStateException("Timed out waiting for " + initialTimeout + " ms for step " + nr + ", we are still at step " + step);
        }
        if (DEBUG) {
            String info = getLineInfo(3);
            STREAM.println("[Ensure " + INSTANCE + "] arrived at step " + nr + " [" + currentThread() + "] " + info);
        }
    }
    
    private String currentThread() {
        Thread thread = Thread.currentThread();
        return thread.getId() + " " + thread.getName();
    }
    
    public static Runnable createRunnableStep(final Ensure ensure, final int nr) {
        return new Runnable() { public void run() { ensure.step(nr); }};
    }
    
    public synchronized void steps(Steps steps) {
        steps.next(this);
    }
    
    /** 
     * Helper class for naming a list of step numbers. If used with the steps(Steps) method
     * you can define at which steps in time this point should be passed. That means you can
     * check methods that will get invoked multiple times during a test.
     */
    public static class Steps {
        private final int[] m_steps;
        private int m_stepIndex;

        /** 
         * Create a list of steps and initialize the step counter to zero.
         */
        public Steps(int... steps) {
            m_steps = steps;
            m_stepIndex = 0;
        }

        /**
         * Ensure we're at the right step. Will throw an index out of bounds exception if we enter this step more often than defined.
         */
        public void next(Ensure ensure) {
            ensure.step(m_steps[m_stepIndex++]);
        }
    }

    /**
     * Saves a thrown exception that occurred in a different thread. You can only save one exception
     * at a time this way.
     */
    public synchronized void throwable(Throwable throwable) {
        m_throwable = throwable;
    }

    /**
     * Throws a <code>Throwable</code> if one occurred in a different thread and that thread saved it
     * using the <code>throwable()</code> method.
     */
    public synchronized void ensure() throws Throwable {
        if (m_throwable != null) {
            throw m_throwable;
        }
    }
}
