package org.metaborg.meta.lang.dynsem.interpreter;

import java.io.InputStream;
import java.io.PrintStream;
import java.nio.file.Path;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.vfs2.FileObject;
import org.metaborg.core.MetaborgException;
import org.metaborg.core.language.ILanguageComponent;
import org.metaborg.meta.lang.dynsem.interpreter.nodes.building.ITermBuildFactory;
import org.metaborg.meta.lang.dynsem.interpreter.nodes.matching.ITermMatchPatternFactory;
import org.metaborg.spoofax.core.Spoofax;
import org.metaborg.spoofax.core.SpoofaxModule;
import org.strategoxt.HybridInterpreter;

import com.google.common.collect.Iterables;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;

public class DynSemContext {

	public static String DYNSEMPATH;

	public static DynSemLanguage LANGUAGE;

	private final InputStream input;
	private final PrintStream output;

	private final ITermRegistry termRegistry;
	private final RuleRegistry ruleRegistry;
	private final DynSemLanguageParser langParser;

	private DynSemPrimedRun primedRun;

	public DynSemContext(ITermRegistry termRegistry, RuleRegistry ruleRegistry, Path parseTable) {
		this(termRegistry, ruleRegistry, parseTable, System.in, System.out);
	}

	public DynSemContext(ITermRegistry termRegistry, RuleRegistry ruleRegistry, Path parseTable, InputStream input,
			PrintStream output) {
		this.termRegistry = termRegistry;
		this.ruleRegistry = ruleRegistry;
		this.input = input;
		this.output = output;
		this.langParser = new DynSemLanguageParser(parseTable);
	}

	private static HybridInterpreter dynsemStrategoRuntime;

	@TruffleBoundary
	public static HybridInterpreter getDynSemStrategoRuntime() {
		if (dynsemStrategoRuntime == null) {
			assert DYNSEMPATH != null;
			try {
				Spoofax spoofax = new Spoofax(new SpoofaxModule(ClassLoader.getSystemClassLoader()));
				FileObject dynsemResource = null;
				if (FilenameUtils.isExtension(DYNSEMPATH, "spoofax-language")) {
					dynsemResource = spoofax.resourceService.resolve("zip:" + DYNSEMPATH + "!/");
				} else {
					dynsemResource = spoofax.resourceService.resolve(DYNSEMPATH);
				}
				Iterable<ILanguageComponent> components = spoofax.discoverLanguages(dynsemResource);
				ILanguageComponent dynsem = Iterables.get(components, 0);

				dynsemStrategoRuntime = spoofax.strategoRuntimeService.runtime(dynsem,
						spoofax.resourceService.resolve(System.getProperty("user.dir")));
				dynsemStrategoRuntime.init();
			} catch (MetaborgException e) {
				throw new RuntimeException("Cannot initialize Spoofax", e);
			}
		}
		return dynsemStrategoRuntime;
	}

	public DynSemLanguageParser getParser() {
		return langParser;
	}

	public RuleRegistry getRuleRegistry() {
		return ruleRegistry;
	}

	public ITermRegistry getTermRegistry() {
		return termRegistry;
	}

	public DynSemPrimedRun getRun() {
		return primedRun;
	}

	public void setRun(DynSemPrimedRun run) {
		this.primedRun = run;
	}

	public ITermBuildFactory lookupTermBuilder(String name, int arity) {
		ITermBuildFactory f = termRegistry.lookupBuildFactory(name, arity);
		assert f != null;
		return f;
	}

	public ITermBuildFactory lookupNativeOpBuilder(String name, int arity) {
		ITermBuildFactory f = termRegistry.lookupNativeOpBuildFactory(name, arity);
		assert f != null;
		return f;
	}

	public ITermMatchPatternFactory lookupMatchPattern(String name, int arity) {
		ITermMatchPatternFactory f = termRegistry.lookupMatchFactory(name, arity);
		assert f != null;
		return f;
	}

	public ITermBuildFactory lookupNativeTypeAdapterBuildFactory(String sort, String function, int arity) {
		ITermBuildFactory f = termRegistry.lookupNativeTypeAdapterBuildFactory(sort, function, arity);
		assert f != null;
		return f;
	}

	public InputStream getInput() {
		return input;
	}

	public PrintStream getOutput() {
		return output;
	}

}

@@ -133,52 +133,8 @@
 h;%0A%0A
-import org.apache.commons.io.FilenameUtils;%0A
 impo
@@ -489,56 +489,8 @@
 ax;%0A
-import org.metaborg.spoofax.core.SpoofaxModule;%0A
 impo
@@ -1728,272 +1728,26 @@
 fax(
-new SpoofaxModule(ClassLoader.getSystemClassLoader()));%0A%09%09%09%09FileObject dynsemResource = null;%0A%09%09%09%09if (FilenameUtils.isExtension(DYNSEMPATH, %22spoofax-language%22)) %7B%0A%09%09%09%09%09dynsemResource = spoofax.resourceService.resolve(%22zip:%22 + DYNSEMPATH + %22!/%22);%0A%09%09%09%09%7D else %7B%0A%09%09%09%09%09
+);%0A%09%09%09%09FileObject 
 dyns
@@ -1808,14 +1808,8 @@
 H);%0A
-%09%09%09%09%7D%0A
 %09%09%09%09

Revert "Provide alternative loading scheme for DynSem Stratego strategies when loading from a spoofax-language package"