/**********************************************************************
 * This file is part of "Object Teams Development Tooling"-Software
 *
 * Copyright 2004, 2014 Fraunhofer Gesellschaft, Munich, Germany,
 * for its Fraunhofer Institute and Computer Architecture and Software
 * Technology (FIRST), Berlin, Germany and Technical University Berlin,
 * Germany.
 *
 * 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:
 * 	  Fraunhofer FIRST - Initial API and implementation
 * 	  Technical University Berlin - Initial API and implementation
 **********************************************************************/
package org.eclipse.objectteams.otdt.tests.compiler;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import junit.textui.TestRunner;

import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.tests.util.Util;
import org.eclipse.jdt.internal.compiler.batch.Main;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.objectteams.otdt.core.ext.WeavingScheme;
import org.eclipse.objectteams.otdt.tests.ClasspathUtil;

/**
 * This class represents a base for testing the compiler with several files.
 *
 * @author Jan Wloka
 */
public class TestBase extends TestCase
{

	public static final String NL = "\r\n";

	public static final String CLASS_FILE_EXTENSION = ".class";
    public static final String JAVA_FILE_EXTENSION 	= ".java";
    public static final String LOG_FILE_EXTENSION 	= ".log";

    public static final String WORKSPACE_NAME 		= "testing-workspace";
    public static final String PROJECT_NAME 		= "TestProject";

	public static final String JAVA_HOME = System.getProperty("java.home");
	public static final String USER_HOME = System.getProperty("user.home");

	private WeavingScheme weavingScheme = WeavingScheme.OTDRE; // FIXME: test OTRE, too!

	public static final String JRE_JAR_PATH;
	static {
		String javaVersion = System.getProperty("java.version");
		if (javaVersion.length() > 3) {
			javaVersion = javaVersion.substring(0, 3);
		}
		long jdkLevel = CompilerOptions.versionToJdkLevel(javaVersion);
		if (jdkLevel >= ClassFileConstants.JDK9) {
			String jreDir = Util.getJREDirectory();
			JRE_JAR_PATH = Util.toNativePath(jreDir + "/lib/jrt-fs.jar");
		} else {
			String path = JAVA_HOME+File.separator+"lib"+File.separator+"rt.jar";
			if ((new File(path).exists())) {
				JRE_JAR_PATH = path;
			} else {
				JRE_JAR_PATH = JAVA_HOME+File.separator+"lib"+File.separator+"vm.jar";
				System.err.println("TestBase: using alternate jre "+JRE_JAR_PATH);
			}
		}
	}

    public static final String PROJECT_PATH = USER_HOME
													+ File.separator
													+ WORKSPACE_NAME
													+ File.separator
													+ PROJECT_NAME;


	private Main   _compiler;
    private String _logFileName;
    private File   _workingDir;

    public TestBase(String testName)
    {
    		super(testName);
    }

    private void cleanWorkingDirectory()
    {
       if (!_workingDir.isDirectory())
       {
       		return;
       }
       cleanRecursively(_workingDir);
//       File[] containedFiles = _workingDir.listFiles();
//
//       for (int idx = 0; idx < containedFiles.length; idx++)
//	   {
//	       	containedFiles[idx].delete();
//	   }
//
//	   _workingDir.delete();
    }
    private void cleanRecursively(File file) {
    	if (file.isDirectory()) {
    		for (File child : file.listFiles()) {
				cleanRecursively(child);
			}
    	}
    	file.delete();
    }

