/*******************************************************************************
 * Copyright (c) 2008, 2011 Obeo.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Obeo - initial API and implementation
 *******************************************************************************/
package org.eclipse.acceleo.engine.internal.evaluation;

import com.google.common.base.Predicate;
import com.google.common.collect.Maps;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;

import org.eclipse.acceleo.common.IAcceleoConstants;
import org.eclipse.acceleo.common.preference.AcceleoPreferences;
import org.eclipse.acceleo.common.utils.AcceleoASTNodeAdapter;
import org.eclipse.acceleo.common.utils.CircularArrayDeque;
import org.eclipse.acceleo.common.utils.Deque;
import org.eclipse.acceleo.engine.AcceleoEngineMessages;
import org.eclipse.acceleo.engine.AcceleoEnginePlugin;
import org.eclipse.acceleo.engine.AcceleoEvaluationException;
import org.eclipse.acceleo.engine.AcceleoRuntimeException;
import org.eclipse.acceleo.engine.event.AcceleoTextGenerationEvent;
import org.eclipse.acceleo.engine.event.IAcceleoTextGenerationListener;
import org.eclipse.acceleo.engine.generation.strategy.IAcceleoGenerationStrategy;
import org.eclipse.acceleo.engine.generation.writers.AbstractAcceleoWriter;
import org.eclipse.acceleo.engine.generation.writers.AcceleoFileWriter;
import org.eclipse.acceleo.model.mtl.Block;
import org.eclipse.acceleo.model.mtl.Module;
import org.eclipse.acceleo.model.mtl.ModuleElement;
import org.eclipse.acceleo.model.mtl.ProtectedAreaBlock;
import org.eclipse.emf.common.EMFPlugin;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.util.BasicMonitor;
import org.eclipse.emf.common.util.Monitor;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.ocl.expressions.OCLExpression;
import org.eclipse.ocl.utilities.ASTNode;

/**
 * This will hold all necessary variables for the evaluation of an Acceleo module.
 * 
 * @param <C>
 *            This should be EClassifier for ecore, Class for UML.
 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
 */
public class AcceleoEvaluationContext<C> {
	/** Default size to be used for new buffers. */
	private static final int DEFAULT_BUFFER_SIZE = 1024;

	/** This is the tag we will look for to determine if a file has to be passed through JMerge. */
	private static final String JMERGE_TAG = "@generated"; //$NON-NLS-1$

	/** DOS line separators. */
	private static final String DOS_LINE_SEPARATOR = "\r\n"; //$NON-NLS-1$

	/** Unix line separators. */
	private static final String UNIX_LINE_SEPARATOR = "\n"; //$NON-NLS-1$

	/** Mac line separators. */
	private static final String MAC_LINE_SEPARATOR = "\r"; //$NON-NLS-1$

	/** Holds the generation preview in the form of mappings filePath => fileContent. */
	protected final Map<String, Writer> generationPreview = new HashMap<String, Writer>();

	/**
	 * This will hold the list of all listeners registered for notification on text generation from this
	 * engine.
	 * 
	 * @since 1.0
	 */
	protected final List<IAcceleoTextGenerationListener> listeners = new ArrayList<IAcceleoTextGenerationListener>(
			3);

	/**
	 * This will be set to true if one of the registered generation listener is interested in generation end
	 * notifications.
	 * 
	 * @since 3.0
	 */
	protected final boolean notifyOnGenerationEnd;

	/** This will maintain the stack trace of expression evaluations. */
	private Deque<OCLExpression<C>> expressionStack = new CircularArrayDeque<OCLExpression<C>>();

	/** References the file which is to be used as the root for all generated files. */
	private final File generationRoot;

	/** The state of his boolean will be changed while reading files prior to generation. */
	private boolean hasJMergeTag;

	/** This will be initialized with this generation's progress monitor. */
	private final Monitor progressMonitor;

	/** The current generation strategy. */
	private final IAcceleoGenerationStrategy strategy;

	/** This will keep a reference to all user code blocks of a given File. */
	private final Map<Writer, Map<String, String>> userCodeBlocks = new HashMap<Writer, Map<String, String>>();

	/** This will hold the buffer stack. */
	private final Deque<Writer> writers = new CircularArrayDeque<Writer>();

	/**
	 * If we try and generate something out of any context (for example, an "if" block outside of any Template
	 * or File), we'll use this "default" writer in order not to lose the generated text.
	 */
	private StringWriter defaultWriter;

	/**
	 * This will allow us to determine whether a given generation tried to generate one or more file(s) more
	 * than once.
	 */
	private Map<String, Integer> generateFiles = new HashMap<String, Integer>();

	/**
	 * Instantiates an evaluation context given the root of the to-be-generated files.
	 * 
	 * @param root
	 *            Root of all files that will be generated.
	 * @param listeners
	 *            The list of all listeners that are to be notified for text generation from this context.
	 * @param generationStrategy
	 *            The generation strategy that's to be used by this context.
	 * @param monitor
	 *            This will be used as the progress monitor for the generation.
	 */
	public AcceleoEvaluationContext(File root, List<IAcceleoTextGenerationListener> listeners,
			IAcceleoGenerationStrategy generationStrategy, Monitor monitor) {
		generationRoot = root;
		strategy = generationStrategy;
		this.listeners.addAll(listeners);
		if (monitor != null) {
			progressMonitor = monitor;
		} else {
			progressMonitor = new BasicMonitor();
		}

		boolean temp = false;
		for (IAcceleoTextGenerationListener listener : listeners) {
			if (listener.listensToGenerationEnd()) {
				temp = true;
				break;
			}
		}
		notifyOnGenerationEnd = temp;
	}

