/**********************************************************************
 * This file is part of "Object Teams Development Tooling"-Software
 * 
 * Copyright 2010, 2014 Stephan Herrmann
 * 
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 * 
 * Please visit http://www.eclipse.org/objectteams for updates and contact.
 * 
 * Contributors:
 * 	  Stephan Herrmann - Initial API and implementation
 **********************************************************************/
package org.eclipse.objectteams.otdt.tests.otjld;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Map;

import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.core.tests.compiler.regression.AbstractComparableTest;
import org.eclipse.jdt.core.tests.compiler.regression.InMemoryNameEnvironment;
import org.eclipse.jdt.core.tests.compiler.regression.RegressionTestSetup;
import org.eclipse.jdt.core.tests.compiler.regression.Requestor;
import org.eclipse.jdt.core.tests.util.CompilerTestSetup;
import org.eclipse.jdt.core.tests.util.TestVerifier;
import org.eclipse.jdt.core.tests.util.Util;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.Compiler;
import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
import org.eclipse.jdt.internal.compiler.batch.FileSystem;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.objectteams.otdt.core.ext.WeavingScheme;
import org.eclipse.objectteams.otdt.tests.ClasspathUtil;

/**
 * Common super class for tests that were formerly implemented using jacks.
 * @author stephan
 */
public class AbstractOTJLDTest extends AbstractComparableTest {

	/** a test verifier that allows reusing a running vm even in the presence of (constant) vm arguments. */
	protected class OTTestVerifier extends TestVerifier {
		protected OTTestVerifier(boolean reuseVM) {
			super(reuseVM);
			this.fVMArguments = getOTVMArgs();
		}
		@Override
		public boolean verifyClassFiles(String sourceFilePath, String className, String expectedOutputString, String expectedErrorStringStart, 
										String[] classpaths, String[] programArguments, String[] vmArguments) {
			vmArguments = mergeArgs(vmArguments);
			return super.verifyClassFiles(sourceFilePath, className, expectedOutputString, expectedErrorStringStart, classpaths, programArguments, vmArguments);
		}
		@Override
		public boolean vmArgsEqual(String[] newArgs) {
			return super.vmArgsEqual(mergeArgs(newArgs));
		}
		protected String[] mergeArgs(String[] newArgs) {
			String[] OTVMArgs = getOTVMArgs();
			if (newArgs == null)
				return OTVMArgs;
			else {
				int l1 = OTVMArgs.length;
				int l2 = newArgs.length;
				String[] result = new String[l1+l2];
				System.arraycopy(OTVMArgs, 0, result, 0, l1);
				System.arraycopy(newArgs, 0, result, l1, l2);
				return result;
			}
		}
	}
	
	private static String getOTDTJarPath(String jarName) {
		return ClasspathUtil.OTDT_PATH + File.separator + "lib" + File.separator + jarName + ".jar";
	}
	
	public String[] getOTVMArgs() {
		String OTRE_MIN_JAR_PATH, OTAGENT_JAR_PATH;
		OTRE_MIN_JAR_PATH 		= getOTDTJarPath("otre_min");
		switch (this.weavingScheme) {
		case OTDRE:
			OTAGENT_JAR_PATH  		= getOTDTJarPath("otredyn_agent");
			break;
		case OTRE:
			OTAGENT_JAR_PATH  		= getOTDTJarPath("otre_agent");
			break;
		default:
			throw new IllegalStateException("Unsupported weavingScheme "+this.weavingScheme);
		}
		if (isJRE9Plus)
			return new String[] {
				"-javaagent:"+OTAGENT_JAR_PATH,
				"-Xbootclasspath/a:"+OTRE_MIN_JAR_PATH,
				"-Dot.dump=1",
				"-Dobjectteams.otdre.verify=1",
				"--add-reads",
				"java.base=ALL-UNNAMED",
				"--add-reads",
				"jdk.net=ALL-UNNAMED",
				"--add-opens",
				"java.base/java.lang=ALL-UNNAMED"
			};
		return new String[] {
				"-javaagent:"+OTAGENT_JAR_PATH,
				"-Xbootclasspath/a:"+OTRE_MIN_JAR_PATH,
				"-Dot.dump=1",
				"-Dobjectteams.otdre.verify=1"
		};
	}
	
