package org.apache.maven.surefire.testng;

/*
 * 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.booter.ProviderParameterNames;
import org.apache.maven.surefire.cli.CommandLineOption;
import org.apache.maven.surefire.report.RunListener;
import org.apache.maven.surefire.testng.conf.Configurator;
import org.apache.maven.surefire.testng.utils.FailFastEventsSingleton;
import org.apache.maven.surefire.testng.utils.FailFastListener;
import org.apache.maven.surefire.testng.utils.Stoppable;
import org.apache.maven.surefire.testset.TestListResolver;
import org.apache.maven.surefire.testset.TestSetFailedException;
import org.apache.maven.surefire.util.internal.StringUtils;
import org.testng.TestNG;
import org.testng.annotations.Test;
import org.testng.xml.XmlClass;
import org.testng.xml.XmlMethodSelector;
import org.testng.xml.XmlSuite;
import org.testng.xml.XmlTest;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import static org.apache.maven.surefire.cli.CommandLineOption.LOGGING_LEVEL_DEBUG;
import static org.apache.maven.surefire.cli.CommandLineOption.SHOW_ERRORS;
import static org.apache.maven.surefire.util.ReflectionUtils.instantiate;
import static org.apache.maven.surefire.util.ReflectionUtils.tryLoadClass;
import static org.apache.maven.surefire.util.internal.ConcurrencyUtils.countDownToZero;

/**
 * Contains utility methods for executing TestNG.
 *
 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
 * @author <a href='mailto:the[dot]mindstorm[at]gmail[dot]com'>Alex Popescu</a>
 */
final class TestNGExecutor
{
    /** The default name for a suite launched from the maven surefire plugin */
    private static final String DEFAULT_SUREFIRE_SUITE_NAME = "Surefire suite";

    /** The default name for a test launched from the maven surefire plugin */
    private static final String DEFAULT_SUREFIRE_TEST_NAME = "Surefire test";

    private static final boolean HAS_TEST_ANNOTATION_ON_CLASSPATH =
            tryLoadClass( TestNGExecutor.class.getClassLoader(), "org.testng.annotations.Test" ) != null;

    private TestNGExecutor()
    {
        throw new IllegalStateException( "not instantiable constructor" );
    }

    @SuppressWarnings( "checkstyle:parameternumbercheck" )
    static void run( Iterable<Class<?>> testClasses, File testSourceDirectory,
                            Map<String, String> options, // string,string because TestNGMapConfigurator#configure()
                            RunListener reportManager, File reportsDirectory,
                            TestListResolver methodFilter, List<CommandLineOption> mainCliOptions,
                            int skipAfterFailureCount )
        throws TestSetFailedException
    {
        TestNG testng = new TestNG( true );

        Configurator configurator = getConfigurator( options.get( "testng.configurator" ) );

        if ( isCliDebugOrShowErrors( mainCliOptions ) )
        {
            System.out.println( "Configuring TestNG with: " + configurator.getClass().getSimpleName() );
        }

        XmlMethodSelector groupMatchingSelector = createGroupMatchingSelector( options );
        XmlMethodSelector methodNameFilteringSelector = createMethodNameFilteringSelector( methodFilter );

        Map<String, SuiteAndNamedTests> suitesNames = new HashMap<String, SuiteAndNamedTests>();

        List<XmlSuite> xmlSuites = new ArrayList<XmlSuite>();
        for ( Class<?> testClass : testClasses )
        {
            TestMetadata metadata = findTestMetadata( testClass );

            SuiteAndNamedTests suiteAndNamedTests = suitesNames.get( metadata.suiteName );
            if ( suiteAndNamedTests == null )
            {
                suiteAndNamedTests = new SuiteAndNamedTests();
                suiteAndNamedTests.xmlSuite.setName( metadata.suiteName );
                configurator.configure( suiteAndNamedTests.xmlSuite, options );
                xmlSuites.add( suiteAndNamedTests.xmlSuite );

                suitesNames.put( metadata.suiteName, suiteAndNamedTests );
            }

            XmlTest xmlTest = suiteAndNamedTests.testNameToTest.get( metadata.testName );
            if ( xmlTest == null )
            {
                xmlTest = new XmlTest( suiteAndNamedTests.xmlSuite );
                xmlTest.setName( metadata.testName );
                addSelector( xmlTest, groupMatchingSelector );
                addSelector( xmlTest, methodNameFilteringSelector );
                xmlTest.setXmlClasses( new ArrayList<XmlClass>() );

                suiteAndNamedTests.testNameToTest.put( metadata.testName, xmlTest );
            }

            xmlTest.getXmlClasses().add( new XmlClass( testClass.getName() ) );
        }

        testng.setXmlSuites( xmlSuites );
        configurator.configure( testng, options );
        postConfigure( testng, testSourceDirectory, reportManager, reportsDirectory, skipAfterFailureCount,
                       extractVerboseLevel( options ) );
        testng.run();
    }

