package org.apache.maven.surefire.common.junit3;

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

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import org.apache.maven.surefire.api.util.ReflectionUtils;

/**
 * Reflection facade for JUnit3 classes
 *
 */
public final class JUnit3Reflector
{
    private static final String TEST_CASE = "junit.framework.Test";

    private static final String TEST_RESULT = "junit.framework.TestResult";

    private static final String TEST_LISTENER = "junit.framework.TestListener";

    private static final String TEST = "junit.framework.Test";

    private static final String ADD_LISTENER_METHOD = "addListener";

    private static final String RUN_METHOD = "run";

    private static final String TEST_SUITE = "junit.framework.TestSuite";

    private static final Class[] EMPTY_CLASS_ARRAY = { };

    private static final Object[] EMPTY_OBJECT_ARRAY = { };

    private final Class[] interfacesImplementedByDynamicProxy;

    private final Class<?> testResultClass;

    private final Method addListenerMethod;

    private final Method testInterfaceRunMethod;

    private final Class<?> testInterface;

    private final Class<?> testCase;

    private final Constructor testsSuiteConstructor;

    public JUnit3Reflector( ClassLoader testClassLoader )
    {
        testResultClass = ReflectionUtils.tryLoadClass( testClassLoader, TEST_RESULT );
        testCase = ReflectionUtils.tryLoadClass( testClassLoader, TEST_CASE );
        testInterface = ReflectionUtils.tryLoadClass( testClassLoader, TEST );
        interfacesImplementedByDynamicProxy =
            new Class[]{ ReflectionUtils.tryLoadClass( testClassLoader, TEST_LISTENER ) };
        Class<?>[] constructorParamTypes = { Class.class };

        Class<?> testSuite = ReflectionUtils.tryLoadClass( testClassLoader, TEST_SUITE );

        // The interface implemented by the dynamic proxy (TestListener), happens to be
        // the same as the param types of TestResult.addTestListener

        if ( isJUnit3Available() )
        {
            testsSuiteConstructor = ReflectionUtils.getConstructor( testSuite, constructorParamTypes );
            addListenerMethod =
                    tryGetMethod( testResultClass, ADD_LISTENER_METHOD, interfacesImplementedByDynamicProxy );
            testInterfaceRunMethod = getMethod( testInterface, RUN_METHOD, testResultClass );
        }
        else
        {
            testsSuiteConstructor = null;
            addListenerMethod = null;
            testInterfaceRunMethod = null;
        }
    }

    // Switch to reflectionutils when building with 2.7.2
    private static Method tryGetMethod( Class<?> clazz, String methodName, Class<?>... parameters )
    {
        try
        {
            return clazz.getMethod( methodName, parameters );
        }
        catch ( NoSuchMethodException e )
        {
            return null;
        }
    }

    private static Method getMethod( Class<?> clazz, String methodName, Class<?>... parameters )
    {
        try
        {
            return clazz.getMethod( methodName, parameters );
        }
        catch ( NoSuchMethodException e )
        {
            throw new RuntimeException( "When finding method " + methodName, e );
        }
    }


    public Object constructTestObject( Class testClass )
        throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, InstantiationException
    {
        Object testObject = createInstanceFromSuiteMethod( testClass );

        if ( testObject == null && testCase.isAssignableFrom( testClass ) )
        {
            testObject = testsSuiteConstructor.newInstance( testClass );
        }

        if ( testObject == null )
        {
            Constructor testConstructor = getTestConstructor( testClass );

            if ( testConstructor.getParameterTypes().length == 0 )
            {
                testObject = testConstructor.newInstance( EMPTY_OBJECT_ARRAY );
            }
            else
            {
                testObject = testConstructor.newInstance( testClass.getName() );
            }
        }
        return testObject;
    }

    private static Object createInstanceFromSuiteMethod( Class<?> testClass )
        throws IllegalAccessException, InvocationTargetException
    {
        Object testObject = null;
        try
        {
            Method suiteMethod = testClass.getMethod( "suite", EMPTY_CLASS_ARRAY );

            if ( Modifier.isPublic( suiteMethod.getModifiers() ) && Modifier.isStatic( suiteMethod.getModifiers() ) )
            {
                testObject = suiteMethod.invoke( null, EMPTY_OBJECT_ARRAY );
            }
        }
        catch ( NoSuchMethodException e )
        {
            // No suite method
        }
        return testObject;
    }

    private static Constructor getTestConstructor( Class<?> testClass )
        throws NoSuchMethodException
    {
        try
        {
            return testClass.getConstructor( String.class );
        }
        catch ( NoSuchMethodException e )
        {
            return testClass.getConstructor( EMPTY_CLASS_ARRAY );
        }
    }

    public Class[] getInterfacesImplementedByDynamicProxy()
    {
        return interfacesImplementedByDynamicProxy;
    }

    public Class<?> getTestResultClass()
    {
        return testResultClass;
    }

    public Method getAddListenerMethod()
    {
        return addListenerMethod;
    }

    public Method getTestInterfaceRunMethod()
    {
        return testInterfaceRunMethod;
    }

    public Class<?> getTestInterface()
    {
        return testInterface;
    }

    public Method getRunMethod( Class<?> testClass )
    {
        return getMethod( testClass, RUN_METHOD, getTestResultClass() );
    }

    public boolean isJUnit3Available()
    {
        return testResultClass != null;
    }
}
