package org.strategoxt.imp.testing.strategies;

import static org.spoofax.interpreter.core.Tools.asJavaString;
import static org.spoofax.interpreter.core.Tools.isTermAppl;
import static org.spoofax.interpreter.core.Tools.termAt;

import org.spoofax.interpreter.core.InterpreterException;
import org.spoofax.interpreter.terms.IStrategoAppl;
import org.spoofax.interpreter.terms.IStrategoString;
import org.spoofax.interpreter.terms.IStrategoTerm;
import org.spoofax.interpreter.terms.ITermFactory;
import org.strategoxt.imp.runtime.Environment;
import org.strategoxt.imp.runtime.dynamicloading.BadDescriptorException;
import org.strategoxt.imp.runtime.services.StrategoObserver;
import org.strategoxt.imp.runtime.stratego.EditorIOAgent;
import org.strategoxt.lang.Context;
import org.strategoxt.lang.MissingStrategyException;
import org.strategoxt.lang.Strategy;

/**
 * Evaluate a strategy in a stratego instance belonging to a language plugin.
 * 
 * @author Lennart Kats <lennart add lclnet.nl>
 */
public class plugin_strategy_invoke_0_2 extends Strategy {

	public static plugin_strategy_invoke_0_2 instance = new plugin_strategy_invoke_0_2();

	/**
	 * @return Fail(trace) for strategy failure, Error(message) a string for errors, 
	 *         or Some(term) for success.
	 */
	@Override
	public IStrategoTerm invoke(Context context, IStrategoTerm current, IStrategoTerm languageName, IStrategoTerm strategy) {
		ITermFactory factory = context.getFactory();
		try {
			String dir = ((EditorIOAgent) context.getIOAgent()).getProjectPath();
			StrategoObserver observer = ObserverCache.getInstance().getObserver(asJavaString(languageName), dir);
			observer.getRuntime().setCurrent(current);
			if (isTermAppl(strategy) && ((IStrategoAppl) strategy).getName().equals("Strategy"))
				strategy = termAt(strategy, 0);
			if (observer.getRuntime().invoke(asJavaString(strategy))) {
				current = observer.getRuntime().current();
				current = factory.makeAppl(factory.makeConstructor("Some", 1), current);
				return current;
			} else {
				Context foreignContext = observer.getRuntime().getCompiledContext();
				// TODO: show only foreign part of stack trace (without using setTrace(), won't work here)
				IStrategoString trace = factory.makeString("rewriting failed\n" + context.getTraceString()
						+ (foreignContext != null ? foreignContext.getTraceString() : ""));
				//if (printTrace.invoke(context, trace) != null)
				//	observer.reportRewritingFailed();
				return factory.makeAppl(factory.makeConstructor("Fail", 1), trace);
			}
		} catch (MissingStrategyException e) {
			return factory.makeAppl(factory.makeConstructor("Error", 1),
					factory.makeString("Problem loading descriptor for testing: " + e.getLocalizedMessage()));
		} catch (BadDescriptorException e) {
			Environment.logException("Problem loading descriptor for testing", e);
			return factory.makeAppl(factory.makeConstructor("Error", 1),
					factory.makeString("Problem loading descriptor for testing: " + e.getLocalizedMessage()));
		} catch (InterpreterException e) {
			Environment.logException("Problem executing strategy for testing: " + strategy, e);
			return factory.makeAppl(factory.makeConstructor("Error", 1),
					factory.makeString(e.getLocalizedMessage()));
		} catch (RuntimeException e) {
			Environment.logException("Problem executing strategy for testing: " + strategy, e);
			return factory.makeAppl(factory.makeConstructor("Error", 1),
					factory.makeString(e.getClass().getName() + ": " + e.getLocalizedMessage() + " (see error log)"));
		}
	}

}

@@ -1462,16 +1462,17 @@
 %0A%09%09try %7B
+ 
 %0A%09%09%09Stri
@@ -2112,193 +2112,43 @@
 %09%09%09%09
-// TODO: show only foreign part of stack trace (without using setTrace(), won't work here)%0A%09%09%09%09IStrategoString trace = factory.makeString(%22rewriting failed%5Cn%22 + context.getTraceString()
+String trace = %22rewriting failed%5Cn%22
 %0A%09%09%09
@@ -2219,102 +2219,65 @@
  %22%22)
-)
 ;%0A%09%09%09%09
-//if (printTrace.invoke(context, trace) != null)%0A%09%09%09%09//%09observer.reportRewritingFailed(
+observer.getRuntime().getIOAgent().printError(trace
 );%0A%09
@@ -2339,22 +2339,42 @@
 l%22, 1), 
+factory.makeString(
 trace)
+)
 ;%0A%09%09%09%7D%0A%09

print stack trace if builder/runner test fails