    // -- use default options: --
    public void compileFile(String fname)
    {
    	compileFile(fname, null);
    }
    public void compileFile(String fname, String[] classpath)
    {
		Map<String,String> options= new HashMap<String,String>();
		options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_5);
		options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5);
		options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
		options.put(CompilerOptions.OPTION_DocCommentSupport, CompilerOptions.ENABLED);
		options.put(CompilerOptions.OPTION_ReportInvalidJavadoc, CompilerOptions.ERROR);
		options.put(CompilerOptions.OPTION_ReportInvalidJavadocTags, CompilerOptions.ERROR);
		compileFile(fname, classpath, options);
    }
    // -- use custom options: --
    public void compileFile(String fname, String[] classpath, Map options)
    {
        System.out.println("*************************** "
        		+ this.getClass().getName()
				+" "
                + this.getName()
                + " ***************************");
        _logFileName = fname;

        try
        {
        	String missing;
	        if ((missing = missingClasspathEntry()) != null)
	        {
	            throw new FileNotFoundException("Missing library "+missing);
	        }

	        String[] args = (classpath == null)
	        					? createClassPath(fname)
	        					: classpath;

			File javaFile = new File(_workingDir.getAbsolutePath()
												+ File.separator
												+ fname
												+ JAVA_FILE_EXTENSION);

			if(!javaFile.exists())
			{
				throw new FileNotFoundException("File to compile was not found!: " + _logFileName);
			}

            _compiler =
                new Main(
                    new PrintWriter(
                    	new FileOutputStream(PROJECT_PATH
                    							+ File.separator
                    							+ _logFileName
                    							+ LOG_FILE_EXTENSION)),
                    new PrintWriter(
                    	new FileOutputStream(PROJECT_PATH
                    							+ File.separator
                    							+ _logFileName
                    							+ LOG_FILE_EXTENSION)),
                    false,
                    options,
                    null);

            _compiler.compile(args);
        }
        catch (FileNotFoundException ex)
        {
            handleException(ex);
        }
    }

    private String missingClasspathEntry()
    {
    	String otrePath = ClasspathUtil.getOTREPath(this.weavingScheme);
        File otreJar = new File(otrePath);
        File jreJar = new File(JRE_JAR_PATH);

        if (!otreJar.exists())
        	return otrePath;
        if (!jreJar.exists())
        	return JRE_JAR_PATH;
        return null;
    }

    public void createFile(String fname, String content)
    {
		try
		{
	    	File pkgDir = createPackageDirectory(content);
	        File file   = new File(pkgDir.getAbsolutePath()
        						+ File.separator
        						+ fname
        						+ JAVA_FILE_EXTENSION);
        file.deleteOnExit();

            FileWriter writer = new FileWriter(file);
            writer.write(content);
            writer.close();
        }
        catch (IOException ex)
        {
            handleException(ex);
        }
    }

	/**
	 * Creates a file at given relative position and all necessary directories
	 * The content of package is not evaluatet for saving location
	 * @param fname the name of the new file to create
	 * @param relPath the relative path where to store the file
	 * @param content the content
	 */
	public void createFileAt(String fname, String relPath, String content)
	{
		try
		{
			String curPath = _workingDir.getAbsolutePath();

			if(relPath.trim().length() > 0)
			{
				curPath+= File.separator + relPath;
			}

			File   pkgDir  = new File(curPath);
			pkgDir.mkdirs();

			File file   = new File(pkgDir.getAbsolutePath()
								+ File.separator
								+ fname
								+ JAVA_FILE_EXTENSION);
		file.deleteOnExit();

			FileWriter writer = new FileWriter(file);
			writer.write(content);
			writer.close();
		}
		catch (IOException ex)
		{
			handleException(ex);
		}
	}

    private File createPackageDirectory(String fileContent) throws IOException
    {
		String qualPkgName = getQualifiedPackageName(fileContent);
		String dirPath     = getDirectoryPath(qualPkgName);

    	String curPath = _workingDir.getAbsolutePath() + File.separator + dirPath;
		File   result  = new File(curPath);
		result.mkdirs();

        return result;
    }

    private String getDirectoryPath(String qualPkgName)
    {
        if ((qualPkgName == null) || (qualPkgName.trim().length() == 0))
        {
			return "";
        }

        if (qualPkgName.indexOf('.') == -1)
        {
        	return qualPkgName;
        }
        else
        {
			return qualPkgName.replaceAll("[.]", File.separator);
        }
    }

    private String getQualifiedPackageName(String fileContent)
    {
        String packageKeyword = "package ";

        int pos1 = fileContent.indexOf(packageKeyword);
		if (pos1 == -1)
		{
			return "";
		}

        int pos2 = fileContent.indexOf(';', pos1);
		if (pos2 == -1)
		{
			return "";
		}


        return fileContent.substring(pos1 + packageKeyword.length(), pos2);
    }

    private void handleException(Exception ex)
    {
        System.out.println("UNCAUGHT EXCEPTION: " + ex);
        ex.printStackTrace(System.out);
    }


    /**
     * checks whether the compiler has proceeded without errors or warnings
     */
	public boolean isCompilationSuccessful()
	{
		if (_compiler.globalErrorsCount != 0)
		{
			printAllProblems();
			return false;
		}
		else
		{
			File file = new File(_workingDir.getAbsolutePath()
									+ File.separator
									+ _logFileName
									+ LOG_FILE_EXTENSION);
			file.delete();
			return true;
		}
	}

	/**
	 * checks whether the compiler has generated the expected errors and warnings,
	 * if it created more problems than specified this is OK for this method.
	 * @param problemIDs IDs of the expected errors and warnings as specified in
	 *                   org.eclipse.jdt.core.compiler.IProblem
	 */
	public boolean hasAtLeastExpectedProblems(int[] problemIDs)
	{
		expected: for (int i = 0; i < problemIDs.length; i++) {
			for (int j = 0; j < _compiler.logger.globalProblems.size(); j++) {
				if (problemIDs[i] == ((IProblem)_compiler.logger.globalProblems.get(j)).getID())
					continue expected;
			}
			printAllProblems();
			return false;
		}
		File file = new File(_workingDir.getAbsolutePath()
								+ File.separator
								+ _logFileName
								+ LOG_FILE_EXTENSION);
		file.delete();
		return true;
	}

	/**
	 * checks whether the compiler has generated the expected errors and warnings
	 * @param problemIDs IDs of the expected errors and warnings as specified in
	 *                   org.eclipse.jdt.core.compiler.IProblem
	 */
	public boolean hasExpectedProblems(int[] problemIDs)
	{
		if ( areProblemsEqual(_compiler.logger.globalProblems, problemIDs) )
		{
			File file = new File(_workingDir.getAbsolutePath()
									+ File.separator
									+ _logFileName
									+ LOG_FILE_EXTENSION);
			file.delete();

			return true;
		}
		else
		{
			printAllProblems();
			return false;
		}
	}

    private void printAllProblems()
    {
        for (Iterator iter = _compiler.logger.globalProblems.iterator(); iter.hasNext();)
        {
            IProblem prob = (IProblem)iter.next();
        	System.err.println(prob.toString());
            if (prob.getID() == IProblem.Unclassified) // it was an exception.
                throw new InternalError(prob.toString());
        }
    }

	/**
	 * checks whether the compiler has generated the expected errors and warnings
	 * @param errorIDs IDs of the expected errors as specified in
	 *                 org.eclipse.jdt.core.compiler.IProblem
	 * @param warningIDs analogous
	 */
    public boolean hasExpectedProblems(int[] errorIDs, int[] warningIDs)
    {
 		if (   areProblemsEqual(_compiler.logger.globalErrors,   errorIDs)
 		    && areProblemsEqual(_compiler.logger.globalWarnings, warningIDs) )
        {

            File file = new File(_workingDir.getAbsolutePath()
            						+ File.separator
            						+ _logFileName
            						+ LOG_FILE_EXTENSION);
            file.delete();

            return true;
        }
        else
        {
        	return false;
        }
    }


    /**
     * @param problems	Vector elements of type IProblem
     */
    private boolean areProblemsEqual(List problems, int[] problemIDs)
    {
		if ( problemIDs == null)
		{
			return problems.isEmpty();
		}

        boolean result = true;

        if (problems.size() != problemIDs.length)
        {
            result = false;
        }
        for (Iterator iter = problems.iterator(); result && iter.hasNext();)
        {
            IProblem curProblem = (IProblem) iter.next();
            int curProblemID = curProblem.getID();

            boolean found = false;
            int idx = 0;

            while (!found && (idx < problemIDs.length))
            {
                if (curProblemID == problemIDs[idx])
                {
                    found = true;
                }
                idx++;
            }
            if (!found)
            {
                result = false;
            }
        }
        return result;
    }