	public static boolean IS_JRE_8;
	static {
		String javaVersion = System.getProperty("java.specification.version");
		IS_JRE_8 = "1.8".equals(javaVersion);
	}
	protected String foreach(String elemType) {
		return (IS_JRE_8 && this.complianceLevel < ClassFileConstants.JDK1_8) 
				? "public void forEach(java.util.function.Consumer<? super "+elemType+"> element) {}\n"
				: "";
	}
	protected String spliterator(String elemType) {
		return (IS_JRE_8 && this.complianceLevel < ClassFileConstants.JDK1_8) 
				? "public java.util.Spliterator<"+elemType+"> spliterator() { return null; }\n"
				: "";
	}
	protected String spliteratorCallout() {
		return (IS_JRE_8 && this.complianceLevel < ClassFileConstants.JDK1_8) ? "spliterator -> spliterator;\n" : "";
	}
	
// copy from JDT-orig for visibility's sake
	protected class Runner {
		public boolean shouldFlushOutputDirectory = true;
		// input:
		public String[] testFiles;
		public String[] dependantFiles;
		public String[] classLibraries;
		public boolean  libsOnModulePath;
		// control compilation:
		public Map<String,String> customOptions;
		public boolean performStatementsRecovery;
		public boolean generateOutput;
		public ICompilerRequestor customRequestor;
		// compiler result:
		public String expectedCompilerLog;
		public String[] alternateCompilerLogs;
		public boolean showCategory;
		public boolean showWarningToken;
		// javac:
		public boolean skipJavac;
		public String expectedJavacOutputString;
		public JavacTestOptions javacTestOptions;
		// execution:
		public boolean forceExecution;
		public String[] vmArguments;
		public String expectedOutputString;
		public String expectedErrorString;

		public ASTVisitor visitor;

		public Runner() {}

		public void runConformTest() {
			runTest(this.shouldFlushOutputDirectory,
					this.testFiles,
					this.dependantFiles != null ? this.dependantFiles : new String[] {},
					this.classLibraries,
					this.libsOnModulePath,
					this.customOptions,
					this.performStatementsRecovery,
					new Requestor(
							this.generateOutput,
							this.customRequestor,
							this.showCategory,
							this.showWarningToken),
					false,
					this.expectedCompilerLog,
					this.alternateCompilerLogs,
					this.forceExecution,
					this.vmArguments,
					this.expectedOutputString,
					this.expectedErrorString,
					this.visitor,
					this.expectedJavacOutputString != null ? this.expectedJavacOutputString : this.expectedOutputString,
					this.skipJavac ? JavacTestOptions.SKIP : this.javacTestOptions);
		}

		public void runNegativeTest() {
			runTest(this.shouldFlushOutputDirectory,
					this.testFiles,
					this.dependantFiles != null ? this.dependantFiles : new String[] {},
					this.classLibraries,
					this.libsOnModulePath,
					this.customOptions,
					this.performStatementsRecovery,
					new Requestor(
							this.generateOutput,
							this.customRequestor,
							this.showCategory,
							this.showWarningToken),
					true,
					this.expectedCompilerLog,
					this.alternateCompilerLogs,
					this.forceExecution,
					this.vmArguments,
					this.expectedOutputString,
					this.expectedErrorString,
					this.visitor,
					this.expectedJavacOutputString != null ? this.expectedJavacOutputString : this.expectedOutputString,
					this.skipJavac ? JavacTestOptions.SKIP : this.javacTestOptions);
		}

		public void runWarningTest() {
			runTest(this.shouldFlushOutputDirectory,
					this.testFiles,
					this.dependantFiles != null ? this.dependantFiles : new String[] {},
					this.classLibraries,
					this.libsOnModulePath,
					this.customOptions,
					this.performStatementsRecovery,
					new Requestor(
							this.generateOutput,
							this.customRequestor,
							this.showCategory,
							this.showWarningToken),
					false,
					this.expectedCompilerLog,
					this.alternateCompilerLogs,
					this.forceExecution,
					this.vmArguments,
					this.expectedOutputString,
					this.expectedErrorString,
					this.visitor,
					this.expectedJavacOutputString != null ? this.expectedJavacOutputString : this.expectedOutputString,
					this.skipJavac ? JavacTestOptions.SKIP : this.javacTestOptions);
		}
	}

	// ===
	
	protected static final JavacTestOptions DEFAULT_TEST_OPTIONS = new JavacTestOptions();

	// shall compiler output be matched exactly or using some matching?
	boolean errorMatching = false;
	
	// each subarray defines a set of classes to be compiled together:
	protected String[][] compileOrder;
	
	protected WeavingScheme weavingScheme = WeavingScheme.OTDRE;
	
	public AbstractOTJLDTest(String name) {
		super(name);
	}

	/** Add otre/otdre and (bcel or asm) to the class path. */
	@Override
	protected String[] getDefaultClassPaths() {
		String[] defaults = super.getDefaultClassPaths();
		int len = defaults.length;
		IPath[] bytecodeLibJarPath = ClasspathUtil.getWeaverPaths(this.weavingScheme);
		int len2 = bytecodeLibJarPath.length;
		System.arraycopy(defaults, 0, defaults=new String[len+1+len2], 0, len);
		defaults[len] = new Path(ClasspathUtil.getOTREPath(this.weavingScheme)).toString();
		for (int i=0; i<len2; i++)
			defaults[len+1+i] = bytecodeLibJarPath[i].toString();
		return defaults;
	}

