package org.apache.maven.surefire.booter;

/*
 * 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 org.apache.maven.surefire.api.booter.BaseProviderFactory;
import org.apache.maven.surefire.api.cli.CommandLineOption;
import org.apache.maven.surefire.api.provider.ProviderParameters;
import org.apache.maven.surefire.api.report.ReporterConfiguration;
import org.apache.maven.surefire.api.report.ReporterFactory;
import org.apache.maven.surefire.api.suite.RunResult;
import org.apache.maven.surefire.api.testset.DirectoryScannerParameters;
import org.apache.maven.surefire.api.testset.RunOrderParameters;
import org.apache.maven.surefire.api.testset.TestArtifactInfo;
import org.apache.maven.surefire.api.testset.TestListResolver;
import org.apache.maven.surefire.api.testset.TestRequest;
import org.apache.maven.surefire.api.util.RunOrder;
import org.apache.maven.surefire.api.util.SurefireReflectionException;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import static java.util.Collections.checkedList;
import static org.apache.maven.surefire.api.util.ReflectionUtils.getConstructor;
import static org.apache.maven.surefire.api.util.ReflectionUtils.getMethod;
import static org.apache.maven.surefire.api.util.ReflectionUtils.instantiateOneArg;
import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeGetter;
import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeMethodWithArray;
import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeSetter;
import static org.apache.maven.surefire.api.util.ReflectionUtils.newInstance;

/**
 * Does reflection based invocation of the surefire methods.
 * <br>
 * This is to avoid complications with linkage issues
 *
 * @author Kristian Rosenvold
 */
public final class SurefireReflector
{
    private final ClassLoader surefireClassLoader;

    private final Class<?> reporterConfiguration;

    private final Class<?> testRequest;

    private final Class<?> testArtifactInfo;

    private final Class<?> directoryScannerParameters;

    private final Class<?> runOrderParameters;

    private final Class<?> baseProviderFactory;

    private final Class<?> runResult;

    private final Class<?> booterParameters;

    private final Class<?> reporterFactory;

    private final Class<?> testListResolver;

    private final Class<Enum<?>> commandLineOptionsClass;

    @SuppressWarnings( "unchecked" )
    public SurefireReflector( ClassLoader surefireClassLoader )
    {
        this.surefireClassLoader = surefireClassLoader;
        try
        {
            reporterConfiguration = surefireClassLoader.loadClass( ReporterConfiguration.class.getName() );
            testRequest = surefireClassLoader.loadClass( TestRequest.class.getName() );
            testArtifactInfo = surefireClassLoader.loadClass( TestArtifactInfo.class.getName() );
            directoryScannerParameters = surefireClassLoader.loadClass( DirectoryScannerParameters.class.getName() );
            runOrderParameters = surefireClassLoader.loadClass( RunOrderParameters.class.getName() );
            baseProviderFactory = surefireClassLoader.loadClass( BaseProviderFactory.class.getName() );
            reporterFactory = surefireClassLoader.loadClass( ReporterFactory.class.getName() );
            runResult = surefireClassLoader.loadClass( RunResult.class.getName() );
            booterParameters = surefireClassLoader.loadClass( ProviderParameters.class.getName() );
            testListResolver = surefireClassLoader.loadClass( TestListResolver.class.getName() );
            commandLineOptionsClass =
                (Class<Enum<?>>) surefireClassLoader.loadClass( CommandLineOption.class.getName() );
        }
        catch ( ClassNotFoundException e )
        {
            throw new SurefireReflectionException( e );
        }
    }

    public Object convertIfRunResult( Object result )
    {
        if ( result == null || !isRunResult( result ) )
        {
            return result;
        }
        int getCompletedCount1 = (Integer) invokeGetter( result, "getCompletedCount" );
        int getErrors = (Integer) invokeGetter( result, "getErrors" );
        int getSkipped = (Integer) invokeGetter( result, "getSkipped" );
        int getFailures = (Integer) invokeGetter( result, "getFailures" );
        return new RunResult( getCompletedCount1, getErrors, getFailures, getSkipped );
    }

