/*******************************************************************************
 * Copyright (c) 2008, 2016 xored software, Inc. and others.
 *
 * 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:
 *     xored software, Inc. - initial API and Implementation (Alex Panchenko)
 *******************************************************************************/
package org.eclipse.dltk.formatter;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.dltk.formatter.internal.ExcludeRegionList;
import org.eclipse.dltk.utils.TextUtils;
import org.eclipse.jface.text.IRegion;

public class FormatterWriter implements IFormatterWriter {

	private final StringBuilder writer = new StringBuilder();
	private final StringBuilder indent = new StringBuilder();
	private final StringBuilder trimmedSpaces = new StringBuilder();
	/**
	 * @since 2.0
	 */
	protected final StringBuilder callbackBuffer = new StringBuilder();
	private final StringBuilder emptyLines = new StringBuilder();

	private boolean lineStarted = false;
	private char lastChar = 0;
	private int lineNumber = 0;
	private final List<IFormatterCallback> newLineCallbacks = new ArrayList<IFormatterCallback>();

	private final String lineDelimiter;
	private final IFormatterDocument document;
	private final IFormatterIndentGenerator indentGenerator;
	private int linesPreserve = -1;
	private int wrapLength = -1;
	private boolean preserveSpaces = true;
	private boolean skipNextNewLine = false;
	private boolean canAppendToPreviousLine = false;
	private boolean trimTrailingSpaces = true;
	private boolean trimBlankLines = true;
	private boolean keepLines = false;

	/**
	 * @param lineDelimiter
	 * @since 2.0
	 */
	public FormatterWriter(IFormatterDocument document, String lineDelimiter,
			IFormatterIndentGenerator indentGenerator) {
		this.document = document;
		this.lineDelimiter = lineDelimiter;
		this.indentGenerator = indentGenerator;
	}

	@Override
	public void ensureLineStarted(IFormatterContext context) {
		if (!lineStarted) {
			startLine(context);
		}
	}

	@Override
	public void write(IFormatterContext context, int startOffset, int endOffset) {
		if (!excludes.isExcluded(startOffset, endOffset)) {
			if (endOffset > startOffset) {
				write(context, document.get(startOffset, endOffset));
			}
		} else {
			final IRegion[] regions = excludes.selectValidRanges(startOffset,
					endOffset);
			for (int i = 0; i < regions.length; ++i) {
				write(context, document.get(regions[i]));
			}
		}
	}

	@Override
	public void writeText(IFormatterContext context, String text) {
		if (text.length() != 0) {
			skipNextNewLine = false;
		}
		if (lineStarted) {
			trimTrailingSpaces(false);
		}
		write(context, text);
	}

	private void trimTrailingSpaces(boolean keepTrimmed) {
		int length = writer.length();
		while (length > 0 && FormatterUtils.isSpace(writer.charAt(length - 1))) {
			--length;
		}
		if (keepTrimmed) {
			trimmedSpaces.append(writer, length, writer.length());
		}
		if (length < writer.length()) {
			writer.setLength(length);
		}
	}

	@Override
	public void writeLineBreak(IFormatterContext context) {
		if (lineStarted && !keepLines) {
			write(context, lineDelimiter);
			assert (!lineStarted);
			skipNextNewLine = true;
		}
	}

	@Override
	public void skipNextLineBreaks(IFormatterContext context) {
		skipNextLineBreaks(context, true);
	}

	@Override
	public void skipNextLineBreaks(IFormatterContext context, boolean value) {
		if (!keepLines) {
			skipNextNewLine = value;
		}
	}

	@Override
	public void appendToPreviousLine(IFormatterContext context, String text) {
		if (!lineStarted && canAppendToPreviousLine) {
			skipNextNewLine = false;
			emptyLines.setLength(0);
			indent.setLength(0);
			int len = writer.length();
			if (len > 0) {
				if (writer.charAt(len - 1) == '\n') {
					--len;
					if (len > 0 && writer.charAt(len - 1) == '\r') {
						--len;
					}
				} else if (writer.charAt(len - 1) == '\r') {
					--len;
				}
				writer.setLength(len);
				if (text.length() == 0) {
					writer.append(trimmedSpaces);
					trimmedSpaces.setLength(0);
				} else {
					writer.append(text);
				}
				lineStarted = true;
			}
		}
	}

	@Override
	public void disableAppendToPreviousLine() {
		canAppendToPreviousLine = false;
	}