	@Override
	public void initialize(CompilerTestSetup setUp) {
		super.initialize(setUp);
		if ("otre".equals(System.getProperty("ot.weaving"))
				||"otre".equals(System.getProperty("test.ot.weaving")))
			weavingScheme = WeavingScheme.OTRE;
		if (setUp instanceof RegressionTestSetup) {
			RegressionTestSetup regressionSetTup = (RegressionTestSetup) setUp;
			if (!(regressionSetTup.verifier instanceof OTTestVerifier)) {
				// overwrite plain TestVerifier:
				regressionSetTup.verifier = this.verifier = new OTTestVerifier(true/*reuseVM*/);
			}
		}
	}

	@Override
	protected TestVerifier getTestVerifier(boolean reuseVM) {
		return new OTTestVerifier(reuseVM);
	}
	
	@Override
	protected void tearDown() throws Exception {
		this.compileOrder = null;
		super.tearDown();
	}

	@SuppressWarnings("unchecked")
	@Override
	protected Map getCompilerOptions() {
		Map options = super.getCompilerOptions();
		options.put(CompilerOptions.OPTION_ReportUnnecessaryElse, CompilerOptions.IGNORE);
		options.put(CompilerOptions.OPTION_ReportSyntheticAccessEmulation, CompilerOptions.IGNORE);
		options.put(CompilerOptions.OPTION_ReportUnusedWarningToken, CompilerOptions.ERROR);
		options.put(CompilerOptions.OPTION_WeavingScheme, this.weavingScheme.name());
		// FIXME: consider setting to warning:
		options.put(CompilerOptions.OPTION_ReportOtreWeavingIntoJava8, CompilerOptions.IGNORE);
		return options;
	}
	
	protected void runNegativeTestMatching(String[] testFiles, String expectedCompilerLog) {
		this.errorMatching = true;
		runTest(
		 		// test directory preparation
				true /* flush output directory */,
				testFiles /* test files */,
				// compiler options
				null /* no class libraries */,
				null /* no custom options */,
				false /* do not perform statements recovery */,
				null /* no custom requestor */,
				// compiler results
				true /* expecting compiler errors */,
				expectedCompilerLog /* expected compiler log */,
				// runtime options
				false /* do not force execution */,
				null /* no vm arguments */,
				// runtime results
				null /* do not check output string */,
				null /* do not check error string */,
				// javac options
				DEFAULT_TEST_OPTIONS /* javac test options */);
		this.errorMatching = false;
	}

	/** Relaxed comparison using contains rather than equals. TODO(SH): pattern matching. */
	protected void checkCompilerLog(String[] testFiles, Requestor requestor,
			String[] alternatePlatformIndependantExpectedLogs, Throwable exception) {
		String computedProblemLog = Util.convertToIndependantLineDelimiter(requestor.problemLog.toString());
		for (String platformIndependantExpectedLog : alternatePlatformIndependantExpectedLogs) {
			if (computedProblemLog.contains(platformIndependantExpectedLog))
				return; // OK
		}
		logTestTitle();
		System.out.println(Util.displayString(computedProblemLog, INDENT, SHIFT));
		logTestFiles(false, testFiles);
		if (errorMatching && exception == null)
			fail("Invalid problem log\n"+computedProblemLog);
		if (!errorMatching && exception == null) {
			assertEquals("Invalid problem log ", alternatePlatformIndependantExpectedLogs[0], computedProblemLog);
		}
    }
	// inaccessible helper from super
	void logTestFiles(boolean logTitle, String[] testFiles) {
		if (logTitle) {
			logTestTitle();
		}
		for (int i = 0; i < testFiles.length; i += 2) {
			System.out.print(testFiles[i]);
			System.out.println(" ["); //$NON-NLS-1$
			System.out.println(testFiles[i + 1]);
			System.out.println("]"); //$NON-NLS-1$
		}
	}
	// inaccessible helper from super
	void logTestTitle() {
		System.out.println(getClass().getName() + '#' + getName());
	}
	
	// support explicit compile order in several steps:
	@Override
	protected void compileTestFiles(Compiler batchCompiler, String[] testFiles) {
		if (this.compileOrder == null) {
			batchCompiler.sortCompilationUnits = true;
			super.compileTestFiles(batchCompiler, testFiles);
		} else {
			for (String[] bunch : this.compileOrder) {
				String[] bunchFiles = new String[bunch.length * 2];
				int b = 0;
				for (int i = 0; i < bunch.length; i++) {
					int b0 = b;
					for (int j = 0; j < testFiles.length; j+=2) {
						if (bunch[i].equals(testFiles[j])) {
							bunchFiles[b++] = testFiles[j];
							bunchFiles[b++] = testFiles[j+1];
						}
					}
					assertTrue("Unmatched filename: "+bunch[i], b == b0+2);
				}
				super.compileTestFiles(batchCompiler, bunchFiles);
				batchCompiler.lookupEnvironment.nameEnvironment.cleanup(); // don't use chached info from previous runs
			}
		}
	}
	
