/*******************************************************************************
 * Copyright (c) 2004, 2011 John-Mason P. Shackelford and others.
 *
 * This program and the accompanying materials 
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 * 
 * 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;

	}
}