    private static boolean isCliDebugOrShowErrors( List<CommandLineOption> mainCliOptions )
    {
        return mainCliOptions.contains( LOGGING_LEVEL_DEBUG ) || mainCliOptions.contains( SHOW_ERRORS );
    }

    private static TestMetadata findTestMetadata( Class<?> testClass )
    {
        TestMetadata result = new TestMetadata();
        if ( HAS_TEST_ANNOTATION_ON_CLASSPATH )
        {
            Test testAnnotation = findAnnotation( testClass, Test.class );
            if ( null != testAnnotation )
            {
                if ( !StringUtils.isBlank( testAnnotation.suiteName() ) )
                {
                    result.suiteName = testAnnotation.suiteName();
                }

                if ( !StringUtils.isBlank( testAnnotation.testName() ) )
                {
                    result.testName = testAnnotation.testName();
                }
            }
        }
        return result;
    }

    private static <T extends Annotation> T findAnnotation( Class<?> clazz, Class<T> annotationType )
    {
        if ( clazz == null )
        {
            return null;
        }

        T result = clazz.getAnnotation( annotationType );
        if ( result != null )
        {
            return result;
        }

        return findAnnotation( clazz.getSuperclass(), annotationType );
    }

    private static class TestMetadata
    {
        private String testName = DEFAULT_SUREFIRE_TEST_NAME;

        private String suiteName = DEFAULT_SUREFIRE_SUITE_NAME;
    }

    private static class SuiteAndNamedTests
    {
        private XmlSuite xmlSuite = new XmlSuite();

        private Map<String, XmlTest> testNameToTest = new HashMap<String, XmlTest>();
    }

    private static void addSelector( XmlTest xmlTest, XmlMethodSelector selector )
    {
        if ( selector != null )
        {
            xmlTest.getMethodSelectors().add( selector );
        }
    }

    @SuppressWarnings( "checkstyle:magicnumber" )
    private static XmlMethodSelector createMethodNameFilteringSelector( TestListResolver methodFilter )
        throws TestSetFailedException
    {
        if ( methodFilter != null && !methodFilter.isEmpty() )
        {
            // the class is available in the testClassPath
            String clazzName = "org.apache.maven.surefire.testng.utils.MethodSelector";
            try
            {
                Class<?> clazz = Class.forName( clazzName );
                Method method = clazz.getMethod( "setTestListResolver", TestListResolver.class );
                method.invoke( null, methodFilter );
            }
            catch ( Exception e )
            {
                throw new TestSetFailedException( e.getMessage(), e );
            }

            XmlMethodSelector xms = new XmlMethodSelector();

            xms.setName( clazzName );
            // looks to need a high value
            xms.setPriority( 10000 );

            return xms;
        }
        else
        {
            return null;
        }
    }

    @SuppressWarnings( "checkstyle:magicnumber" )
    private static XmlMethodSelector createGroupMatchingSelector( Map<String, String> options )
        throws TestSetFailedException
    {
        final String groups = options.get( ProviderParameterNames.TESTNG_GROUPS_PROP );
        final String excludedGroups = options.get( ProviderParameterNames.TESTNG_EXCLUDEDGROUPS_PROP );

        if ( groups == null && excludedGroups == null )
        {
            return null;
        }

        // the class is available in the testClassPath
        final String clazzName = "org.apache.maven.surefire.testng.utils.GroupMatcherMethodSelector";
        try
        {
            Class<?> clazz = Class.forName( clazzName );

            // HORRIBLE hack, but TNG doesn't allow us to setup a method selector instance directly.
            Method method = clazz.getMethod( "setGroups", String.class, String.class );
            method.invoke( null, groups, excludedGroups );
        }
        catch ( Exception e )
        {
            throw new TestSetFailedException( e.getMessage(), e );
        }

        XmlMethodSelector xms = new XmlMethodSelector();

        xms.setName( clazzName );
        // looks to need a high value
        xms.setPriority( 9999 );

        return xms;
    }

