package org.strategoxt.imp.runtime.parser;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.Map;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.spoofax.interpreter.terms.IStrategoTerm;
import org.spoofax.jsglr.client.imploder.IToken;
import org.spoofax.jsglr.io.FileTools;
import org.spoofax.jsglr.shared.BadTokenException;
import org.spoofax.jsglr.shared.SGLRException;
import org.spoofax.jsglr.shared.TokenExpectedException;
import org.strategoxt.imp.runtime.stratego.SourceAttachment;
import org.strategoxt.lang.WeakValueHashMap;

/**
 * An abstract imploding SGLR parser class.
 *
 * @author Lennart Kats <L.C.L.Kats add tudelft.nl>
 */ 
public abstract class AbstractSGLRI {
	
	@SuppressWarnings("unused")
	private static final Map<ParseCacheKey, IStrategoTerm> parseCache =
		Collections.synchronizedMap(new WeakValueHashMap<ParseCacheKey, IStrategoTerm>());
	
	private final SGLRParseController controller;
	
	private boolean implodeEnabled = true;
		
	@SuppressWarnings("unused")
	private final Object parseTableId;
	
	private String startSymbol;
	
	// Simple accessors

	public int getEOFTokenKind() {
		return IToken.TK_EOF;
	}
	
	public SGLRParseController getController() {
		return controller;
	}
	
	public String getStartSymbol() {
		return startSymbol;
	}
	
	public void setStartSymbol(String startSymbol) {
		this.startSymbol = startSymbol;
	}
	
	@Deprecated
	public void setKeepAmbiguities(boolean value) {
		if (!value)
			throw new UnsupportedOperationException();
	}
	
	public void setImplodeEnabled(boolean implodeEnabled) {
		this.implodeEnabled = implodeEnabled;
	}
	
	public boolean isImplodeEnabled() {
		return implodeEnabled;
	}
	
	// Initialization and parsing
	
	public AbstractSGLRI(Object parseTableId, String startSymbol, SGLRParseController controller) {
		this.controller = controller;
		this.startSymbol = startSymbol;
		this.parseTableId = parseTableId;
	}
	
	// Parsing
	
	/**
	 * Parse an input, returning the AST and initializing the parse stream.
	 * 
	 * @return  The abstract syntax tree.
	 */
	public IStrategoTerm parse(String input, String filename)
			throws TokenExpectedException, BadTokenException, SGLRException, IOException {
		
		/* UNDONE: disabled the parse cache for now
		 * TODO: revise parse cache?
		 *       (should still be disabled for testing language)
		CachingKey cachingKey = new CachingKey(parseTableId, startSymbol, inputChars, filename);
		IStrategoTerm result = parsedCache.get(cachingKey);
		if (result != null) {
			currentTokenizer = getTokenizer(result);
			assert currentTokenizer != null;
			return result;
		}
		*/

		assert getController() == null || getController().getParseLock().isHeldByCurrentThread();
		IStrategoTerm result = doParse(input, filename);
		if (new NullProgressMonitor().isCanceled())
			throw new OperationCanceledException();
		SGLRParseController controller = getController() == null ? null : getController();
		IResource resource = controller == null ? null : controller.getResource();
		if(resource==null && filename !=null && new File(filename).exists()){
			IPath path = new Path(filename).makeRelativeTo(ResourcesPlugin.getWorkspace().getRoot().getLocation());
			resource=ResourcesPlugin.getWorkspace().getRoot().getFile(path);
		}
		if (controller != null || resource != null)
			SourceAttachment.putSource(result, resource, controller);
		
		// parsedCache.put(cachingKey, result);
		// putTokenizer(result, currentTokenizer);
		
		return result;
	}
	
	/**
	 * Parse an input, returning the AST and initializing the parse stream.
	 * Also initializes a new tokenizer for the given input.
	 * 
	 * @note This redirects to the preferred {@link #parse(String, String)} method.
	 * 
	 * @return  The abstract syntax tree.
	 */
	public final IStrategoTerm parse(InputStream input, String filename)
			throws TokenExpectedException, BadTokenException, SGLRException, IOException {
		
		String inputString = FileTools.loadFileAsString(new BufferedReader(new InputStreamReader(input)));
		return parse(inputString, filename);
	}
	
	protected abstract IStrategoTerm doParse(String input, String filename)
			throws TokenExpectedException, BadTokenException, SGLRException, IOException;
}
@@ -280,98 +280,8 @@
 ce;%0A
-import org.eclipse.core.resources.ResourcesPlugin;%0Aimport org.eclipse.core.runtime.IPath;%0A
 impo
@@ -393,46 +393,8 @@
 on;%0A
-import org.eclipse.core.runtime.Path;%0A
 impo
@@ -675,32 +675,90 @@
 ectedException;%0A
+import org.strategoxt.imp.runtime.stratego.EditorIOAgent;%0A
 import org.strat
@@ -3339,19 +3339,34 @@
 e !=null
- &&
+) %7B%0A%09%09%09File file =
  new Fil
@@ -3380,194 +3380,86 @@
 ame)
-.exists())%7B%0A%09%09%09IPath path = new Path(filename).makeRelativeTo(ResourcesPlugin.getWorkspace().getRoot().getLocation());%0A%09%09%09resource=ResourcesPlugin.getWorkspace().getRoot().getFile(path);
+;%0A%09%09%09if (file.exists()) %7B%0A%09%09%09%09resource = EditorIOAgent.getResource(file);%0A%09%09%09%7D
 %0A%09%09%7D

Use EditorIOAgent for path resolving