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

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.naming.directory.InvalidAttributesException;

import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
import org.apache.sling.performance.annotation.AfterMethodInvocation;
import org.apache.sling.performance.annotation.BeforeMethodInvocation;
import org.apache.sling.performance.annotation.PerformanceTest;
import org.junit.After;
import org.junit.Before;
import org.junit.runners.model.FrameworkMethod;

class FrameworkPerformanceMethod extends FrameworkMethod {

	private Object target;
	private PerformanceSuiteState performanceSuiteState;

	public FrameworkPerformanceMethod(Method method, Object target,
			PerformanceSuiteState performanceSuiteState) {
		super(method);
		this.target = target;
		this.performanceSuiteState = performanceSuiteState;

	}

	@Override
	public Object invokeExplosively(Object target, Object... params)
			throws Throwable {
		// Executes the test method on the supplied target

		// Check if this is the first test running from this specific
		// PerformanceSuite
		// and run the BeforeSuite methods
		if ((performanceSuiteState != null)
				&& (performanceSuiteState.getBeforeSuiteMethod() != null)
				&& (performanceSuiteState.getTargetObjectSuite() != null)
				&& (performanceSuiteState.getNumberOfExecutedMethods() == 0)
				&& !performanceSuiteState.testSuiteName
						.equals(ParameterizedTestList.TEST_CASE_ONLY)) {
			performanceSuiteState.getBeforeSuiteMethod().invoke(
					performanceSuiteState.getTargetObjectSuite());
		}

		// In case of a PerformanceSuite we need to run the methods annotated
		// with Before and After
		// ourselves as JUnit can't find them (JUnit is looking for them in the
		// test suite class);
		// in case we don't have to deal with a PerformanceSuite just skip this
		// as JUnit will run the methods itself
		if ((performanceSuiteState != null)
				&& !performanceSuiteState.testSuiteName
						.equals(ParameterizedTestList.TEST_CASE_ONLY)) {

			recursiveCallSpecificMethod(this.target.getClass(), this.target,
					Before.class);
		}

		// Need to count the number of tests run from the PerformanceSuite
		// so that we can call the AfterSuite method after the last test from
		// the suite
		// has run and the AfterSuite needs to run
		performanceSuiteState.incrementNumberOfExecutedTestMethods();

		Object response = null;

		Method testMethodToInvoke = this.getMethod();

		PerformanceTest performanceAnnotation = testMethodToInvoke
				.getAnnotation(PerformanceTest.class);

		// retrieve the test configuration options
		int warmuptime = performanceAnnotation.warmuptime();
		int runtime = performanceAnnotation.runtime();
		int warmupinvocations = performanceAnnotation.warmupinvocations();
		int runinvocations = performanceAnnotation.runinvocations();

		DescriptiveStatistics statistics = new DescriptiveStatistics();

		// System.out.println("Warmup started - test :" +
		// testMethodToInvoke.getName());

		if (warmupinvocations != 0) {
			// Run the number of invocation specified in the annotation
			// for warming up the system
			for (int invocationIndex = 0; invocationIndex < warmupinvocations; invocationIndex++) {

				recursiveCallSpecificMethod(this.target.getClass(),
						this.target, BeforeMethodInvocation.class);

				// TODO: implement the method to run a before a specific test
				// method
				// recursiveCallSpecificMethod(this.target.getClass(),
				// this.target, BeforeSpecificTest.class);

				response = super.invokeExplosively(this.target, params);

				// TODO: implement the method to run a after a specific test
				// method
				// recursiveCallSpecificMethod(this.target.getClass(),
				// this.target, AfterSpecificTest.class);

				recursiveCallSpecificMethod(this.target.getClass(),
						this.target, AfterMethodInvocation.class);
			}
		} else {
			// Run a few iterations to warm up the system
			long warmupEnd = System.currentTimeMillis() + warmuptime * 1000;
			while (System.currentTimeMillis() < warmupEnd) {
				recursiveCallSpecificMethod(this.target.getClass(),
						this.target, BeforeMethodInvocation.class);

				// TODO: implement the method to run a before a specific test
				// method
				// recursiveCallSpecificMethod(this.target.getClass(),
				// this.target, BeforeSpecificTest.class);

				response = super.invokeExplosively(this.target, params);

				// recursiveCallSpecificMethod(this.target.getClass(),
				// this.target, AfterSpecificTest.class);
				// TODO: implement the method to run a after a specific test
				// method

				recursiveCallSpecificMethod(this.target.getClass(),
						this.target, AfterMethodInvocation.class);
			}
		}

		// System.out.println("Warmup ended - test :" +
		// testMethodToInvoke.getName());
		if (runinvocations != 0) {
			// Run the specified number of iterations and capture the execution
			// times
			for (int invocationIndex = 0; invocationIndex < runinvocations; invocationIndex++) {

				response = this.invokeTimedTestMethod(testMethodToInvoke,
						statistics, params);
			}
		} else {
			// Run test iterations and capture the execution times
			long runtimeEnd = System.currentTimeMillis() + runtime * 1000;

			while (System.currentTimeMillis() < runtimeEnd) {

				response = this.invokeTimedTestMethod(testMethodToInvoke,
						statistics, params);

			}
		}

		if (statistics.getN() > 0) {
			ReportLogger
					.writeReport(this.target.getClass().getName(),
							this.performanceSuiteState.testSuiteName,
							getMethod().getName(), statistics,
							ReportLogger.ReportType.TXT);
		}

		// In case of a PerformanceSuite we need to run the methods annotated
		// with Before and After
		// ourselves as JUnit can't find them; in case we don't have to deal
		// with a PerformanceSuite
		// just skip this as JUnit will run the methods itself
		if ((performanceSuiteState != null)
				&& !performanceSuiteState.testSuiteName
						.equals(ParameterizedTestList.TEST_CASE_ONLY)) {

			recursiveCallSpecificMethod(this.target.getClass(), this.target,
					After.class);
		}

		// Check if this is the last test running from a PerformanceSuite
		// and run the AfterSuite method
		if ((performanceSuiteState != null)
				&& (performanceSuiteState.getAfterSuiteMethod() != null)
				&& (performanceSuiteState.getTargetObjectSuite() != null)
				&& (performanceSuiteState.getNumberOfExecutedMethods() == performanceSuiteState
						.getNumberOfMethodsInSuite())
				&& !performanceSuiteState.testSuiteName
						.equals(ParameterizedTestList.TEST_CASE_ONLY)) {
			performanceSuiteState.getAfterSuiteMethod().invoke(
					performanceSuiteState.getTargetObjectSuite());

		}

		return response;
	}