    private Object createTestRequest( TestRequest suiteDefinition )
    {
        if ( suiteDefinition == null )
        {
            return null;
        }
        else
        {
            Object resolver = createTestListResolver( suiteDefinition.getTestListResolver() );
            Class<?>[] arguments = { List.class, File.class, testListResolver, int.class };
            Constructor<?> constructor = getConstructor( testRequest, arguments );
            return newInstance( constructor,
                                suiteDefinition.getSuiteXmlFiles(),
                                suiteDefinition.getTestSourceDirectory(),
                                resolver,
                                suiteDefinition.getRerunFailingTestsCount() );
        }
    }

    private Object createTestListResolver( TestListResolver resolver )
    {
        if ( resolver == null )
        {
            return null;
        }
        else
        {
            Constructor<?> constructor = getConstructor( testListResolver, String.class );
            return newInstance( constructor, resolver.getPluginParameterTest() );
        }
    }

    private Object createDirectoryScannerParameters( DirectoryScannerParameters directoryScannerParameters )
    {
        if ( directoryScannerParameters == null )
        {
            return null;
        }
        //Can't use the constructor with the RunOrder parameter. Using it causes some integration tests to fail.
        Class<?>[] arguments = { File.class, List.class, List.class, List.class, boolean.class, String.class };
        Constructor<?> constructor = getConstructor( this.directoryScannerParameters, arguments );
        return newInstance( constructor,
                            directoryScannerParameters.getTestClassesDirectory(),
                            directoryScannerParameters.getIncludes(),
                            directoryScannerParameters.getExcludes(),
                            directoryScannerParameters.getSpecificTests(),
                            directoryScannerParameters.isFailIfNoTests(),
                            RunOrder.asString( directoryScannerParameters.getRunOrder() ) );
    }

    private Object createRunOrderParameters( RunOrderParameters runOrderParameters )
    {
        if ( runOrderParameters == null )
        {
            return null;
        }
        //Can't use the constructor with the RunOrder parameter. Using it causes some integration tests to fail.
        Class<?>[] arguments = { String.class, File.class };
        Constructor<?> constructor = getConstructor( this.runOrderParameters, arguments );
        File runStatisticsFile = runOrderParameters.getRunStatisticsFile();
        return newInstance( constructor, RunOrder.asString( runOrderParameters.getRunOrder() ), runStatisticsFile );
    }

    private Object createTestArtifactInfo( TestArtifactInfo testArtifactInfo )
    {
        if ( testArtifactInfo == null )
        {
            return null;
        }
        Class<?>[] arguments = { String.class, String.class };
        Constructor<?> constructor = getConstructor( this.testArtifactInfo, arguments );
        return newInstance( constructor, testArtifactInfo.getVersion(), testArtifactInfo.getClassifier() );
    }

    private Object createReporterConfiguration( ReporterConfiguration reporterConfig )
    {
        Constructor<?> constructor = getConstructor( reporterConfiguration, File.class, boolean.class );
        return newInstance( constructor, reporterConfig.getReportsDirectory(), reporterConfig.isTrimStackTrace() );
    }

    public Object createBooterConfiguration( ClassLoader surefireClassLoader, boolean insideFork )
    {
        return instantiateOneArg( surefireClassLoader, BaseProviderFactory.class.getName(), boolean.class, insideFork );
    }

    public Object instantiateProvider( String providerClassName, Object booterParameters )
    {
        return instantiateOneArg( surefireClassLoader, providerClassName, this.booterParameters, booterParameters );
    }

    public void setIfDirScannerAware( Object o, DirectoryScannerParameters dirScannerParams )
    {
        if ( baseProviderFactory.isAssignableFrom( o.getClass() ) )
        {
            setDirectoryScannerParameters( o, dirScannerParams );
        }
    }

    public void setMainCliOptions( Object o, List<CommandLineOption> options )
    {
        if ( baseProviderFactory.isAssignableFrom( o.getClass() ) )
        {
            List<Enum<?>> newOptions = checkedList( new ArrayList<Enum<?>>( options.size() ), commandLineOptionsClass );
            Collection<Integer> ordinals = toOrdinals( options );
            for ( Enum<?> e : commandLineOptionsClass.getEnumConstants() )
            {
                if ( ordinals.contains( e.ordinal() ) )
                {
                    newOptions.add( e );
                }
            }
            invokeSetter( o, "setMainCliOptions", List.class, newOptions );
        }
    }

