package junit.runner;

import junit.framework.*;
import java.lang.reflect.*;
import java.text.NumberFormat;
import java.io.*;
import java.util.*;

/**
 * Base class for all test runners.
 * This class was born live on stage in Sardinia during XP2000.
 */
public abstract class BaseTestRunner implements TestListener {
	public static final String SUITE_METHODNAME= "suite";
	
	static Properties fPreferences;
	static int fgMaxMessageLength= 500;
	static boolean fgFilterStack= true;
	boolean fLoading= true;
	
	/**
	 * Returns the Test corresponding to the given suite. This is
	 * a template method, subclasses override runFailed(), clearStatus().
	 */
	public Test getTest(String suiteClassName) {
		if (suiteClassName.length() <= 0) {
			clearStatus();
			return null;
		}
		Class testClass= null;
		try {
			testClass= loadSuiteClass(suiteClassName);
		} catch (ClassNotFoundException e) {
			String clazz= e.getMessage();
			if (clazz == null) 
				clazz= suiteClassName;
			runFailed("Class not found \""+clazz+"\"");
			return null;
		} catch(Exception e) {
			runFailed("Error: "+e.toString());
			return null;
		}
		Method suiteMethod= null;
		try {
			suiteMethod= testClass.getMethod(SUITE_METHODNAME, new Class[0]);
	 	} catch(Exception e) {
	 		// try to extract a test suite automatically
			clearStatus();			
			return new TestSuite(testClass);
		}
		Test test= null;
		try {
			test= (Test)suiteMethod.invoke(null, new Class[0]); // static method
			if (test == null)
				return test;
		} 
		catch (InvocationTargetException e) {
			runFailed("Failed to invoke suite():" + e.getTargetException().toString());
			return null;
		}
		catch (IllegalAccessException e) {
			runFailed("Failed to invoke suite():" + e.toString());
			return null;
		}
		
		clearStatus();
		return test;
	}
	
	/**
	 * Returns the formatted string of the elapsed time.
	 */
	public String elapsedTimeAsString(long runTime) {
		return NumberFormat.getInstance().format((double)runTime/1000);
	}
	
	/**
	 * Processes the command line arguments and
	 * returns the name of the suite class to run or null
	 */
	protected String processArguments(String[] args) {
		String suiteName= null;
		for (int i= 0; i < args.length; i++) {
			if (args[i].equals("-noloading")) {
				setLoading(false);
			} else if (args[i].equals("-nofilterstack")) {
				fgFilterStack= false;
			} else if (args[i].equals("-c")) {
				if (args.length > i+1)
					suiteName= extractClassName(args[i+1]);
				else
					System.out.println("Missing Test class name");
				i++;
			} else {
				suiteName= args[i];
			}
		}
		return suiteName;		
	}

	/**
	 * Sets the loading behaviour of the test runner
	 */
	public void setLoading(boolean enable) {
		fLoading= enable;
	}
	/**
	 * Extract the class name from a String in VA/Java style
	 */
	public String extractClassName(String className) {
		if(className.startsWith("Default package for")) 
			return className.substring(className.lastIndexOf(".")+1);
		return className;
	}
	
	/**
	 * Truncates a String to the maximum length.
	 */
	public static String truncate(String s) {
		if (fgMaxMessageLength != -1 && s.length() > fgMaxMessageLength)
			s= s.substring(0, fgMaxMessageLength)+"...";
		return s;
	}
	
	/**
	 * Override to define how to handle a failed loading of
	 * a test suite.
	 */
	protected abstract void runFailed(String message);
	
	/**
	 * Returns the loaded Class for a suite name. 
	 */
	protected Class loadSuiteClass(String suiteClassName) throws ClassNotFoundException {
		return getLoader().load(suiteClassName);
	}
	
	/**
	 * Clears the status message.
	 */
	protected void clearStatus() { // Belongs in the GUI TestRunner class
	}
	
	/**
	 * Returns the loader to be used.
	 */
	public TestSuiteLoader getLoader() {
		if (useReloadingTestSuiteLoader())
			return new ReloadingTestSuiteLoader();
		return new StandardTestSuiteLoader();
	}
	
	protected boolean useReloadingTestSuiteLoader() {
		return getPreference("loading").equals("true") && !inVAJava() && fLoading;
	}
	
	private static File getPreferencesFile() {
	 	String home= System.getProperty("user.home");
 		return new File(home, "junit.properties");
 	}
 	
 	private static void readPreferences() {
 		InputStream is= null;
 		try {
 			is= new FileInputStream(getPreferencesFile());
 			fPreferences= new Properties(fPreferences);
			fPreferences.load(is);
		} catch (IOException e) {
			try {
				if (is != null)
					is.close();
			} catch (IOException e1) {
			}
		}
 	}
 	
 	public static String getPreference(String key) {
 		return fPreferences.getProperty(key);
 	}
 	
 	public static int getPreference(String key, int dflt) {
 		String value= getPreference(key);
 		int intValue= dflt;
 		if (value == null)
 			return intValue;
 		try {
 			intValue= Integer.parseInt(value);
 	 	} catch (NumberFormatException ne) {
 		}
 		return intValue;
 	}

 	public static boolean inVAJava() {
		try {
			Class.forName("com.ibm.uvm.tools.DebugSupport");
		}
		catch (Exception e) {
			return false;
		}
		return true;
	}


	/**
	 * Returns a filtered stack trace
	 */
	public static String getFilteredTrace(Throwable t) { 
		StringWriter stringWriter= new StringWriter();
		PrintWriter writer= new PrintWriter(stringWriter);
		t.printStackTrace(writer);
		StringBuffer buffer= stringWriter.getBuffer();
		String trace= buffer.toString();
		return BaseTestRunner.filterStack(trace);
	}

	/**
	 * Filters stack frames from internal JUnit classes
	 */
	public static String filterStack(String stack) {
		if (!getPreference("filterstack").equals("true") || fgFilterStack == false)
			return stack;
			
		StringWriter sw= new StringWriter();
		PrintWriter pw= new PrintWriter(sw);
		StringReader sr= new StringReader(stack);
		BufferedReader br= new BufferedReader(sr);
		
		String line;
		try {	
			while ((line= br.readLine()) != null) {
				if (!filterLine(line))
					pw.println(line);
			}
		} catch (Exception IOException) {
			return stack; // return the stack unfiltered
		}
		return sw.toString();
	}
	
	static boolean filterLine(String line) {
		String[] patterns= new String[] {
			"junit.framework.TestCase",
			"junit.framework.TestResult",
			"junit.framework.TestSuite",
			"junit.framework.Assert.", // don't filter AssertionFailure
			"junit.swingui.TestRunner",
			"junit.awtui.TestRunner",
			"junit.textui.TestRunner",
			"java.lang.reflect.Method.invoke("
		};
		for (int i= 0; i < patterns.length; i++) {
			if (line.indexOf(patterns[i]) > 0)
				return true;
		}
		return false;
	}

 	{
 		fPreferences= new Properties();
 		//JDK 1.2 feature
 		//fPreferences.setProperty("loading", "true");
 		fPreferences.put("loading", "true");
 		fPreferences.put("filterstack", "true");
  		readPreferences();
 		fgMaxMessageLength= getPreference("maxmessage", fgMaxMessageLength);
 	}
 	
}