package org.antlr.mojo.antlr3;

import java.util.List;
import java.util.Set;
import java.util.HashSet;
import java.util.ArrayList;
import java.util.Collections;
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.net.URL;
import java.net.MalformedURLException;
import java.net.URLClassLoader;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.compiler.util.scan.mapping.SourceMapping;
import org.codehaus.plexus.compiler.util.scan.mapping.SuffixMapping;
import org.codehaus.plexus.compiler.util.scan.SourceInclusionScanner;
import org.codehaus.plexus.compiler.util.scan.SimpleSourceInclusionScanner;
import org.codehaus.plexus.compiler.util.scan.InclusionScanException;
import org.antlr.runtime.ANTLRFileStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.gunit.GrammarInfo;
import org.antlr.gunit.gUnitExecutor;
import org.antlr.gunit.AbstractTest;
import org.antlr.gunit.Interp;

/**
 * Takes gUnit scripts and directly performs testing.
 *
 * @goal gunit
 *
 * @phase test
 * @requiresDependencyResolution test
 * @requiresProject true
 *
 * @author Steve Ebersole
 */
public class GUnitExecuteMojo extends AbstractMojo {
	public static final String ANTLR_GROUP_ID = "org.antlr";
	public static final String ANTLR_ARTIFACT_NAME = "antlr";
	public static final String ANTLR_RUNTIME_ARTIFACT_NAME = "antlr-runtime";

	/**
     * INTERNAL : The Maven Project to which we are attached
     *
     * @parameter expression="${project}"
     * @required
     */
    private MavenProject project;

	/**
	 * INTERNAL : The artifacts associated to the dependencies defined as part
	 * of our configuration within the project to which we are being attached.
	 *
	 * @parameter expression="${plugin.artifacts}"
     * @required
     * @readonly
	 */
	private List<Artifact> pluginArtifacts;

	/**
     * Specifies the directory containing the gUnit testing files.
     *
     * @parameter expression="${basedir}/src/test/gunit"
     * @required
     */
    private File sourceDirectory;

    /**
     * A set of patterns for matching files from the sourceDirectory that
     * should be included as gUnit source files.
     *
     * @parameter
     */
    private Set<String> includes;

    /**
     * A set of exclude patterns.
     *
     * @parameter
     */
    private Set<String> excludes;

	/**
     * Specifies directory to which gUnit reports should get written.
     *
     * @parameter expression="${basedir}/target/gunit-report"
     * @required
     */
    private File reportDirectory;

	/**
	 * Should gUnit functionality be completely by-passed?
	 * <p>
	 * By default we skip gUnit tests if the user requested that all testing be skipped using 'maven.test.skip'</p>
	 *
	 * @parameter expression="${maven.test.skip}"
	 */
	private boolean skip;

	public Set<String> getIncludePatterns() {
		return includes == null || includes.isEmpty()
				? Collections.singleton( "**/*.testsuite" )
				: includes;
	}

	public Set<String> getExcludePatterns() {
		return excludes == null
				? Collections.<String>emptySet()
				: excludes;
	}


	public final void execute() throws MojoExecutionException, MojoFailureException {
		if ( skip ) {
			getLog().info( "Skipping gUnit processing" );
			return;
		}
		Artifact pluginAntlrArtifact = determinePluginAntlrArtifact();

		validateProjectsAntlrVersion( determineArtifactVersion( pluginAntlrArtifact ) );

		performExecution( determineProjectCompileScopeClassLoader( pluginAntlrArtifact ) );
	}

	private Artifact determinePluginAntlrArtifact() throws MojoExecutionException {
		for ( Artifact artifact : pluginArtifacts ) {
			boolean match = ANTLR_GROUP_ID.equals( artifact.getGroupId() )
					&& ANTLR_ARTIFACT_NAME.equals( artifact.getArtifactId() );
			if ( match ) {
				return artifact;
			}
		}
		throw new MojoExecutionException(
				"Unexpected state : could not locate " + ANTLR_GROUP_ID + ':' + ANTLR_ARTIFACT_NAME +
						" in plugin dependencies"
		);
	}

	private ArtifactVersion determineArtifactVersion(Artifact artifact) throws MojoExecutionException {
		try {
			return artifact.getVersion() != null
					? new DefaultArtifactVersion( artifact.getVersion() )
					: artifact.getSelectedVersion();
		}
		catch ( OverConstrainedVersionException e ) {
			throw new MojoExecutionException( "artifact [" + artifact.getId() + "] defined an overly constrained version range" );
		}
	}