//	public boolean isCompilationSuccessful(int errors, int warnings)
//	{
//		if (_compiler.globalErrorsCount != errors
//			|| _compiler.globalProblemsCount > (errors + warnings)
//			|| _compiler.globalWarningsCount != warnings)
//		{
//			return false;
//		}
//		else
//		{
//			// TODO (SH): check whether we have the expected problems.
//			File file = new File(_workingDir.getAbsolutePath()
//									+ File.separator
//									+ _logFileName
//									+ LOG_FILE_EXTENSION);
//			file.delete();
//
//			return true;
//		}
//	}


    private String[] createClassPath(String fname)
    {
        File javaFile = new File(_workingDir.getAbsolutePath()
        							+ File.separator
        							+ fname
        							+ JAVA_FILE_EXTENSION);

        String[] args =
        {
            "-classpath",
            new Path(ClasspathUtil.getOTREPath(this.weavingScheme)).toString()
                		+ File.pathSeparator
                		+ new Path(JRE_JAR_PATH).toString()
                		+ File.pathSeparator
                		+ new Path(_workingDir.getAbsolutePath()
                		+ File.separator).toString(),
            		 javaFile.getAbsolutePath()
        };

        return args;
    }

    protected String[] createClassPathNoOTRE(String fname)
    {
        File javaFile = new File(_workingDir.getAbsolutePath()
        							+ File.separator
        							+ fname
        							+ JAVA_FILE_EXTENSION);

        String[] args =
        {
            "-classpath",
            new Path(JRE_JAR_PATH).toString()
                		+ File.pathSeparator
                		+ new Path(_workingDir.getAbsolutePath()
                		+ File.separator).toString(),
            javaFile.getAbsolutePath()
        };

        return args;
    }


	protected void setUp() throws Exception
	{
		_workingDir = new File(PROJECT_PATH);
		cleanWorkingDirectory();
		_workingDir.mkdirs();
	}

    protected void tearDown() throws Exception
    {

    }

    /**
     * This method was added for convenient testing of single testmethods in testclasses.
     * The first commandline argument is expected to be the class where the
     * testmethod can be found. The following arguments are the testmethodnames
     * that should run.
     * example:
     * java Testbase org.eclipse.objectteams.otdt.tests.compiler.errorreporting.compiler.CalloutBindingTest testMultipleCalloutBinding1
     * @param args
     * @throws ClassNotFoundException
     * @throws SecurityException
     * @throws NoSuchMethodException
     * @throws IllegalArgumentException
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */

	public static void main(String[] args) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException
	{
		TestSuite selected = null;
		Constructor clsConst =null;

		switch (args.length)
		{
			case 0:
			{
				System.err.println("You must specify the class containing the testcases as argument.");
				System.exit(1);
				break; // duh
			}

			case 1: // take all methods
			{
				Class testClass = Class.forName(args[0]);
				selected = new TestSuite(testClass);
				break;
			}

			default: // single methods to execute given
			{
				Class<?> testClass = Class.forName(args[0]);
				clsConst = testClass.getConstructor( new Class<?>[] { String.class } );
				selected = new TestSuite();

				for (int idx = 1; idx < args.length; idx++)
				{
					selected.addTest((Test)clsConst.newInstance( new Object[] { args[idx] } ));
				}
			}
		}

		TestRunner.run(selected);
	}
}