	protected void write(IFormatterContext context, String text) {
		if (!context.isWrapping()) {
			for (int i = 0; i < text.length(); ++i) {
				write(context, text.charAt(i));
			}
		} else {
			int offset;
			int start = findLineStart();
			if (lineStarted) {
				offset = calculateOffset(start);
			} else {
				offset = 0;
			}
			int savedLineNumber = lineNumber;
			for (int i = 0; i < text.length(); ++i) {
				final char ch = text.charAt(i);
				if (lineStarted && !FormatterUtils.isSpace(ch)
						&& !FormatterUtils.isLineSeparator(ch)) {
					if (savedLineNumber != lineNumber) {
						start = findLineStart();
						offset = calculateOffset(start);
						savedLineNumber = lineNumber;
					}
					if (wrapLength > 0 && offset > wrapLength) {
						int begin = start;
						while (begin < writer.length()
								&& FormatterUtils.isSpace(writer.charAt(begin))) {
							++begin;
						}
						if (begin < writer.length()
								&& writer.charAt(begin) == '#') {
							++begin;
						}
						while (begin < writer.length()
								&& FormatterUtils.isSpace(writer.charAt(begin))) {
							++begin;
						}
						int wordBegin = writer.length();
						while (wordBegin > begin
								&& !FormatterUtils.isSpace(writer
										.charAt(wordBegin - 1))) {
							--wordBegin;
						}
						int prevWordEnd = wordBegin;
						while (prevWordEnd > begin
								&& FormatterUtils.isSpace(writer
										.charAt(prevWordEnd - 1))) {
							--prevWordEnd;
						}
						if (prevWordEnd > begin) {
							writer.replace(prevWordEnd, wordBegin,
									lineDelimiter + "# "); //$NON-NLS-1$
							start = prevWordEnd + lineDelimiter.length();
							offset = calculateOffset(start);
						}
					}
				}
				write(context, ch);
				++offset;
			}
		}
	}

	private int calculateOffset(int pos) {
		int offset = 0;
		while (pos < writer.length()) {
			char ch = writer.charAt(pos++);
			if (ch == '\t') {
				final int tabSize = indentGenerator.getTabSize();
				offset = (offset + tabSize - 1) / tabSize * tabSize;
			} else {
				++offset;
			}
		}
		return offset;
	}

	private int findLineStart() {
		int pos = writer.length();
		while (pos > 0
				&& !FormatterUtils.isLineSeparator(writer.charAt(pos - 1))) {
			--pos;
		}
		return pos;
	}

	/**
	 * @param context
	 * @param charAt
	 */
	protected void write(IFormatterContext context, char ch) {
		if (ch == '\n' || ch == '\r') {
			if (lineStarted) {
				trimmedSpaces.setLength(0);
				if (trimTrailingSpaces) {
					trimTrailingSpaces(true);
				}
				writer.append(ch);
				lineStarted = false;
				if (!newLineCallbacks.isEmpty()) {
					executeNewLineCallbacks(context);
					assert newLineCallbacks.isEmpty();
				}
			} else if (ch == '\n' && lastChar == '\r') {
				if (emptyLines.length() == 0) {
					writer.append(ch); // windows EOL = "\r\n"
				} else {
					emptyLines.append(ch);
				}
			} else {
				if (!trimBlankLines) {
					emptyLines.append(indent);
				}
				indent.setLength(0);
				emptyLines.append(ch);
			}
		} else if (!lineStarted) {
			if (Character.isWhitespace(ch)) {
				indent.append(ch);
			} else {
				startLine(context);
				writer.append(ch);
			}
		} else {
			if (!preserveSpaces && context.isIndenting()
					&& !context.isComment() && FormatterUtils.isSpace(ch)) {
				if (writer.charAt(writer.length() - 1) != ' ') {
					writer.append(' ');
				}
			} else {
				writer.append(ch);
			}
		}
		lastChar = ch;
	}

	private void executeNewLineCallbacks(IFormatterContext context) {
		final IFormatterRawWriter callbackWriter = new IFormatterRawWriter() {

			@Override
			public void writeIndent(IFormatterContext context) {
				FormatterWriter.this.writeIndent(context, callbackBuffer);
			}

			@Override
			public void writeText(IFormatterContext context, String text) {
				callbackBuffer.append(text);
			}

		};
		IFormatterCallback[] copy = newLineCallbacks
				.toArray(new IFormatterCallback[newLineCallbacks.size()]);
		newLineCallbacks.clear();
		for (IFormatterCallback callback : copy) {
			callback.call(context, callbackWriter);
		}
	}