	/**
	 * Method that runs 1 invocation of the timed test method
	 * 
	 * @param testMethodToInvoke
	 *            the test method to invoke
	 * @param statistics
	 *            the statistics object that collects the results
	 * @param params
	 *            the parameters for the invocation of the test method
	 * @return the response from the method invocation
	 * @throws Throwable
	 */
	private Object invokeTimedTestMethod(Method testMethodToInvoke,
			DescriptiveStatistics statistics, Object... params)
			throws Throwable {

		Object response = null;

		recursiveCallSpecificMethod(this.target.getClass(), this.target,
				BeforeMethodInvocation.class);

		// TODO: implement the method to run a before a specific test method
		// recursiveCallSpecificMethod(this.target.getClass(), this.target,
		// BeforeSpecificTest.class);

		// timing the test method execution
		// System.out.println("Start test: " + testMethodToInvoke.getName());
		long start = System.nanoTime();
		response = super.invokeExplosively(this.target, params);
		long timeMilliseconds = TimeUnit.MILLISECONDS.convert(System.nanoTime()
				- start, TimeUnit.NANOSECONDS);
		statistics.addValue(timeMilliseconds);

		// System.out.println("End test: " + testMethodToInvoke.getName());

		// System.out.println("Test execution time (ms): " + timeMilliseconds);

		// TODO: implement the method to run a after a specific test method
		// recursiveCallSpecificMethod(this.target.getClass(), this.target,
		// AfterSpecificTest.class);

		recursiveCallSpecificMethod(this.target.getClass(), this.target,
				AfterMethodInvocation.class);

		return response;
	}

	/**
	 * Recursively call a specific method annotated with a custom annotation
	 * 
	 * @param test
	 *            the test class that contains the method
	 * @param instance
	 *            the instance on which will run the method
	 * @param methodAnnotation
	 *            the method annotation to look for
	 * @throws InvocationTargetException
	 * @throws InvalidAttributesException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 */
	@SuppressWarnings({ "rawtypes" })
	private void recursiveCallSpecificMethod(Class test, Object instance,
			Class<? extends Annotation> methodAnnotation)
			throws InvocationTargetException, InvalidAttributesException,
			IllegalAccessException, InstantiationException {
		if (test.getSuperclass() != null) {
			recursiveCallSpecificMethod(test.getSuperclass(), instance,
					methodAnnotation);
		}

		Method testMethod = getSpecificTestMethod(test, methodAnnotation);
		if (testMethod != null) {
			if (!testMethod.isAccessible()) {
				testMethod.setAccessible(true);
			}
			testMethod.invoke(instance);
		}
	}

	/**
	 * Get the method annotated with the custom annotation
	 * 
	 * @param testClass
	 *            the test class on which to look for the method
	 * @param methodAnnotation
	 *            the method annotation to look for
	 * @return
	 * @throws InvalidAttributesException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 */
	@SuppressWarnings({ "rawtypes" })
	private Method getSpecificTestMethod(Class testClass,
			Class<? extends Annotation> methodAnnotation)
			throws InvalidAttributesException, IllegalAccessException,
			InstantiationException {

		Method[] methodsToReturn = getSpecificMethods(testClass,
				methodAnnotation);
		Method methodToReturn = null;
		if (methodsToReturn.length == 1) {
			methodToReturn = methodsToReturn[0];
		} else if (methodsToReturn.length > 1) {
			throw new InvalidAttributesException(
					"Only 1 non parameterized before method accepted");
		}

		return methodToReturn;
	}

	/**
	 * Retrieve all the specific methods from test class
	 * 
	 * @param testClass
	 *            the test class that we need to search in
	 * @param annotation
	 *            the annotation that we should look for
	 * @return the list with the methods that have the specified annotation
	 */
	@SuppressWarnings({ "rawtypes" })
	private Method[] getSpecificMethods(Class testClass,
			Class<? extends Annotation> annotation) {
		Method[] allMethods = testClass.getDeclaredMethods();

		List<Method> methodListResult = new ArrayList<Method>();

		for (Method testMethod : allMethods) {
			if (testMethod.isAnnotationPresent(annotation)) {
				methodListResult.add(testMethod);
			}
		}
		return methodListResult.toArray(new Method[] {});
	}

}