	private void validateProjectsAntlrVersion(ArtifactVersion pluginAntlrVersion) throws MojoExecutionException {
		Artifact antlrArtifact = null;
		Artifact antlrRuntimeArtifact = null;

		if ( project.getCompileArtifacts() != null ) {
			for ( Object o : project.getCompileArtifacts() ) {
				final Artifact artifact = ( Artifact ) o;
				if ( ANTLR_GROUP_ID.equals( artifact.getGroupId() ) ) {
					if ( ANTLR_ARTIFACT_NAME.equals( artifact.getArtifactId() ) ) {
						antlrArtifact = artifact;
						break;
					}
					if ( ANTLR_RUNTIME_ARTIFACT_NAME.equals( artifact.getArtifactId() ) ) {
						antlrRuntimeArtifact = artifact;
					}
				}
			}
		}

		validateBuildTimeArtifact( antlrArtifact, pluginAntlrVersion );
		validateRunTimeArtifact( antlrRuntimeArtifact, pluginAntlrVersion );
	}

	@SuppressWarnings(value = "unchecked")
	protected void validateBuildTimeArtifact(Artifact antlrArtifact, ArtifactVersion pluginAntlrVersion)
			throws MojoExecutionException {
		if ( antlrArtifact == null ) {
			validateMissingBuildtimeArtifact();
			return;
		}

		// otherwise, lets make sure they match...
		ArtifactVersion projectAntlrVersion = determineArtifactVersion( antlrArtifact );
		if ( pluginAntlrVersion.compareTo( projectAntlrVersion ) != 0 ) {
			getLog().warn(
					"Encountered " + ANTLR_GROUP_ID + ':' + ANTLR_ARTIFACT_NAME + ':' + projectAntlrVersion.toString() +
							" which did not match Antlr version used by plugin [" + pluginAntlrVersion.toString() + "]"
			);
		}
	}

	protected void validateMissingBuildtimeArtifact() {
		// generally speaking, its ok for the project to not define a dep on the build-time artifact...
	}

	@SuppressWarnings(value = "unchecked")
	protected void validateRunTimeArtifact(Artifact antlrRuntimeArtifact, ArtifactVersion pluginAntlrVersion)
			throws MojoExecutionException {
		if ( antlrRuntimeArtifact == null ) {
			// its possible, if the project instead depends on the build-time (or full) artifact.
			return;
		}

		ArtifactVersion projectAntlrVersion = determineArtifactVersion( antlrRuntimeArtifact );
		if ( pluginAntlrVersion.compareTo( projectAntlrVersion ) != 0 ) {
			getLog().warn(
					"Encountered " + ANTLR_GROUP_ID + ':' + ANTLR_RUNTIME_ARTIFACT_NAME + ':' + projectAntlrVersion.toString() +
							" which did not match Antlr version used by plugin [" + pluginAntlrVersion.toString() + "]"
			);
		}
	}

	/**
	 * Builds the classloader to pass to gUnit.
	 *
	 * @param antlrArtifact The plugin's (our) Antlr dependency artifact.
	 *
	 * @return The classloader for gUnit to use
	 *
	 * @throws MojoExecutionException Problem resolving artifacts to {@link java.net.URL urls}.
	 */
	private ClassLoader determineProjectCompileScopeClassLoader(Artifact antlrArtifact)
			throws MojoExecutionException {
		ArrayList<URL> classPathUrls = new ArrayList<URL>();
		getLog().info( "Adding Antlr artifact : " + antlrArtifact.getId() );
		classPathUrls.add( resolveLocalURL( antlrArtifact ) );

		for ( String path : classpathElements() ) {
			try {
				getLog().info( "Adding project compile classpath element : " + path );
				classPathUrls.add( new File( path ).toURI().toURL() );
			}
			catch ( MalformedURLException e ) {
				throw new MojoExecutionException( "Unable to build path URL [" + path + "]" );
			}
		}

		return new URLClassLoader( classPathUrls.toArray( new URL[classPathUrls.size()] ), getClass().getClassLoader() );
	}

	protected static URL resolveLocalURL(Artifact artifact) throws MojoExecutionException {
		try {
			return artifact.getFile().toURI().toURL();
		}
		catch ( MalformedURLException e ) {
			throw new MojoExecutionException( "Unable to resolve artifact url : " + artifact.getId(), e );
		}
	}