	/**
	 * Appends the given string to the last buffer of the context stack. This will notify all text generation
	 * listeners along the way.
	 * 
	 * @param string
	 *            String that is to be appended to the current buffer.
	 * @param sourceBlock
	 *            The block for which this text has been generated.
	 * @param source
	 *            The Object for which was generated this text.
	 * @param fireEvent
	 *            Tells us whether we should fire generation events.
	 * @throws AcceleoEvaluationException
	 *             Thrown if we cannot append to the current buffer.
	 */
	public void append(String string, Block sourceBlock, EObject source, boolean fireEvent)
			throws AcceleoEvaluationException {
		try {
			if (!writers.isEmpty()) {
				final Writer currentWriter = writers.getLast();
				currentWriter.append(string);
				if (fireEvent && string.length() > 0) {
					fireTextGenerated(new AcceleoTextGenerationEvent(string, sourceBlock, source));
				}
			} else {
				final String message = AcceleoEngineMessages
						.getString("AcceleoEvaluationVisitor.PossibleEmptyFileName"); //$NON-NLS-1$
				if (!EMFPlugin.IS_ECLIPSE_RUNNING || AcceleoPreferences.isDebugMessagesEnabled()) {
					AcceleoEnginePlugin.log(message, false);
				}
				if (defaultWriter == null) {
					defaultWriter = new StringWriter(DEFAULT_BUFFER_SIZE);
				}
				defaultWriter.append(string);
			}
		} catch (final IOException e) {
			throw new AcceleoEvaluationException(AcceleoEngineMessages
					.getString("AcceleoEvaluationContext.AppendError"), e); //$NON-NLS-1$
		}
	}

	/**
	 * Adds the given expression at the end of the expression stack.
	 * 
	 * @param expression
	 *            Expression that is to be appended to the expression stack trace.
	 */
	public void addToStack(OCLExpression<C> expression) {
		expressionStack.add(expression);
	}

	/**
	 * Allows clients to await for the lost file creation to end.
	 * 
	 * @throws InterruptedException
	 *             This will be thrown if the lost files creation is interrupted somehow.
	 */
	public void awaitCompletion() throws InterruptedException {
		strategy.awaitCompletion();
	}

	/**
	 * This will create and return an evaluation exception with a custom stack trace filled in for the given
	 * block. The <em>messageKey</em> should map to an actual message in
	 * <em>org/eclipse/acceleo/engine/acceleoenginemessages.properties</em>.
	 * 
	 * @param node
	 *            Node from which the failure originated.
	 * @param messageKey
	 *            This should map to the message that is to be retrieved for this exception.
	 * @param currentSelf
	 *            The last recorded value of the <em>self</em> variable.
	 * @return An evaluation exception for the given block.
	 */
	public AcceleoEvaluationException createAcceleoException(ASTNode node, String messageKey,
			Object currentSelf) {
		return createAcceleoException(node, null, messageKey, currentSelf);
	}

	/**
	 * This will create and return an evaluation exception with a custom stack trace filled in for the given
	 * block. The <em>messageKey</em> should map to an actual message in
	 * <em>org/eclipse/acceleo/engine/acceleoenginemessages.properties</em>.
	 * 
	 * @param node
	 *            Node from which the failure originated.
	 * @param expression
	 *            if the actual failure was caused by a subexpression of <em>block</em>, pass it here.
	 * @param messageKey
	 *            This should map to the message that is to be retrieved for this exception.
	 * @param currentSelf
	 *            The last recorded value of the <em>self</em> variable.
	 * @return An evaluation exception for the given block.
	 */
	public AcceleoEvaluationException createAcceleoException(ASTNode node, OCLExpression<C> expression,
			String messageKey, Object currentSelf) {
		Adapter adapter = EcoreUtil.getAdapter(node.eAdapters(), AcceleoASTNodeAdapter.class);
		int line = 0;
		if (adapter instanceof AcceleoASTNodeAdapter) {
			line = ((AcceleoASTNodeAdapter)adapter).getLine();
		}
		String moduleName = ((Module)EcoreUtil.getRootContainer(node)).getName();
		String message = AcceleoEngineMessages.getString(messageKey, Integer.valueOf(line), moduleName, node
				.toString(), currentSelf, expression);

		AcceleoFileWriter acceleoFileWriter = this.getAcceleoFileWriterFromContext();
		if (acceleoFileWriter != null) {
			message += " " + AcceleoEngineMessages.getString("AcceleoEvaluationContext.FileException", //$NON-NLS-1$ //$NON-NLS-2$
					acceleoFileWriter.getTargetPath());
		}

		final AcceleoEvaluationException exception = new AcceleoEvaluationException(message);
		exception.setStackTrace(createAcceleoStackTrace());
		return exception;
	}

	/**
	 * Returns the first Acceleo writer found in the context or <code>null</code> otherwise.
	 * 
	 * @return The first Acceleo writer found in the context or <code>null</code> otherwise.
	 */
	private AcceleoFileWriter getAcceleoFileWriterFromContext() {
		for (int i = writers.size() - 1; i >= 0; i--) {
			Writer writer = writers.get(i);
			if (writer instanceof AcceleoFileWriter) {
				return (AcceleoFileWriter)writer;
			}
		}
		return null;
	}

