/*******************************************************************************
 * Copyright (c) 2004, 2011 John-Mason P. Shackelford 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:
 *     John-Mason P. Shackelford - initial API and implementation
 * 	   IBM Corporation - bug fixes
 *******************************************************************************/

package org.eclipse.ant.internal.ui.editor.formatter;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

import org.eclipse.ant.internal.core.IAntCoreConstants;
import org.eclipse.ant.internal.ui.AntUIPlugin;
import org.eclipse.ant.internal.ui.preferences.AntEditorPreferenceConstants;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;

public class XmlDocumentFormatter {

	private static class CommentReader extends TagReader {

		private boolean complete = false;

		@Override
		protected void clear() {
			this.complete = false;
		}

		@Override
		public String getStartOfTag() {
			return "<!--"; //$NON-NLS-1$
		}

		@Override
		protected String readTag() throws IOException {
			int intChar;
			char c;
			StringBuffer node = new StringBuffer();

			while (!complete && (intChar = reader.read()) != -1) {
				c = (char) intChar;

				node.append(c);

				if (c == '>' && node.toString().endsWith("-->")) { //$NON-NLS-1$
					complete = true;
				}
			}
			return node.toString();
		}
	}

	private static class DoctypeDeclarationReader extends TagReader {

		private boolean complete = false;

		@Override
		protected void clear() {
			this.complete = false;
		}

		@Override
		public String getStartOfTag() {
			return "<!"; //$NON-NLS-1$
		}

		@Override
		protected String readTag() throws IOException {
			int intChar;
			char c;
			StringBuffer node = new StringBuffer();

			while (!complete && (intChar = reader.read()) != -1) {
				c = (char) intChar;

				node.append(c);

				if (c == '>') {
					complete = true;
				}
			}
			return node.toString();
		}

	}

	private static class ProcessingInstructionReader extends TagReader {

		private boolean complete = false;

		@Override
		protected void clear() {
			this.complete = false;
		}

		@Override
		public String getStartOfTag() {
			return "<?"; //$NON-NLS-1$
		}

		@Override
		protected String readTag() throws IOException {
			int intChar;
			char c;
			StringBuffer node = new StringBuffer();

			while (!complete && (intChar = reader.read()) != -1) {
				c = (char) intChar;

				node.append(c);

				if (c == '>' && node.toString().endsWith("?>")) { //$NON-NLS-1$
					complete = true;
				}
			}
			return node.toString();
		}
	}

	private static abstract class TagReader {

		protected Reader reader;

		private String tagText;

		protected abstract void clear();

		public int getPostTagDepthModifier() {
			return 0;
		}

		public int getPreTagDepthModifier() {
			return 0;
		}

		abstract public String getStartOfTag();

		public String getTagText() {
			return this.tagText;
		}

		public boolean isTextNode() {
			return false;
		}

		protected abstract String readTag() throws IOException;

		public boolean requiresInitialIndent() {
			return true;
		}

		public void setReader(Reader reader) throws IOException {
			this.reader = reader;
			this.clear();
			this.tagText = readTag();
		}

		public boolean startsOnNewline() {
			return true;
		}
	}

	private static class TagReaderFactory {

		// Warning: the order of the Array is important!
		private static TagReader[] tagReaders = new TagReader[] { new CommentReader(), new DoctypeDeclarationReader(),
				new ProcessingInstructionReader(), new XmlElementReader() };

		private static TagReader textNodeReader = new TextReader();

		public static TagReader createTagReaderFor(Reader reader) throws IOException {

			char[] buf = new char[10];
			reader.mark(10);
			reader.read(buf, 0, 10);
			reader.reset();

			String startOfTag = String.valueOf(buf);

			for (int i = 0; i < tagReaders.length; i++) {
				if (startOfTag.startsWith(tagReaders[i].getStartOfTag())) {
					tagReaders[i].setReader(reader);
					return tagReaders[i];
				}
			}
			// else
			textNodeReader.setReader(reader);
			return textNodeReader;
		}
	}

	private static class TextReader extends TagReader {

		private boolean complete;

		private boolean isTextNode;