	@SuppressWarnings( "unchecked" )
	private List<String> classpathElements() throws MojoExecutionException {
		try {
			// todo : should we combine both compile and test scoped elements?
			return ( List<String> ) project.getTestClasspathElements();
		}
		catch ( DependencyResolutionRequiredException e ) {
			throw new MojoExecutionException( "Call to Project#getCompileClasspathElements required dependency resolution" );
		}
	}

	private void performExecution(ClassLoader projectCompileScopeClassLoader) throws MojoExecutionException {
		getLog().info( "gUnit report directory : " + reportDirectory.getAbsolutePath() );
		if ( !reportDirectory.exists() ) {
			boolean directoryCreated = reportDirectory.mkdirs();
			if ( !directoryCreated ) {
				getLog().warn( "mkdirs() reported problem creating report directory" );
			}
		}

		Result runningResults = new Result();
		ArrayList<String> failureNames = new ArrayList<String>();

		System.out.println();
		System.out.println( "-----------------------------------------------------------" );
		System.out.println( " G U N I T   R E S U L T S" );
		System.out.println( "-----------------------------------------------------------" );

		for ( File script : collectIncludedSourceGrammars() ) {
			final String scriptPath = script.getAbsolutePath();
			System.out.println( "Executing script " + scriptPath );
			try {
				String scriptBaseName = StringUtils.chompLast( FileUtils.basename( script.getName() ), "." );

				ANTLRFileStream antlrStream = new ANTLRFileStream( scriptPath );
				GrammarInfo grammarInfo = Interp.parse( antlrStream );
				gUnitExecutor executor = new gUnitExecutor(
						grammarInfo,
						projectCompileScopeClassLoader,
						script.getParentFile().getAbsolutePath()
				);

				String report = executor.execTest();
				writeReportFile( new File( reportDirectory, scriptBaseName + ".txt" ), report );

				Result testResult = new Result();
				testResult.tests = executor.numOfTest;
				testResult.failures = executor.numOfFailure;
				testResult.invalids = executor.numOfInvalidInput;

				System.out.println( testResult.render() );

				runningResults.add( testResult );
				for ( AbstractTest test : executor.failures ) {
					failureNames.add( scriptBaseName + "#" + test.getHeader() );
				}
			}
			catch ( IOException e ) {
				throw new MojoExecutionException( "Could not open specified script file", e );
			}
			catch ( RecognitionException e ) {
				throw new MojoExecutionException( "Could not parse gUnit script", e );
			}
		}

		System.out.println();
		System.out.println( "Summary :" );
		if ( ! failureNames.isEmpty() ) {
			System.out.println( "  Found " + failureNames.size() + " failures" );
			for ( String name : failureNames ) {
				System.out.println( "    - " + name );
			}
		}
		System.out.println( runningResults.render() );
		System.out.println();

		if ( runningResults.failures > 0 ) {
			throw new MojoExecutionException( "Found gUnit test failures" );
		}

		if ( runningResults.invalids > 0 ) {
			throw new MojoExecutionException( "Found invalid gUnit tests" );
		}
	}

	private Set<File> collectIncludedSourceGrammars() throws MojoExecutionException {
		SourceMapping mapping = new SuffixMapping( "g", Collections.<String>emptySet() );
        SourceInclusionScanner scan = new SimpleSourceInclusionScanner( getIncludePatterns(), getExcludePatterns() );
        scan.addSourceMapping( mapping );
		try {
			return scan.getIncludedSources( sourceDirectory, null );
		}
		catch ( InclusionScanException e ) {
			throw new MojoExecutionException( "Error determining gUnit sources", e );
		}
	}

	private void writeReportFile(File reportFile, String results) {
		try {
			Writer writer = new FileWriter( reportFile );
			writer = new BufferedWriter( writer );
			try {
				writer.write( results );
				writer.flush();
			}
			finally {
				try {
					writer.close();
				}
				catch ( IOException ignore ) {
				}
			}
		}
		catch ( IOException e ) {
			getLog().warn(  "Error writing gUnit report file", e );
		}
	}

	private static class Result {
		private int tests = 0;
		private int failures = 0;
		private int invalids = 0;

		public String render() {
			return String.format( "Tests run: %d,  Failures: %d,  Invalid: %d", tests, failures, invalids );
		}

		public void add(Result result) {
			this.tests += result.tests;
			this.failures += result.failures;
			this.invalids += result.invalids;
		}
	}

}