	/**
	 * Wraps the given throwable inside a custom Acceleo Exception.
	 * 
	 * @param cause
	 *            Actual cause of the failure.
	 * @return The created exception. Could be <code>null</code> if this context has already been disposed.
	 */
	public AcceleoRuntimeException createAcceleoRuntimeException(Throwable cause) {
		AcceleoRuntimeException exception = new AcceleoRuntimeException(cause);
		if (expressionStack.size() > 0) {
			StackTraceElement[] traceElements = createAcceleoStackTrace();
			if (traceElements.length > 0) {
				exception.setStackTrace(traceElements);
			}
		}
		return exception;
	}

	/**
	 * This will create a stack trace according to the current evaluation stack as recorded in
	 * {@link #expressionStack}.
	 * 
	 * @return Stack trace that can be used with {@link Exception#setStackTrace(StackTraceElement[])}.
	 */
	public StackTraceElement[] createAcceleoStackTrace() {
		StackTraceElement[] stackTrace = new StackTraceElement[expressionStack.size()];
		for (int i = expressionStack.size() - 1; i >= 0; i--) {
			OCLExpression<C> expression = expressionStack.get(i);

			EObject rootContainer = EcoreUtil.getRootContainer(expression);
			if (rootContainer instanceof Module) {
				Module containingModule = (Module)rootContainer;
				String moduleFile;
				if (containingModule.eResource() != null && containingModule.eResource().getURI() != null) {
					moduleFile = containingModule.eResource().getURI().trimFileExtension().lastSegment()
							+ '.' + IAcceleoConstants.MTL_FILE_EXTENSION;
				} else {
					moduleFile = containingModule.getName() + '.' + IAcceleoConstants.MTL_FILE_EXTENSION;
				}
				EObject containingModuleElement = expression;
				while (!(containingModuleElement instanceof ModuleElement)) {
					containingModuleElement = containingModuleElement.eContainer();
				}
				Adapter adapter = EcoreUtil.getAdapter(expression.eAdapters(), AcceleoASTNodeAdapter.class);
				int line = 0;
				if (adapter instanceof AcceleoASTNodeAdapter) {
					line = ((AcceleoASTNodeAdapter)adapter).getLine();
				}
				stackTrace[expressionStack.size() - i - 1] = new StackTraceElement(
						containingModule.getName(), containingModuleElement.toString(), moduleFile, line);
			} else if (rootContainer instanceof ProtectedAreaBlock) {
				// Let's not handle this now...
				stackTrace = new StackTraceElement[0];
			}
		}
		return stackTrace;
	}

	/**
	 * Closes the last writer of the stack and returns its result if it was a StringWriter. This is a
	 * convenience methode to close contexts that were opened for other than file blocks.
	 * 
	 * @return Result held by the last writer of the stack.
	 * @throws AcceleoEvaluationException
	 *             This will be thrown if the last writer of the stack cannot be flushed and closed.
	 */
	public String closeContext() throws AcceleoEvaluationException {
		return closeContext(null, null);
	}

	/**
	 * Closes the last writer of the stack and returns its result if it was a StringWriter. The empty String
	 * will be returned for FileWriters.
	 * 
	 * @param sourceBlock
	 *            The source block that first created this context. Only used when closing a file context.
	 * @param source
	 *            The source EObject for this block. Only used when closing a file context.
	 * @return Result held by the last writer of the stack.
	 * @throws AcceleoEvaluationException
	 *             This will be thrown if the last writer of the stack cannot be flushed and closed.
	 */
	public String closeContext(Block sourceBlock, EObject source) throws AcceleoEvaluationException {
		if (writers.isEmpty()) {
			final String message = AcceleoEngineMessages
					.getString("AcceleoEvaluationVisitor.PossibleEmptyFileName"); //$NON-NLS-1$
			if (!EMFPlugin.IS_ECLIPSE_RUNNING && AcceleoPreferences.isDebugMessagesEnabled()) {
				AcceleoEnginePlugin.log(message, false);
			}
			return ""; //$NON-NLS-1$
		}

		final Writer last = writers.removeLast();
		final String result;
		try {
			if (last instanceof AbstractAcceleoWriter) {
				final String filePath = ((AbstractAcceleoWriter)last).getTargetPath();
				final Map<String, String> lostCode = userCodeBlocks.get(last);
				if (lostCode.size() > 0) {
					Map<String, StringWriter> lostFiles = strategy.createLostFile(filePath, lostCode);
					if (lostFiles != null) {
						for (Map.Entry<String, StringWriter> lostFile : lostFiles.entrySet()) {
							generationPreview.put(lostFile.getKey(), lostFile.getValue());
						}
					}
				}
				strategy.flushWriter(filePath, last);
				fireFileGenerated(filePath, sourceBlock, source);
				result = ""; //$NON-NLS-1$
			} else if (last instanceof OutputStreamWriter) {
				last.close();
				result = ""; //$NON-NLS-1$
			} else {
				// others are plain StringWriters. Close has no effect on those.
				// Note that we'll never be here for file blocks : these always are AcceleoWriterDecorators
				result = last.toString();
			}
			return result;
		} catch (final IOException e) {
			throw new AcceleoEvaluationException(AcceleoEngineMessages
					.getString("AcceleoEvaluationContext.WriteError"), e); //$NON-NLS-1$
		}
	}

