package org.strategoxt.imp.testing.cmd.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.apache.commons.vfs2.FileObject;
import org.metaborg.spoofax.core.context.SpoofaxContext;
import org.metaborg.spoofax.core.language.ILanguage;
import org.metaborg.spoofax.core.language.ILanguageService;
import org.metaborg.spoofax.core.resource.ResourceService;
import org.metaborg.spoofax.core.stratego.StrategoRuntimeService;
import org.metaborg.sunshine.environment.ServiceRegistry;
import org.spoofax.interpreter.core.InterpreterException;
import org.spoofax.interpreter.core.UndefinedStrategyException;
import org.spoofax.interpreter.terms.IStrategoAppl;
import org.spoofax.interpreter.terms.IStrategoTerm;
import org.spoofax.interpreter.terms.ITermFactory;
import org.strategoxt.HybridInterpreter;
import org.strategoxt.lang.Context;
import org.strategoxt.lang.Strategy;

/**
 * Evaluate a strategy in a stratego instance belonging to a language plugin.
 */
public class plugin_strategy_invoke_0_2 extends Strategy {
    public static final 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) {
        final ITermFactory factory = context.getFactory();
        final ServiceRegistry env = ServiceRegistry.INSTANCE();
        final ILanguage lang = env.getService(ILanguageService.class).get(asJavaString(languageName));
        final FileObject location =
            env.getService(ResourceService.class).resolve(context.getIOAgent().getWorkingDir());
        final HybridInterpreter runtime =
            env.getService(StrategoRuntimeService.class).runtime(new SpoofaxContext(lang, location));

        // strategy should be a String
        if(isTermAppl(strategy) && ((IStrategoAppl) strategy).getName().equals("Strategy"))
            strategy = termAt(strategy, 0);

        runtime.setCurrent(current);
        // TODO catch blocks copied from eclipse-specific code.
        // Why do we need them? Don't we want to fail fast?
        try {
            if(runtime.invoke(asJavaString(strategy))) {
                current = runtime.current();
                current = factory.makeAppl(factory.makeConstructor("Some", 1), current);
                return current;
            } else {
                Context foreignContext = runtime.getCompiledContext();
                String trace =
                    "rewriting failed\n" + (foreignContext != null ? foreignContext.getTraceString() : "");
                return factory.makeAppl(factory.makeConstructor("Fail", 1), factory.makeString(trace));
            }
        } catch(UndefinedStrategyException e) {
            return factory.makeAppl(
                factory.makeConstructor("Error", 1),
                factory.makeString("Problem executing foreign strategy for testing: "
                    + e.getLocalizedMessage()));
        } catch(InterpreterException e) {
            return factory.makeAppl(factory.makeConstructor("Error", 1),
                factory.makeString(e.getLocalizedMessage()));
        } catch(RuntimeException e) {
            return factory.makeAppl(
                factory.makeConstructor("Error", 1),
                factory.makeString(e.getClass().getName() + ": " + e.getLocalizedMessage()
                    + " (see error log)"));
        }
    }
}

@@ -270,16 +270,76 @@
 Object;%0A
+import org.metaborg.spoofax.core.context.ContextIdentifier;%0A
 import o
@@ -1432,23 +1432,8 @@
  for
-%0A     *        
  suc
@@ -1851,28 +1851,16 @@
 cation =
-%0A           
  env.get
@@ -2044,16 +2044,33 @@
 runtime(
+%0A                
 new Spoo
@@ -2084,22 +2084,38 @@
 ext(
-lang, 
+new ContextIdentifier(
 location
 ));%0A
@@ -2110,16 +2110,23 @@
 location
+, lang)
 ));%0A%0A   
@@ -2818,36 +2818,16 @@
  trace =
-%0A                   
  %22rewrit
@@ -3109,33 +3109,16 @@
 akeAppl(
-%0A                
 factory.
@@ -3231,36 +3231,16 @@
 sting: %22
-%0A                   
  + e.get
@@ -3375,32 +3375,16 @@
 or%22, 1),
-%0A               
  factory
@@ -3496,33 +3496,16 @@
 akeAppl(
-%0A                
 factory.
@@ -3627,28 +3627,8 @@
 ge()
-%0A                   
  + %22

Update to latest Spoofax core.