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 java.io.File;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.surefire.report.ReporterManager;
import org.apache.maven.surefire.suite.SurefireTestSuite;
import org.apache.maven.surefire.testng.conf.Configurator;
import org.apache.maven.surefire.testng.conf.TestNG4751Configurator;
import org.apache.maven.surefire.testng.conf.TestNG52Configurator;
import org.apache.maven.surefire.testng.conf.TestNGMapConfigurator;
import org.apache.maven.surefire.testset.TestSetFailedException;
import org.testng.IReporter;
import org.testng.TestNG;

/**
 * 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>
 */
public class TestNGExecutor
{
    private TestNGExecutor()
    {
    }

    public static void run( Class[] testClasses, String testSourceDirectory, Map options, ArtifactVersion version,
                            String classifier, ReporterManager reportManager, SurefireTestSuite suite, File reportsDirectory )
        throws TestSetFailedException
    {
        // kind of ugly, but listeners are configured differently
        final String listeners = (String) options.remove("listener");
        TestNG testng = new TestNG( false );
        Configurator configurator = getConfigurator( version );
        configurator.configure( testng, options );
        postConfigure( testng, testSourceDirectory, listeners, classifier, reportManager, suite, reportsDirectory );
        testng.setTestClasses( testClasses );
        testng.run();
    }

    public static void run( List suiteFiles, String testSourceDirectory, Map options, ArtifactVersion version,
                            String classifier, ReporterManager reportManager, SurefireTestSuite suite, File reportsDirectory )
        throws TestSetFailedException
    {
        TestNG testng = new TestNG( false );
        Configurator configurator = getConfigurator( version );
        configurator.configure( testng, options );
        postConfigure( testng, testSourceDirectory, (String) options.get("listener"), classifier, reportManager, suite, reportsDirectory );

        testng.setTestSuites( suiteFiles );
        testng.run();
    }

    private static Configurator getConfigurator( ArtifactVersion version ) throws TestSetFailedException
    {
        try
        {
            VersionRange range = VersionRange.createFromVersionSpec( "[4.7,5.1]" );
            if ( range.containsVersion( version ) )
            {
                return new TestNG4751Configurator();
            }
            range = VersionRange.createFromVersionSpec( "[5.2]" );
            if ( range.containsVersion( version ) )
            {
                return new TestNG52Configurator();
            }
            range = VersionRange.createFromVersionSpec( "[5.3,)" );
            if ( range.containsVersion( version ) )
            {
                return new TestNGMapConfigurator();
            }

            throw new TestSetFailedException( "Unknown TestNG version " + version );
        }
        catch ( InvalidVersionSpecificationException invsex )
        {
            throw new TestSetFailedException( "Bug in plugin. Please report it with the attached stacktrace", invsex );
        }
    }


    private static void postConfigure( TestNG testNG, String sourcePath, String listenerClasses, 
                                       String classifier, ReporterManager reportManager, SurefireTestSuite suite, File reportsDirectory )
        throws TestSetFailedException
    {
        // turn off all TestNG output
        testNG.setVerbose( 0 );

        TestNGReporter reporter = createTestNGReporter( reportManager, suite );
        testNG.addListener( (Object) reporter );
        attachNonStandardReporter( testNG, "org.testng.reporters.XMLReporter" );
        attachNonStandardReporter( testNG, "org.testng.reporters.FailedReporter" );
        // TODO: we should have the Profile so that we can decide if this is needed or not
        testNG.setListenerClasses(loadListenerClasses(listenerClasses));
        
        // FIXME: use classifier to decide if we need to pass along the source dir (onyl for JDK14)
        if ( sourcePath != null )
        {
            testNG.setSourcePath( sourcePath );
        }

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

    // 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( ReporterManager reportManager, SurefireTestSuite suite ) {
        try {
            Class.forName( "org.testng.internal.IResultListener" );
            Class c = Class.forName( "org.apache.maven.surefire.testng.ConfigurationAwareTestNGReporter" );
            try
            {
                Constructor ctor = c.getConstructor( new Class[] { ReporterManager.class, SurefireTestSuite.class } );
                return (TestNGReporter) ctor.newInstance( new Object[] { reportManager, suite } );
            }
            catch ( Exception e )
            {
                throw new RuntimeException("Bug in ConfigurationAwareTestNGReporter", e);
            }
        } catch (ClassNotFoundException e) {
            return new TestNGReporter( reportManager, suite );
        }
    }
    
    private static List loadListenerClasses(String listenerClasses) throws TestSetFailedException
    {
        if (listenerClasses == null || "".equals(listenerClasses.trim())) {
            return Collections.emptyList();
        }
        
        List classes = new ArrayList();
        String[] classNames = listenerClasses.split(" *, *");
        for(int i = 0; i < classNames.length; i++) 
        {
            try 
            {
                classes.add(Class.forName(classNames[i]));
            }
            catch(Exception ex) 
            {
                throw new TestSetFailedException("Cannot find listener class " + classNames[i], ex);
            }              
        }
        
        return classes;
    }

    private static void attachNonStandardReporter( TestNG testNG, String className )
    {
        try
        {
            Class c = Class.forName( className );
            if (IReporter.class.isAssignableFrom( c )) {
                testNG.addListener( c.newInstance() );
            }
        }
        catch ( Exception e ) {} // ignore
    }

}