	private void startLine(IFormatterContext context) {
		if (callbackBuffer.length() != 0) {
			writer.append(callbackBuffer);
			callbackBuffer.setLength(0);
		}
		if (context.getBlankLines() >= 0) {
			if (writer.length() != 0) {
				for (int i = 0; i < context.getBlankLines(); ++i) {
					writer.append(lineDelimiter);
				}
			}
			context.resetBlankLines();
		} else if (emptyLines.length() != 0) {
			writeEmptyLines();
		}
		skipNextNewLine = false;
		emptyLines.setLength(0);
		if (context.isIndenting()) {
			writeIndent(context);
		} else {
			writer.append(indent);
		}
		indent.setLength(0);
		lineStarted = true;
		++lineNumber;
		canAppendToPreviousLine = true;
	}

	private void writeEmptyLines() {
		if (skipNextNewLine) {
			int i = 0;
			if (emptyLines.charAt(i) == '\r') {
				++i;
				if (i < emptyLines.length() && emptyLines.charAt(i) == '\n') {
					++i;
				}
			} else if (emptyLines.charAt(i) == '\n') {
				++i;
			}
			if (i > 0) {
				emptyLines.delete(0, i);
			}
		}
		if (linesPreserve >= 0 && linesPreserve < Integer.MAX_VALUE
				&& TextUtils.countLines(emptyLines) > linesPreserve) {
			writer.append(TextUtils.selectHeadLines(emptyLines, linesPreserve));
		} else {
			writer.append(emptyLines);
		}
	}

	/**
	 * @param context
	 */
	protected void writeIndent(IFormatterContext context) {
		writeIndent(context, writer);
	}

	/**
	 * @since 2.0
	 */
	protected void writeIndent(IFormatterContext context, StringBuilder buffer) {
		indentGenerator.generateIndent(context.getIndent(), buffer);
	}

	public String getOutput() {
		return writer.toString();
	}

	private final ExcludeRegionList excludes = new ExcludeRegionList();

	@Override
	public void excludeRegion(IRegion region) {
		excludes.excludeRegion(region);
	}

	@Override
	public void addNewLineCallback(IFormatterCallback callback) {
		newLineCallbacks.add(callback);
	}

	public void flush(IFormatterContext context) {
		if (!newLineCallbacks.isEmpty()) {
			if (lineStarted) {
				writer.append(lineDelimiter);
				lineStarted = false;
			}
			executeNewLineCallbacks(context);
			assert newLineCallbacks.isEmpty();
		}
		if (callbackBuffer.length() != 0) {
			writer.append(callbackBuffer);
			callbackBuffer.setLength(0);
		}
		if (emptyLines.length() != 0) {
			writeEmptyLines();
			emptyLines.setLength(0);
		}
	}

	/**
	 * @since 2.0
	 */
	public int getLinesPreserve() {
		return linesPreserve;
	}

	/**
	 * @param value
	 */
	public void setLinesPreserve(int value) {
		this.linesPreserve = value;
	}

	/**
	 * @return the wrapLength
	 */
	public int getWrapLength() {
		return wrapLength;
	}

	/**
	 * @param wrapLength
	 *            the wrapLength to set
	 */
	public void setWrapLength(int wrapLength) {
		this.wrapLength = wrapLength;
	}

	public boolean isPreserveSpaces() {
		return preserveSpaces;
	}

	public void setPreserveSpaces(boolean preserveSpaces) {
		this.preserveSpaces = preserveSpaces;
	}

	/**
	 * @since 2.0
	 */
	public boolean isTrimTrailingSpaces() {
		return trimTrailingSpaces;
	}

	/**
	 * @since 2.0
	 */
	public void setTrimTrailingSpaces(boolean trimTrailingSpaces) {
		this.trimTrailingSpaces = trimTrailingSpaces;
	}

	/**
	 * @since 2.0
	 */
	public boolean isTrimEmptyLines() {
		return trimBlankLines;
	}

	/**
	 * @since 2.0
	 */
	public void setTrimEmptyLines(boolean trimEmptyLines) {
		this.trimBlankLines = trimEmptyLines;
	}

	/**
	 * @param keepLines
	 *            the keepLines to set
	 * @since 2.0
	 */
	public void setKeepLines(boolean keepLines) {
		this.keepLines = keepLines;
	}

	/**
	 * @return the keepLines
	 * @since 2.0
	 */
	public boolean isKeepLines() {
		return keepLines;
	}

}