	/**
	 * This will be used to dispose of all created buffers and caches.
	 * 
	 * @throws AcceleoEvaluationException
	 *             Thrown if the disposal of the old writers fails.
	 */
	public void dispose() throws AcceleoEvaluationException {
		AcceleoEvaluationException exception = null;
		try {
			try {
				awaitCompletion();
			} catch (InterruptedException e) {
				exception = new AcceleoEvaluationException(AcceleoEngineMessages
						.getString("AcceleoEvaluationContext.CleanUpError"), e); //$NON-NLS-1$
			}
			try {
				for (final Writer writer : writers) {
					writer.close();
				}
			} catch (final IOException e) {
				exception = new AcceleoEvaluationException(AcceleoEngineMessages
						.getString("AcceleoEvaluationContext.CleanUpError"), e); //$NON-NLS-1$
			}
		} finally {
			generationPreview.clear();
			listeners.clear();
			userCodeBlocks.clear();
			writers.clear();
			expressionStack.clear();
		}
		if (exception != null) {
			throw exception;
		}
	}

	/**
	 * Notifies the context that a file at the given <em>filePath</em> will be generated.
	 * 
	 * @param filePath
	 *            Path to the file.
	 */
	public void generateFile(String filePath) {
		Integer timesGenerated = generateFiles.get(filePath);
		if (timesGenerated == null) {
			timesGenerated = Integer.valueOf(1);
		} else {
			timesGenerated = Integer.valueOf(timesGenerated.intValue() + 1);
		}
		generateFiles.put(filePath, timesGenerated);
	}

	/**
	 * This will return the indentation of the very last line of the very last file writer in context.
	 * 
	 * @return indentation of the very last line in context.
	 */
	public String getLastFileIndentation() {
		Writer writer = null;
		for (int i = writers.size() - 1; i >= 0 && !(writer instanceof AbstractAcceleoWriter); i--) {
			writer = writers.get(i);
		}
		if (writer != null) {
			return ((AbstractAcceleoWriter)writer).getCurrentLineIndentation();
		}
		return ""; //$NON-NLS-1$
	}

	/**
	 * Walks up the expression stack and returns the last visited Block.
	 * 
	 * @return The last visited Block.
	 */
	public Block getLastVisitedBlock() {
		if (expressionStack.isEmpty()) {
			return null;
		}
		final ListIterator<OCLExpression<C>> expressionIterator = expressionStack
				.listIterator(expressionStack.size());
		OCLExpression<C> previous;
		do {
			previous = expressionIterator.previous();
		} while (!(previous instanceof Block) && expressionIterator.hasPrevious());

		Block lastBlock = null;
		if (previous instanceof Block) {
			lastBlock = (Block)previous;
		}
		return lastBlock;
	}

	public Deque<OCLExpression<C>> getExpressionStack() {
		return expressionStack;
	}

	/**
	 * This will return the indentation of the very last line of the very last opened writer in context.
	 * 
	 * @return indentation of the very last line in context.
	 */
	public String getCurrentLineIndentation() {
		StringBuffer currentIndentation = new StringBuffer();
		if (!writers.isEmpty()) {
			Writer writer = writers.getLast();
			if (writer instanceof AbstractAcceleoWriter) {
				return ((AbstractAcceleoWriter)writer).getCurrentLineIndentation();
			}
			// Only String writers remain
			String content = writer.toString();
			int newLineIndex = -1;
			if (content.contains(DOS_LINE_SEPARATOR)) {
				newLineIndex = content.lastIndexOf(DOS_LINE_SEPARATOR) + DOS_LINE_SEPARATOR.length();
			} else if (content.contains(UNIX_LINE_SEPARATOR)) {
				newLineIndex = content.lastIndexOf(UNIX_LINE_SEPARATOR) + UNIX_LINE_SEPARATOR.length();
			} else if (content.contains(MAC_LINE_SEPARATOR)) {
				newLineIndex = content.lastIndexOf(MAC_LINE_SEPARATOR) + MAC_LINE_SEPARATOR.length();
			}

			if (newLineIndex == -1) {
				newLineIndex = 0;
			}
			for (int i = newLineIndex; i < content.length(); i++) {
				if (Character.isWhitespace(content.charAt(i))) {
					currentIndentation.append(content.charAt(i));
				} else {
					break;
				}
			}
		}
		return currentIndentation.toString();
	}

	/**
	 * Returns the text that has been appended to the default writer, if any.
	 * 
	 * @return The text that has been appended to the default writer, <code>null</code> if none.
	 */
	public String getDefaultText() {
		if (defaultWriter != null) {
			defaultWriter.flush();
			String text = defaultWriter.toString();
			defaultWriter = null;
			return text;
		}
		return null;
	}

	/**
	 * Returns the file that would be created for the given filePath according to the current generation root.
	 * 
	 * @param filePath
	 *            path of the file that will be generated.
	 * @return The File that would be created for the given filePath.
	 */
	public File getFileFor(String filePath) {
		final File generatedFile;
		if (filePath.startsWith("file:")) { //$NON-NLS-1$
			generatedFile = new File(filePath);
		} else {
			generatedFile = new File(generationRoot, filePath);
		}
		return generatedFile;
	}

	/**
	 * Returns the preview of the generation handled by this context.
	 * 
	 * @return The generation preview.
	 */
	public Map<String, String> getGenerationPreview() {
		return new HashMap<String, String>(strategy.preparePreview(generationPreview));
	}

