/*
 * 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[]{});
         }
 
}


