/*******************************************************************************
 * 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;
			StringBuilder node = new StringBuilder();

			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;
			StringBuilder node = new StringBuilder();

			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;
			StringBuilder node = new StringBuilder();

			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 {

			StringBuilder node = new StringBuilder();

			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'}
	 */
	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) {
		StringBuilder indent = new StringBuilder(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;

	}
}