    static void run( List<String> suiteFiles, File testSourceDirectory,
                            Map<String, String> options, // string,string because TestNGMapConfigurator#configure()
                            RunListener reportManager, File reportsDirectory, int skipAfterFailureCount )
        throws TestSetFailedException
    {
        TestNG testng = new TestNG( true );
        Configurator configurator = getConfigurator( options.get( "testng.configurator" ) );
        configurator.configure( testng, options );
        postConfigure( testng, testSourceDirectory, reportManager, reportsDirectory, skipAfterFailureCount,
                       extractVerboseLevel( options ) );
        testng.setTestSuites( suiteFiles );
        testng.run();
    }

    private static Configurator getConfigurator( String className )
    {
        try
        {
            return (Configurator) Class.forName( className ).newInstance();
        }
        catch ( InstantiationException e )
        {
            throw new RuntimeException( e );
        }
        catch ( IllegalAccessException e )
        {
            throw new RuntimeException( e );
        }
        catch ( ClassNotFoundException e )
        {
            throw new RuntimeException( e );
        }
    }

    private static void postConfigure( TestNG testNG, File sourcePath, final RunListener reportManager,
                                       File reportsDirectory, int skipAfterFailureCount, int verboseLevel )
            throws TestSetFailedException
    {
        // 0 (default): turn off all TestNG output
        testNG.setVerbose( verboseLevel );

        TestNGReporter reporter = createTestNGReporter( reportManager );
        testNG.addListener( (Object) reporter );

        if ( skipAfterFailureCount > 0 )
        {
            ClassLoader cl = Thread.currentThread().getContextClassLoader();
            testNG.addListener( instantiate( cl, "org.apache.maven.surefire.testng.utils.FailFastNotifier",
                                             Object.class ) );
            testNG.addListener( new FailFastListener( createStoppable( reportManager, skipAfterFailureCount ) ) );
        }

        if ( sourcePath != null )
        {
            try
            {
                testNG.setSourcePath( sourcePath.getCanonicalPath() );
            }
            catch ( IOException e )
            {
                throw new TestSetFailedException( e.getLocalizedMessage(), e );
            }
        }

        testNG.setOutputDirectory( reportsDirectory.getAbsolutePath() );
    }

    private static Stoppable createStoppable( final RunListener reportManager, int skipAfterFailureCount )
    {
        final AtomicInteger currentFaultCount = new AtomicInteger( skipAfterFailureCount );

        return new Stoppable()
        {
            @Override
            public void fireStopEvent()
            {
                if ( countDownToZero( currentFaultCount ) )
                {
                    FailFastEventsSingleton.getInstance().setSkipOnNextTest();
                }

                reportManager.testExecutionSkippedByUser();
            }
        };
    }

    // If we have access to IResultListener, return a ConfigurationAwareTestNGReporter
    // But don't cause NoClassDefFoundErrors if it isn't available; just return a regular TestNGReporter instead
    private static TestNGReporter createTestNGReporter( RunListener reportManager )
    {
        try
        {
            Class.forName( "org.testng.internal.IResultListener" );
            Class c = Class.forName( "org.apache.maven.surefire.testng.ConfigurationAwareTestNGReporter" );
            @SuppressWarnings( "unchecked" ) Constructor<?> ctor = c.getConstructor( RunListener.class );
            return (TestNGReporter) ctor.newInstance( reportManager );
        }
        catch ( InvocationTargetException e )
        {
            throw new RuntimeException( "Bug in ConfigurationAwareTestNGReporter", e.getCause() );
        }
        catch ( ClassNotFoundException e )
        {
            return new TestNGReporter( reportManager );
        }
        catch ( Exception e )
        {
            throw new RuntimeException( "Bug in ConfigurationAwareTestNGReporter", e );
        }
    }

    private static int extractVerboseLevel( Map<String, String> options )
        throws TestSetFailedException
    {
        try
        {
            String verbose = options.get( "surefire.testng.verbose" );
            return verbose == null ? 0 : Integer.parseInt( verbose );
        }
        catch ( NumberFormatException e )
        {
            throw new TestSetFailedException( "Provider property 'surefire.testng.verbose' should refer to "
                                                  + "number -1 (debug mode), 0, 1 .. 10 (most detailed).", e );
        }
    }
}