	/**
	 * This will return the current progress monitor.
	 * 
	 * @return The current progress monitor.
	 */
	public Monitor getProgressMonitor() {
		return progressMonitor;
	}

	/**
	 * This will return the content of the protected area associated with the given marker in the current
	 * context.
	 * 
	 * @param marker
	 *            Marker of the sought protected area content.
	 * @return Content of the protected area associated with the given marker. <code>null</code> if no content
	 *         can be found.
	 */
	public String getProtectedAreaContent(String marker) {
		// Seeks out the last opened file writer
		Writer writer = null;
		for (int i = writers.size() - 1; i >= 0 && !(writer instanceof AbstractAcceleoWriter); i--) {
			writer = writers.get(i);
		}

		final Map<String, String> areas = userCodeBlocks.get(writer);
		if (areas != null) {
			return areas.remove(marker);
		}
		return null;
	}

	/**
	 * This will be called by the generation engine once all evaluations are finished for this generation. It
	 * will be used to call for the current generation strategy's global handlers.
	 */
	public void hookGenerationEnd() {
		final Map<String, Map<String, String>> lostCode = new HashMap<String, Map<String, String>>();
		for (Map.Entry<Writer, Map<String, String>> entry : userCodeBlocks.entrySet()) {
			if (!entry.getValue().isEmpty()) {
				final String filePath = ((AbstractAcceleoWriter)entry.getKey()).getTargetPath();
				lostCode.put(filePath, entry.getValue());
			}
		}
		if (!lostCode.isEmpty()) {
			strategy.createLostFiles(lostCode);
		}
		try {
			strategy.flushWriters(generationPreview);
		} catch (IOException e) {
			throw new AcceleoEvaluationException(AcceleoEngineMessages
					.getString("AcceleoEvaluationContext.WriteError"), e); //$NON-NLS-1$
		}

		Map<String, Integer> filteredFiles = Maps.filterEntries(generateFiles,
				new Predicate<Map.Entry<String, Integer>>() {
					public boolean apply(Map.Entry<String, Integer> input) {
						return input.getValue().intValue() > 1;
					}
				});

		if (!filteredFiles.isEmpty()) {
			final StringBuilder message = new StringBuilder(AcceleoEngineMessages
					.getString("AcceleoEvaluationContext.OverrodeFiles")); //$NON-NLS-1$
			message.append('\n').append('\n');
			for (Map.Entry<String, Integer> file : filteredFiles.entrySet()) {
				message.append(file.getKey() + " : " + file.getValue().toString() + " times" + '\n'); //$NON-NLS-1$ //$NON-NLS-2$
			}
			AcceleoEnginePlugin.log(message.toString(), false);
		}
	}

	/**
	 * Creates a new writer and appends it to the end of the stack.
	 * 
	 * @throws AcceleoEvaluationException
	 *             Thrown if the precedent buffer cannot be flushed.
	 */
	public void openNested() throws AcceleoEvaluationException {
		try {
			if (!writers.isEmpty()) {
				writers.getLast().flush();
			}
		} catch (final IOException e) {
			throw new AcceleoEvaluationException(AcceleoEngineMessages
					.getString("AcceleoEvaluationContext.FlushError"), e); //$NON-NLS-1$
		}
		writers.add(new StringWriter(DEFAULT_BUFFER_SIZE));
	}

	/**
	 * Create a new writer for the file located at the given path under <tt>generationRoot</tt> and appends it
	 * to the end of the stack.
	 * <p>
	 * &quot;file&quot; schemes are handled as absolute paths and will ignore the <tt>generationRoot</tt>.
	 * </p>
	 * 
	 * @param generatedFile
	 *            File that is to be created.
	 * @param fileBlock
	 *            The file block which asked for this context. Only used for generation events.
	 * @param source
	 *            The source EObject for this file block. Only used for generation events.
	 * @param appendMode
	 *            If <code>false</code>, the file will be replaced by a new one.
	 * @param charset
	 *            Charset of the target file.
	 * @throws AcceleoEvaluationException
	 *             Thrown if the file cannot be created.
	 */
	public void openNested(File generatedFile, Block fileBlock, EObject source, boolean appendMode,
			String charset) throws AcceleoEvaluationException {
		fireFilePathComputed(new AcceleoTextGenerationEvent(generatedFile.getPath(), fileBlock, source));
		try {
			if (!writers.isEmpty()) {
				writers.getLast().flush();
			}
			final Map<String, String> savedCodeBlocks = new HashMap<String, String>();
			if (generatedFile.exists()) {
				savedCodeBlocks.putAll(saveProtectedAreas(generatedFile));
			}
			// If the current preview contains overlapping blocks, give them priority
			if (generationPreview.containsKey(generatedFile.getPath())) {
				savedCodeBlocks.putAll(saveProtectedAreas(generationPreview.get(generatedFile.getPath())
						.toString()));
			}
			// We checked for JMerge tags when saving protected areas. we'll use this information here.
			final AbstractAcceleoWriter writer;
			if (charset != null) {
				writer = strategy.createWriterFor(generatedFile, (AbstractAcceleoWriter)generationPreview
						.get(generatedFile.getPath()), appendMode, hasJMergeTag, charset);
			} else {
				writer = strategy.createWriterFor(generatedFile, (AbstractAcceleoWriter)generationPreview
						.get(generatedFile.getPath()), appendMode, hasJMergeTag);
			}
			generationPreview.put(generatedFile.getPath(), writer);
			// reset the jmerge state for the following file blocks
			hasJMergeTag = false;
			userCodeBlocks.put(writer, savedCodeBlocks);
			writers.add(writer);
		} catch (final IOException e) {
			throw new AcceleoEvaluationException(AcceleoEngineMessages.getString(
					"AcceleoEvaluationContext.FileCreationError", generatedFile.getPath()), e); //$NON-NLS-1$
		}
	}

