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 java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.apache.maven.surefire.api.provider.SurefireProvider;
import org.apache.maven.surefire.api.report.ReporterException;
import org.apache.maven.surefire.api.suite.RunResult;
import org.apache.maven.surefire.api.testset.TestSetFailedException;

import static org.apache.maven.surefire.api.util.ReflectionUtils.getMethod;
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.invokeMethodWithArray2;

/**
 * Creates the surefire provider.
 * <br>
 *
 * @author Kristian Rosenvold
 */
public class ProviderFactory
{
    private final StartupConfiguration startupConfiguration;

    private final ProviderConfiguration providerConfiguration;

    private final ClassLoader classLoader;

    private final SurefireReflector surefireReflector;

    private final Object reporterManagerFactory;

    private static final Class[] INVOKE_PARAMETERS = { Object.class };

    private static final Class[] INVOKE_EMPTY_PARAMETER_TYPES = { };

    private static final Object[] INVOKE_EMPTY_PARAMETERS = { };

    public ProviderFactory( StartupConfiguration startupConfiguration, ProviderConfiguration providerConfiguration,
                            ClassLoader testsClassLoader, Object reporterManagerFactory )
    {
        this.providerConfiguration = providerConfiguration;
        this.startupConfiguration = startupConfiguration;
        this.surefireReflector = new SurefireReflector( testsClassLoader );
        this.classLoader = testsClassLoader;
        this.reporterManagerFactory = reporterManagerFactory;
    }

    public static RunResult invokeProvider( Object testSet, ClassLoader testsClassLoader, Object factory,
                                            ProviderConfiguration providerConfiguration, boolean insideFork,
                                            StartupConfiguration startupConfig, boolean restoreStreams )
        throws TestSetFailedException, InvocationTargetException
    {
        final PrintStream orgSystemOut = System.out;
        final PrintStream orgSystemErr = System.err;
        // Note that System.out/System.err are also read in the "ReporterConfiguration" instantiation
        // in createProvider below. These are the same values as here.

        try
        {
            return new ProviderFactory( startupConfig, providerConfiguration, testsClassLoader, factory )
                .createProvider( insideFork )
                .invoke( testSet );
        }
        finally
        {
            if ( restoreStreams && System.getSecurityManager() == null )
            {
                System.setOut( orgSystemOut );
                System.setErr( orgSystemErr );
            }
        }
    }

    public SurefireProvider createProvider( boolean isInsideFork )
    {
        final Thread currentThread = Thread.currentThread();
        final ClassLoader systemClassLoader = currentThread.getContextClassLoader();
        currentThread.setContextClassLoader( classLoader );
        // Note: Duplicated in ForkedBooter#createProviderInCurrentClassloader
        Object o = surefireReflector.createBooterConfiguration( classLoader, isInsideFork );
        surefireReflector.setReporterFactoryAware( o, reporterManagerFactory );
        surefireReflector.setTestSuiteDefinitionAware( o, providerConfiguration.getTestSuiteDefinition() );
        surefireReflector.setProviderPropertiesAware( o, providerConfiguration.getProviderProperties() );
        surefireReflector.setReporterConfigurationAware( o, providerConfiguration.getReporterConfiguration() );
        surefireReflector.setTestClassLoaderAware( o, classLoader );
        surefireReflector.setTestArtifactInfoAware( o, providerConfiguration.getTestArtifact() );
        surefireReflector.setRunOrderParameters( o, providerConfiguration.getRunOrderParameters() );
        surefireReflector.setIfDirScannerAware( o, providerConfiguration.getDirScannerParams() );
        surefireReflector.setMainCliOptions( o, providerConfiguration.getMainCliOptions() );
        surefireReflector.setSkipAfterFailureCount( o, providerConfiguration.getSkipAfterFailureCount() );
        if ( isInsideFork )
        {
            surefireReflector.setSystemExitTimeout( o, providerConfiguration.getSystemExitTimeout() );
        }

        Object provider = surefireReflector.instantiateProvider( startupConfiguration.getActualClassName(), o );
        currentThread.setContextClassLoader( systemClassLoader );

        return new ProviderProxy( provider, classLoader );
    }

    private final class ProviderProxy
        implements SurefireProvider
    {
        private final Object providerInOtherClassLoader;

        private final ClassLoader testsClassLoader;


        private ProviderProxy( Object providerInOtherClassLoader, ClassLoader testsClassLoader )
        {
            this.providerInOtherClassLoader = providerInOtherClassLoader;
            this.testsClassLoader = testsClassLoader;
        }

        @Override
        @SuppressWarnings( "unchecked" )
        public Iterable<Class<?>> getSuites()
        {
            ClassLoader current = swapClassLoader( testsClassLoader );
            try
            {
                return (Iterable<Class<?>>) invokeGetter( providerInOtherClassLoader, "getSuites" );
            }
            finally
            {
                Thread.currentThread().setContextClassLoader( current );
            }
        }

        @Override
        public RunResult invoke( Object forkTestSet )
            throws ReporterException, InvocationTargetException
        {
            ClassLoader current = swapClassLoader( testsClassLoader );
            try
            {
                Method invoke = getMethod( providerInOtherClassLoader.getClass(), "invoke", INVOKE_PARAMETERS );
                Object result = invokeMethodWithArray2( providerInOtherClassLoader, invoke, forkTestSet );
                return (RunResult) surefireReflector.convertIfRunResult( result );
            }
            finally
            {
                if ( System.getSecurityManager() == null )
                {
                    Thread.currentThread().setContextClassLoader( current );
                }
            }
        }

        private ClassLoader swapClassLoader( ClassLoader newClassLoader )
        {
            ClassLoader current = Thread.currentThread().getContextClassLoader();
            Thread.currentThread().setContextClassLoader( newClassLoader );
            return current;
        }

        @Override
        public void cancel()
        {
            Class<?> providerType = providerInOtherClassLoader.getClass();
            Method invoke = getMethod( providerType, "cancel", INVOKE_EMPTY_PARAMETER_TYPES );
            invokeMethodWithArray( providerInOtherClassLoader, invoke, INVOKE_EMPTY_PARAMETERS );
        }
    }
}