		@Override
		protected void clear() {
			this.complete = false;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.ant.internal.ui.editor.formatter.XmlDocumentFormatter.TagReader#getStartOfTag()
		 */
		@Override
		public String getStartOfTag() {
			return IAntCoreConstants.EMPTY_STRING;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.ant.internal.ui.editor.formatter.XmlDocumentFormatter.TagReader#isTextNode()
		 */
		@Override
		public boolean isTextNode() {
			return this.isTextNode;
		}

		@Override
		protected String readTag() throws IOException {

			StringBuffer node = new StringBuffer();

			while (!complete) {

				reader.mark(1);
				int intChar = reader.read();
				if (intChar == -1)
					break;

				char c = (char) intChar;
				if (c == '<') {
					reader.reset();
					complete = true;
				} else {
					node.append(c);
				}
			}

			// if this text node is just whitespace
			// remove it, except for the newlines.
			if (node.length() < 1) {
				this.isTextNode = false;

			} else if (node.toString().trim().length() == 0) {
				String whitespace = node.toString();
				node = new StringBuffer();
				for (int i = 0; i < whitespace.length(); i++) {
					char whitespaceCharacter = whitespace.charAt(i);
					if (whitespaceCharacter == '\n' || whitespaceCharacter == '\r') {
						node.append(whitespaceCharacter);
					}
				}
				this.isTextNode = false;

			} else {
				this.isTextNode = true;
			}
			return node.toString();
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.ant.internal.ui.editor.formatter.XmlDocumentFormatter.TagReader#requiresInitialIndent()
		 */
		@Override
		public boolean requiresInitialIndent() {
			return false;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.ant.internal.ui.editor.formatter.XmlDocumentFormatter.TagReader#startsOnNewline()
		 */
		@Override
		public boolean startsOnNewline() {
			return false;
		}
	}

	private static class XmlElementReader extends TagReader {

		private boolean complete = false;

		@Override
		protected void clear() {
			this.complete = false;
		}

		@Override
		public int getPostTagDepthModifier() {
			if (getTagText().endsWith("/>") || getTagText().endsWith("/ >")) { //$NON-NLS-1$ //$NON-NLS-2$
				return 0;
			} else if (getTagText().startsWith("</")) { //$NON-NLS-1$
				return 0;
			} else {
				return +1;
			}
		}

		@Override
		public int getPreTagDepthModifier() {
			if (getTagText().startsWith("</")) { //$NON-NLS-1$
				return -1;
			}
			return 0;
		}

		@Override
		public String getStartOfTag() {
			return "<"; //$NON-NLS-1$
		}

		@Override
		protected String readTag() throws IOException {

			StringBuffer node = new StringBuffer();

			boolean insideQuote = false;
			int intChar;

			while (!complete && (intChar = reader.read()) != -1) {
				char c = (char) intChar;

				node.append(c);
				// TODO logic incorrectly assumes that " is quote character
				// when it could also be '
				if (c == '"') {
					insideQuote = !insideQuote;
				}
				if (c == '>' && !insideQuote) {
					complete = true;
				}
			}
			return node.toString();
		}
	}

	private int depth;
	private StringBuffer formattedXml;
	private boolean lastNodeWasText;
	private String fDefaultLineDelimiter;

	public XmlDocumentFormatter() {
		super();
		depth = -1;
	}

	private void copyNode(Reader reader, StringBuffer out, FormattingPreferences prefs) throws IOException {

		TagReader tag = TagReaderFactory.createTagReaderFor(reader);

		depth = depth + tag.getPreTagDepthModifier();

		if (!lastNodeWasText) {

			if (tag.startsOnNewline() && !hasNewlineAlready(out)) {
				out.append(fDefaultLineDelimiter);
			}

			if (tag.requiresInitialIndent()) {
				out.append(indent(prefs.getCanonicalIndent()));
			}
		}

		out.append(tag.getTagText());

		depth = depth + tag.getPostTagDepthModifier();

		lastNodeWasText = tag.isTextNode();

	}

	/**
	 * Returns the indent of the given string.
	 * 
	 * @param line
	 *            the text line
	 * @param tabWidth
	 *            the width of the '\t' character.
	 */
	public static int computeIndent(String line, int tabWidth) {
		int result = 0;
		int blanks = 0;
		int size = line.length();
		for (int i = 0; i < size; i++) {
			char c = line.charAt(i);
			if (c == '\t') {
				result++;
				blanks = 0;
			} else if (isIndentChar(c)) {
				blanks++;
				if (blanks == tabWidth) {
					result++;
					blanks = 0;
				}
			} else {
				return result;
			}
		}
		return result;
	}

	/**
	 * Indent char is a space char but not a line delimiters. <code>== Character.isWhitespace(ch) && ch != '\n' && ch != '\r'</code>
	 */
	public static boolean isIndentChar(char ch) {
		return Character.isWhitespace(ch) && !isLineDelimiterChar(ch);
	}

	/**
	 * Line delimiter chars are '\n' and '\r'.
	 */
	public static boolean isLineDelimiterChar(char ch) {
		return ch == '\n' || ch == '\r';
	}

	public String format(String documentText, FormattingPreferences prefs) {

		Assert.isNotNull(documentText);
		Assert.isNotNull(prefs);

		Reader reader = new StringReader(documentText);
		formattedXml = new StringBuffer();

		if (depth == -1) {
			depth = 0;
		}
		lastNodeWasText = false;
		try {
			while (true) {
				reader.mark(1);
				int intChar = reader.read();
				reader.reset();

				if (intChar != -1) {
					copyNode(reader, formattedXml, prefs);
				} else {
					break;
				}
			}
			reader.close();
		}
		catch (IOException e) {
			AntUIPlugin.log(e);
		}
		return formattedXml.toString();
	}

	private boolean hasNewlineAlready(StringBuffer out) {
		return out.lastIndexOf("\n") == formattedXml.length() - 1 //$NON-NLS-1$
				|| out.lastIndexOf("\r") == formattedXml.length() - 1; //$NON-NLS-1$
	}

	private String indent(String canonicalIndent) {
		StringBuffer indent = new StringBuffer(30);
		for (int i = 0; i < depth; i++) {
			indent.append(canonicalIndent);
		}
		return indent.toString();
	}

	public void setInitialIndent(int indent) {
		depth = indent;
	}

	/**
	 * Returns the indentation of the line at <code>offset</code> as a <code>StringBuffer</code>. If the offset is not valid, the empty string is
	 * returned.
	 * 
	 * @param offset
	 *            the offset in the document
	 * @return the indentation (leading whitespace) of the line in which <code>offset</code> is located
	 */
	public static StringBuffer getLeadingWhitespace(int offset, IDocument document) {
		StringBuffer indent = new StringBuffer();
		try {
			IRegion line = document.getLineInformationOfOffset(offset);
			int lineOffset = line.getOffset();
			int nonWS = findEndOfWhiteSpace(document, lineOffset, lineOffset + line.getLength());
			indent.append(document.get(lineOffset, nonWS - lineOffset));
			return indent;
		}
		catch (BadLocationException e) {
			return indent;
		}
	}

	/**
	 * Returns the first offset greater than <code>offset</code> and smaller than <code>end</code> whose character is not a space or tab character. If
	 * no such offset is found, <code>end</code> is returned.
	 * 
	 * @param document
	 *            the document to search in
	 * @param offset
	 *            the offset at which searching start
	 * @param end
	 *            the offset at which searching stops
	 * @return the offset in the specifed range whose character is not a space or tab
	 * @exception BadLocationException
	 *                if position is an invalid range in the given document
	 */
	public static int findEndOfWhiteSpace(IDocument document, int offset, int end) throws BadLocationException {
		while (offset < end) {
			char c = document.getChar(offset);
			if (c != ' ' && c != '\t') {
				return offset;
			}
			offset++;
		}
		return end;
	}

	/**
	 * Creates a string that represents one indent (can be spaces or tabs..)
	 * 
	 * @return one indentation
	 */
	public static StringBuffer createIndent() {
		StringBuffer oneIndent = new StringBuffer();
		IPreferenceStore pluginPrefs = AntUIPlugin.getDefault().getPreferenceStore();
		pluginPrefs.getBoolean(AntEditorPreferenceConstants.FORMATTER_TAB_CHAR);

		if (!pluginPrefs.getBoolean(AntEditorPreferenceConstants.FORMATTER_TAB_CHAR)) {
			int tabLen = pluginPrefs.getInt(AntEditorPreferenceConstants.FORMATTER_TAB_SIZE);
			for (int i = 0; i < tabLen; i++) {
				oneIndent.append(' ');
			}
		} else {
			oneIndent.append('\t'); // default
		}

		return oneIndent;
	}

	public void setDefaultLineDelimiter(String defaultLineDelimiter) {
		fDefaultLineDelimiter = defaultLineDelimiter;

	}
}