	protected INameEnvironment getNameEnvironment(final String[] testFiles, String[] classPaths) {
		this.classpaths = classPaths == null ? getDefaultClassPaths() : classPaths;
		// make cleanup weaker:
		return new InMemoryNameEnvironment(testFiles, getClassLibs(false)) {
			@Override
			public void cleanup() {
				for (int i = 0, max = this.classLibs.length; i < max; i++)
					if (this.classLibs[i] instanceof FileSystem)
						((FileSystem) this.classLibs[i]).softReset();
			}
		};
	}
	
	/** Additional entry for tests expecting a compiler warning and don't run. */
	protected void runTestExpectingWarnings(String[] files, String expectedWarnings) {
    	Map options = getCompilerOptions();
		runConformTest(
	 		// test directory preparation
			true /* flush output directory */,
			files,
			// compiler options
			null /* no class libraries */,
			options /* custom options - happen to be the default not changed by the test suite */,
			// compiler results
			expectedWarnings,
			// runtime results
			null /* do not check output string */,
			null /* do not check error string */,
			// javac options
			JavacTestOptions.Excuse.EclipseHasSomeMoreWarnings /* javac test options */);	
	}
	
	/** Additional entry for tests expecting a compiler warning and don't run. */
	protected void runTestExpectingWarnings(String[] files, String expectedWarnings, Map options) {
		runConformTest(
	 		// test directory preparation
			true /* flush output directory */,
			files,
			// compiler options
			null /* no class libraries */,
			options /* custom options - happen to be the default not changed by the test suite */,
			// compiler results
			expectedWarnings,
			// runtime results
			null /* do not check output string */,
			null /* do not check error string */,
			// javac options
			JavacTestOptions.Excuse.EclipseHasSomeMoreWarnings /* javac test options */);	
	}
	
	/** Additional entry for tests expecting a compiler warning and don't run. */
	protected void runTestExpectingWarnings(String[] files, String expectedWarnings, boolean flushOutputDirectory) {
    	Map options = getCompilerOptions();
		runConformTest(
	 		// test directory preparation
			flushOutputDirectory,
			files,
			// compiler options
			null /* no class libraries */,
			options /* custom options - happen to be the default not changed by the test suite */,
			// compiler results
			expectedWarnings,
			// runtime results
			null /* do not check output string */,
			null /* do not check error string */,
			// javac options
			JavacTestOptions.Excuse.EclipseHasSomeMoreWarnings /* javac test options */);	
	}
	/** Additional entry for tests expecting a compiler warning and run. */
	protected void runTestExpectingWarnings(String[] files, String expectedWarnings, String expectedOutput) {
    	Map options = getCompilerOptions();
		runConformTest(
	 		// test directory preparation
			true/*flushOutputDirectory*/,
			files,
			// compiler options
			null /* no class libraries */,
			options /* custom options - happen to be the default not changed by the test suite */,
			// compiler results
			expectedWarnings,
			// runtime results
			expectedOutput,
			null /* do not check error string */,
			// javac options
			JavacTestOptions.Excuse.EclipseHasSomeMoreWarnings /* javac test options */);	
	}

	protected void myWriteFiles(String[] testFiles) {
		// force the directory to comply with the infrastructure from AbstractRegressionTest:
		String testName = null;
		try {
			testName = getName();
			setName("regression");
			// Write files in dir
			writeFiles(testFiles);
		} finally {
			setName(testName);
		}
	}
	
	protected String getTestResourcePath(String filename) {
        try
        {
            URL platformURL = Platform
				                .getBundle("org.eclipse.objectteams.otdt.tests")
				                .getEntry("/testresources/"+filename);
            return new File(FileLocator.toFileURL(platformURL).getFile())
                .getAbsolutePath();
        }
        catch (IOException ex)
        {
            ex.printStackTrace();
        }
        return null;
	}
	/** Create a vm arg for team activation and reset the verifier (avoid reuse of a running VM). */
	protected String[] getTeamActivationVMArgs(String relativeFilePath) {
		if (this.verifier != null)
			this.verifier.shutDown();
        this.verifier = getTestVerifier(false);
        this.createdVerifier = true;
		return new String[] {
				"-Dot.teamconfig="+OUTPUT_DIR+'/'+relativeFilePath
		};
	}
}
