/*
 * 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.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import org.apache.sling.performance.annotation.AfterSuite;
import org.apache.sling.performance.annotation.BeforeSuite;
import org.apache.sling.performance.annotation.PerformanceTest;
import org.apache.sling.performance.annotation.PerformanceTestSuite;
import org.junit.After;
import org.junit.Before;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;


/**
 * The custom JUnit runner that collects the performance tests
 *
 */
public class PerformanceRunner extends BlockJUnit4ClassRunner {
        protected LinkedList<FrameworkMethod> tests = new LinkedList<FrameworkMethod>();
        private List<PerformanceSuiteState> suitesState = new ArrayList<PerformanceSuiteState>();
        
        
        public PerformanceRunner(Class<?> clazz) throws InitializationError {
        	super(clazz);
        	try {
        		computeTests();
        		}
        	catch (Exception e) {
        		throw new InitializationError(e);
        	}
        }

        /**
         * Compute the tests that will be run
         * @throws Exception
         */
        protected void computeTests() throws Exception {
                tests.addAll(super.computeTestMethods());
                
                // count the performance tests
                tests.addAll(computePerformanceTests());
                
                // This is called here to ensure the test class constructor is called at least
                // once during testing.  
                createTest();
        }
        
        /**
         * Compute performance tests
         * @return the list containing the performance test methods
         * @throws Exception
         */
        protected Collection<? extends FrameworkMethod> computePerformanceTests() throws Exception {
                List<FrameworkPerformanceMethod> tests = new LinkedList<FrameworkPerformanceMethod>();

                List<Object> testObjects = new ArrayList<Object>();
                ParameterizedTestList testCenter = new ParameterizedTestList();
                
                // Retrieve the test objects included in the Performance test suite
                for (FrameworkMethod method: getTestClass().getAnnotatedMethods(PerformanceTestSuite.class)) {
                	Object targetObject = getTestClass().getJavaClass().newInstance();
                	if (method.getMethod().getReturnType().equals(ParameterizedTestList.class)){
                		testCenter = (ParameterizedTestList) method.getMethod().invoke(targetObject);
                		testObjects = testCenter.getTestObjectList();
                	}
                	else{
                		throw new InitializationError("Wrong signature for the @PerformanceSuite method");
                	}
                }
                
                // Retrieve the methods before running the methods from the test suite
                List<FrameworkMethod> beforeSuiteMethods = getTestClass().getAnnotatedMethods(BeforeSuite.class);
                if (beforeSuiteMethods.size() > 1){
                	throw new InitializationError("Only one @BeforeSuite method is allowed for a @PerformanceSuite");
                }
                
                // Retrieve the methods before running the methods from the test suite
                List<FrameworkMethod> afterSuiteMethods = getTestClass().getAnnotatedMethods(AfterSuite.class);
                if (afterSuiteMethods.size() > 1){
                	throw new InitializationError("Only one @AfterSuite method is allowed for a @PerformanceSuite");
                }
                
                PerformanceSuiteState current = null;
                boolean suiteAlreadyRegistered = false;
                
                for(PerformanceSuiteState suiteState : suitesState){
                	if (suiteState.testSuiteName.equals(testCenter.getTestSuiteName())){
                		suiteAlreadyRegistered = true;
                		suiteState.incrementNumberOfTestMethodsInSuite();
                		current = suiteState;
                		break;
                	}
                }
                
                // Create a new PerformanceSuiteState object
                PerformanceSuiteState newSuite = new PerformanceSuiteState(testCenter.getTestSuiteName());
                
                if (!suiteAlreadyRegistered){	
                	if (beforeSuiteMethods.size() == 1){
	        			newSuite.setBeforeSuiteMethod(beforeSuiteMethods.get(0).getMethod());
	        		}
	        		if (afterSuiteMethods.size() == 1){
	        			newSuite.setAfterSuiteMethod(afterSuiteMethods.get(0).getMethod());
	        		}
	        		
	        		current = newSuite;
	        		newSuite.setTargetObjectSuite(getTestClass().getJavaClass().newInstance());
	        		
                }
        		
                
                // In case there are any objects retrieved from the Performance Suite
                // we should add them to the tests that will be run and increase the number of methods
                // contained in the PerformaceSuite
                if (!testObjects.isEmpty()){
                	for (Object testObject : testObjects){
                		// retrieve the test methods from the test classes 
                		Method[] testMethods = getSpecificMethods(testObject.getClass(), PerformanceTest.class); 
                		
                		if (!suiteAlreadyRegistered){
                			newSuite.incrementNumberOfTestMethodsInSuite();
                		}
                		
                		for (Method method: testMethods){
                			FrameworkPerformanceMethod performaceTestMethod = new FrameworkPerformanceMethod(method, testObject, current);
                			tests.add(performaceTestMethod);
                		}
                	}
                	
                	// add the new suite to the list of suites 
                	suitesState.add(newSuite);
                }

                // Retrieve the performance tests in the case we don't have a performance test suite
                for (FrameworkMethod method: getTestClass().getAnnotatedMethods(PerformanceTest.class)) {
                	Object targetObject = getTestClass().getJavaClass().newInstance();
                	FrameworkPerformanceMethod performaceTestMethod = new FrameworkPerformanceMethod(method.getMethod(), targetObject, current);
              	  	tests.add(performaceTestMethod);
                }
                
                return tests;
        }
       
        
        /**
         * Retrieve specific method 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[]{});
        }
        
        /**
         * {@inheritDoc}
         * @see org.junit.runners.BlockJUnit4ClassRunner#computeTestMethods()
         */
        @Override
        protected List<FrameworkMethod> computeTestMethods() {
                return tests;
        }

        /**
         * Need to override method otherwise the validation will fail because of some
         * hardcoded conditions in JUnit
         */
        @Override
        protected void validateInstanceMethods(List<Throwable> errors) {
                validatePublicVoidNoArgMethods(After.class, false, errors);
                validatePublicVoidNoArgMethods(Before.class, false, errors);
                validateTestMethods(errors);
        }
        
        
}