	/**
	 * Create a new writer directed at the given {@link OutputStream}. This is mainly used for fileBlocks with
	 * "stdout" URI.
	 * 
	 * @param stream
	 *            Stream to which writing will be directed.
	 */
	public void openNested(OutputStream stream) {
		try {
			if (!writers.isEmpty()) {
				writers.getLast().flush();
			}
		} catch (final IOException e) {
			throw new AcceleoEvaluationException(AcceleoEngineMessages
					.getString("AcceleoEvaluationContext.FlushError"), e); //$NON-NLS-1$
		}
		writers.add(new OutputStreamWriter(new AcceleoFilterOutputStream(stream)));
	}

	/**
	 * Create a new writer for the file located at the given path under <tt>generationRoot</tt> and appends it
	 * to the end of the stack.
	 * <p>
	 * &quot;file&quot; schemes are handled as absolute paths and will ignore the <tt>generationRoot</tt>.
	 * </p>
	 * 
	 * @param filePath
	 *            Path of the file around which we need a FileWriter. The file will be created under the
	 *            generationRoot if needed.
	 * @param fileBlock
	 *            The file block which asked for this context. Only used for generation events.
	 * @param source
	 *            The source EObject for this file block. Only used for generation events.
	 * @param appendMode
	 *            If <code>false</code>, the file will be replaced by a new one.
	 * @throws AcceleoEvaluationException
	 *             Thrown if the file cannot be created.
	 */
	public void openNested(String filePath, Block fileBlock, EObject source, boolean appendMode)
			throws AcceleoEvaluationException {
		openNested(getFileFor(filePath), fileBlock, source, appendMode, null);
	}

	/**
	 * Removes the last added expression from the expression stack trace.
	 */
	public void removeFromStack() {
		if (!expressionStack.isEmpty()) {
			expressionStack.removeLast();
		}
	}

	/**
	 * Notifies all listeners that a file has just been generated.
	 * 
	 * @param filePath
	 *            Path of the generated file.
	 * @param fileBlock
	 *            File block which generation just ended.
	 * @param source
	 *            The Object for which was generated this file.
	 */
	protected void fireFileGenerated(String filePath, Block fileBlock, EObject source) {
		AcceleoTextGenerationEvent event = new AcceleoTextGenerationEvent(filePath, fileBlock, source);
		for (IAcceleoTextGenerationListener listener : listeners) {
			listener.fileGenerated(event);
		}
	}

	/**
	 * Notifies all listeners that a file is going to be created.
	 * 
	 * @param event
	 *            The generation event that is to be sent to registered listeners.
	 */
	private void fireFilePathComputed(AcceleoTextGenerationEvent event) {
		for (IAcceleoTextGenerationListener listener : listeners) {
			listener.filePathComputed(event);
		}
	}

	/**
	 * Notifies all listeners that text has been generated.
	 * 
	 * @param event
	 *            The generation event that is to be sent to registered listeners.
	 */
	private void fireTextGenerated(AcceleoTextGenerationEvent event) {
		for (IAcceleoTextGenerationListener listener : listeners) {
			listener.textGenerated(event);
		}
	}

	/**
	 * This will return the list of protected areas the given file contains.
	 * 
	 * @param reader
	 *            Reader which content is to be searched through for protected areas.
	 * @return The list of saved protected areas.
	 * @throws IOException
	 *             Thrown if we cannot read through the provided reader.
	 */
	private Map<String, String> internalSaveProtectedAreas(LineReader reader) throws IOException {
		final Map<String, String> protectedAreas = new HashMap<String, String>();
		final String usercodeStart = AcceleoEngineMessages.getString("usercode.start"); //$NON-NLS-1$
		final String usercodeEnd = AcceleoEngineMessages.getString("usercode.end"); //$NON-NLS-1$
		String line = reader.readLine();
		while (line != null) {
			if (!hasJMergeTag && line.contains(JMERGE_TAG)) {
				hasJMergeTag = true;
			}
			if (line.contains(usercodeStart)) {
				final String marker = line.substring(line.indexOf(usercodeStart) + usercodeStart.length())
						.trim();
				final StringBuffer areaContent = new StringBuffer(DEFAULT_BUFFER_SIZE);
				final int start = line.indexOf(usercodeStart);
				// Everything preceding the start of user code doesn't need to be saved
				areaContent.append(line.substring(start));

				/*
				 * TODO If there is no "end of user code", or if the protected content is too large, this will
				 * fail in OutOfMemoryErrors. Could we use a temp File (java.nio?) instead of a StringBuffer?
				 */
				String lastEOF = reader.getLastEOLSequence();
				areaContent.append(lastEOF);

				line = reader.readLine();
				lastEOF = reader.getLastEOLSequence();
				while (line != null) {
					if (!hasJMergeTag && line.contains(JMERGE_TAG)) {
						hasJMergeTag = true;
					}
					// Everything following the end of user code marker doesn't need to be saved
					if (line.contains(usercodeEnd)) {
						final int endOffset = line.indexOf(usercodeEnd) + usercodeEnd.length();
						areaContent.append(line.substring(0, endOffset));
						break;
					}
					areaContent.append(line);
					areaContent.append(lastEOF);

					line = reader.readLine();
					lastEOF = reader.getLastEOLSequence();
				}
				protectedAreas.put(marker, areaContent.toString());
			}
			line = reader.readLine();
		}
		return protectedAreas;
	}