    public void setSkipAfterFailureCount( Object o, int skipAfterFailureCount )
    {
        invokeSetter( o, "setSkipAfterFailureCount", int.class, skipAfterFailureCount );
    }

    public void setSystemExitTimeout( Object o, Integer systemExitTimeout )
    {
        invokeSetter( o, "setSystemExitTimeout", Integer.class, systemExitTimeout );
    }

    void setDirectoryScannerParameters( Object o, DirectoryScannerParameters dirScannerParams )
    {
        Object param = createDirectoryScannerParameters( dirScannerParams );
        invokeSetter( o, "setDirectoryScannerParameters", directoryScannerParameters, param );
    }

    public void setRunOrderParameters( Object o, RunOrderParameters runOrderParameters )
    {
        Object param = createRunOrderParameters( runOrderParameters );
        invokeSetter( o, "setRunOrderParameters", this.runOrderParameters, param );
    }

    public void setTestSuiteDefinitionAware( Object o, TestRequest testSuiteDefinition2 )
    {
        if ( baseProviderFactory.isAssignableFrom( o.getClass() ) )
        {
            setTestSuiteDefinition( o, testSuiteDefinition2 );
        }
    }

    void setTestSuiteDefinition( Object o, TestRequest testSuiteDefinition1 )
    {
        Object param = createTestRequest( testSuiteDefinition1 );
        invokeSetter( o, "setTestRequest", testRequest, param );
    }

    public void setProviderPropertiesAware( Object o, Map<String, String> properties )
    {
        if ( baseProviderFactory.isAssignableFrom( o.getClass() ) )
        {
            setProviderProperties( o, properties );
        }
    }

    void setProviderProperties( Object o, Map<String, String> providerProperties )
    {
        invokeSetter( o, "setProviderProperties", Map.class, providerProperties );
    }

    public void setReporterConfigurationAware( Object o, ReporterConfiguration reporterConfiguration1 )
    {
        if ( baseProviderFactory.isAssignableFrom( o.getClass() ) )
        {
            setReporterConfiguration( o, reporterConfiguration1 );
        }
    }

    private void setReporterConfiguration( Object o, ReporterConfiguration reporterConfiguration )
    {
        Object param = createReporterConfiguration( reporterConfiguration );
        invokeSetter( o, "setReporterConfiguration", this.reporterConfiguration, param );
    }

    public void setTestClassLoaderAware( Object o, ClassLoader testClassLoader )
    {
        if ( baseProviderFactory.isAssignableFrom( o.getClass() ) )
        {
            setTestClassLoader( o, testClassLoader );
        }
    }

    void setTestClassLoader( Object o, ClassLoader testClassLoader )
    {
        Method setter = getMethod( o, "setClassLoaders", ClassLoader.class );
        invokeMethodWithArray( o, setter, testClassLoader );
    }

    public void setTestArtifactInfoAware( Object o, TestArtifactInfo testArtifactInfo1 )
    {
        if ( baseProviderFactory.isAssignableFrom( o.getClass() ) )
        {
            setTestArtifactInfo( o, testArtifactInfo1 );
        }
    }

    void setTestArtifactInfo( Object o, TestArtifactInfo testArtifactInfo )
    {
        Object param = createTestArtifactInfo( testArtifactInfo );
        invokeSetter( o, "setTestArtifactInfo", this.testArtifactInfo, param );
    }

    public void setReporterFactoryAware( Object o, Object reporterFactory )
    {
        if ( baseProviderFactory.isAssignableFrom( o.getClass() ) )
        {
            setReporterFactory( o, reporterFactory );
        }
    }

    void setReporterFactory( Object o, Object reporterFactory )
    {
        invokeSetter( o, "setReporterFactory", this.reporterFactory, reporterFactory );
    }

    private boolean isRunResult( Object o )
    {
        return runResult.isAssignableFrom( o.getClass() );
    }

    private static Collection<Integer> toOrdinals( Collection<? extends Enum<?>> enums )
    {
        Collection<Integer> ordinals = new ArrayList<>( enums.size() );
        for ( Enum<?> e : enums )
        {
            ordinals.add( e.ordinal() );
        }
        return ordinals;
    }
}