	/**
	 * This will return the list of protected areas the given file contains. <b>Note</b> that we will use this
	 * occasion to look for {@value #JMERGE_TAG} throughout the file.
	 * 
	 * @param file
	 *            File which protected areas are to be saved.
	 * @return The list of saved protected areas.
	 * @throws IOException
	 *             Thrown if we cannot read through <tt>file</tt>.
	 */
	private Map<String, String> saveProtectedAreas(File file) throws IOException {
		Map<String, String> protectedAreas = new HashMap<String, String>();
		LineReader reader = null;
		try {
			reader = new LineReader(new FileReader(file));
			protectedAreas = internalSaveProtectedAreas(reader);
		} catch (final FileNotFoundException e) {
			// cannot be thrown here, we were called after testing that the file indeed existed.
			AcceleoEnginePlugin.log(e, true);
		} finally {
			if (reader != null) {
				reader.close();
			}
		}
		return protectedAreas;
	}

	/**
	 * This will return the list of protected areas the given String contains. <b>Note</b> that we will use
	 * this occasion to look for {@value #JMERGE_TAG} throughout the file.
	 * 
	 * @param buffer
	 *            String (file content) which protected areas are to be saved.
	 * @return The list of saved protected areas.
	 */
	private Map<String, String> saveProtectedAreas(String buffer) {
		Map<String, String> protectedAreas = new HashMap<String, String>();
		LineReader reader = null;
		try {
			reader = new LineReader(new StringReader(buffer));
			protectedAreas = internalSaveProtectedAreas(reader);
		} catch (IOException e) {
			// Cannot happen here
			AcceleoEnginePlugin.log(e, true);
		} finally {
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					// This should never happen with a String Reader
					AcceleoEnginePlugin.log(e, true);
				}
			}
		}
		return protectedAreas;
	}

	/**
	 * This implementation of a FilterOutputStream will avoid closing the standard output if it is the
	 * underlying stream.
	 * 
	 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
	 */
	private final class AcceleoFilterOutputStream extends FilterOutputStream {
		/**
		 * Constructs an output stream redirecting all calls to the given {@link OutputStream}.
		 * 
		 * @param out
		 *            The decorated output stream.
		 */
		public AcceleoFilterOutputStream(OutputStream out) {
			super(out);
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see java.io.FilterOutputStream#close()
		 */
		@Override
		public void close() throws IOException {
			try {
				flush();
			} catch (IOException e) {
				// Ignored exception
			}
			if (out != System.out) {
				out.close();
			}
		}
	}

	/**
	 * This implementation of a Reader will allow us to read lines while still giving us access to the eol
	 * sequence.
	 * <p>
	 * Portions of this class have been copied from BufferedReader.
	 * </p>
	 * 
	 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
	 */
	public final class LineReader extends Reader {
		/** Size of our read buffer. */
		private static final int BUFFER_SIZE = 8192;

		/** Character buffer in which we'll read. */
		private char[] characterBuffer = new char[BUFFER_SIZE];

		/** Our underlying stream. */
		private Reader input;

		/** Number of chars in the local buffer. */
		private int nChars;

		/** Next character to read from the local buffer. */
		private int nextChar;

		/** Last EOL sequence encountered by {@link #readLine(boolean)}. */
		private String lastEOL = DOS_LINE_SEPARATOR;

		/**
		 * The gap until the next line.
		 */
		private int gap;

		/**
		 * Constructs our buffered reader given its underlying reader.
		 * 
		 * @param in
		 *            The reader from which to retrieve input.
		 */
		public LineReader(Reader in) {
			super(in);
			this.input = in;
			nChars = 0;
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see java.io.Reader#markSupported()
		 */
		@Override
		public boolean markSupported() {
			return false;
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see java.io.Reader#read()
		 */
		@Override
		public int read() throws IOException {
			synchronized(lock) {
				ensureOpen();
				if (nextChar >= nChars) {
					fill();
					if (nextChar >= nChars) {
						return -1;
					}
				}
				return characterBuffer[nextChar++];
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see java.io.Reader#close()
		 */
		@Override
		public void close() throws IOException {
			synchronized(lock) {
				if (input == null) {
					return;
				}
				input.close();
				input = null;
				characterBuffer = null;
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see java.io.Reader#read(char[], int, int)
		 */
		@Override
		public int read(char[] cbuf, int off, int len) throws IOException {
			synchronized(lock) {
				ensureOpen();
				if (off < 0 || len < 0 || (off + len) > cbuf.length || (off + len) < 0) {
					throw new IndexOutOfBoundsException();
				} else if (len == 0) {
					return 0;
				}

				int n = internalRead(cbuf, off, len);
				if (n > 0) {
					while (n < len && input.ready()) {
						int n1 = internalRead(cbuf, off + n, len - n);
						if (n1 <= 0) {
							break;
						}
						n += n1;
					}
				}
				return n;
			}
		}

		/**
		 * Reads a line of text. A line is considered to be terminated by either a line feed ('\n'), a
		 * carriage return ('\r') or a carriage return followed immediately by a line feed ("\r\n"). The line
		 * termination sequence will be omitted.
		 * 
		 * @return A string containing the content of the line, or <code>null</code> if the end of the stream
		 *         has been reached.
		 * @throws IOException
		 *             Thrown if the stream is closed or an I/O operation fails.
		 */
		public String readLine() throws IOException {
			StringBuilder lineBuffer = null;
			int startChar;

			String line = null;
			synchronized(lock) {
				ensureOpen();

				while (line == null) {
					int previousGap = gap;
					if (nextChar >= nChars) {
						fill();
					}
					if (nextChar >= nChars) {
						// Reached the end of the stream
						if (lineBuffer != null && lineBuffer.length() > 0) {
							line = lineBuffer.toString();
						}
						break;
					}
					boolean eol = false;
					char c = 0;
					int i;

					for (i = nextChar + gap; i < nChars; i++) {
						c = characterBuffer[i];
						if (c == '\n' || c == '\r') {
							eol = true;
							break;
						}
					}

					startChar = nextChar;
					nextChar = i;

					if (eol) {
						if (lineBuffer == null) {
							line = new String(characterBuffer, startChar, i - startChar);
						} else {
							lineBuffer.append(characterBuffer, startChar, i - startChar);
							line = lineBuffer.toString();
						}
						if (c == '\n') {
							lastEOL = "\n"; //$NON-NLS-1$
							nextChar++;
						} else if (c == '\r') {
							final int max = 8191;
							if (nextChar != max && characterBuffer.length >= nextChar
									&& characterBuffer[nextChar + 1] == '\n') {
								lastEOL = DOS_LINE_SEPARATOR;
								nextChar += 2;
								gap = 0;
							} else if (nextChar != max) {
								lastEOL = "\r"; //$NON-NLS-1$
								nextChar++;
								gap = 0;
							} else if (nextChar == max && DOS_LINE_SEPARATOR.equals(lastEOL)) {
								nextChar += 2;
								gap = 1;
							} else if (nextChar == max) {
								nextChar++;
								gap = 0;
							}
						}
					}

					if (lineBuffer == null) {
						lineBuffer = new StringBuilder();
					}
					lineBuffer
							.append(characterBuffer, startChar + previousGap, i - (startChar + previousGap));
				}
			}
			return line;
		}

		/**
		 * Returns the last EOL sequence encountered by {@link #readLine()}.
		 * 
		 * @return The last EOL sequence encountered by {@link #readLine()}. May be <code>null</code>.
		 */
		public String getLastEOLSequence() {
			return lastEOL;
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see java.io.Reader#ready()
		 */
		@Override
		public boolean ready() throws IOException {
			synchronized(lock) {
				ensureOpen();

				return nextChar < nChars || input.ready();
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see java.io.Reader#skip(long)
		 */
		@Override
		public long skip(long n) throws IOException {
			if (n < 0L) {
				throw new IllegalArgumentException(AcceleoEngineMessages
						.getString("AcceleoEvaluationContext.NegativeSkip")); //$NON-NLS-1$
			}
			synchronized(lock) {
				ensureOpen();
				long r = n;
				while (r > 0) {
					if (nextChar >= nChars) {
						fill();
					}
					if (nextChar >= nChars) {
						break;
					}
					long d = nChars - nextChar;
					if (r <= d) {
						nextChar += r;
						r = 0;
						break;
					}
					r -= d;
					nextChar = nChars;
				}
				return n - r;
			}
		}

		/**
		 * Reads characters into a portion of an array, reading from the underlying stream if necessary.
		 * 
		 * @param cbuf
		 *            The character buffer into which we are to read.
		 * @param off
		 *            Starting offset.
		 * @param len
		 *            Number of chars to read.
		 * @return The number of read characters.
		 * @throws IOException
		 *             Thrown if the stream is closed or an I/O operation fails.
		 * @see #read(char[], int, int)
		 */
		private int internalRead(char[] cbuf, int off, int len) throws IOException {
			if (nextChar >= nChars) {
				if (len >= characterBuffer.length) {
					return input.read(cbuf, off, len);
				}
				fill();
			}
			int readChars = -1;
			if (nextChar < nChars) {
				readChars = Math.min(len, nChars - nextChar);
				System.arraycopy(characterBuffer, nextChar, cbuf, off, readChars);
				nextChar += readChars;
			}
			return readChars;
		}

		/**
		 * Make sure that the underlying stream hasn't been closed.
		 * 
		 * @throws IOException
		 *             Thrown if the stream has been closed.
		 */
		private void ensureOpen() throws IOException {
			if (input == null) {
				throw new IOException(AcceleoEngineMessages
						.getString("AcceleoEvaluationContext.ClosedStream")); //$NON-NLS-1$
			}
		}

		/**
		 * Fills the input buffer, taking the mark into account if it is valid.
		 * 
		 * @throws IOException
		 *             Thrown if the stream is closed or an I/O operation fails.
		 */
		private void fill() throws IOException {
			int n;
			do {
				n = input.read(characterBuffer, 0, characterBuffer.length);
			} while (n == 0);

			if (n > 0) {
				nChars = n;
				nextChar = 0;
			}
		}
	}
}
