/*******************************************************************************
 * Copyright (c) 2011, 2015 Tasktop Technologies.
 * 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:
 *     David Green - initial API and implementation
 *******************************************************************************/

package org.eclipse.mylyn.wikitext.internal.parser.html;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.mylyn.wikitext.parser.DocumentBuilder;
import org.eclipse.mylyn.wikitext.parser.DocumentBuilder.BlockType;
import org.eclipse.mylyn.wikitext.parser.DocumentBuilder.SpanType;
import org.eclipse.mylyn.wikitext.parser.LinkAttributes;
import org.eclipse.mylyn.wikitext.parser.ListAttributes;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

import com.google.common.collect.ImmutableSet;

/**
 * A parser for (X)HTML that is based on SAX. Subclasses determine the source of SAX events.
 *
 * @author David Green
 */
public abstract class AbstractSaxHtmlParser {

	private static final Pattern HEADING_PATTERN = Pattern.compile("h([1-6])"); //$NON-NLS-1$

	/**
	 * element names for block elements
	 */
	private static Set<String> blockElements;

	/**
	 * element names for elements that cause adjacent whitespace to be collapsed
	 */
	private static Set<String> whitespaceCollapsingElements;

	private static Set<String> noCharacterContentElements;
	static {
		ImmutableSet.Builder<String> blockElementsBuilder = ImmutableSet.builder();
		blockElementsBuilder.add("div"); //$NON-NLS-1$
		blockElementsBuilder.add("dl"); //$NON-NLS-1$
		blockElementsBuilder.add("form"); //$NON-NLS-1$
		blockElementsBuilder.add("h1"); //$NON-NLS-1$
		blockElementsBuilder.add("h2"); //$NON-NLS-1$
		blockElementsBuilder.add("h3"); //$NON-NLS-1$
		blockElementsBuilder.add("h4"); //$NON-NLS-1$
		blockElementsBuilder.add("h5"); //$NON-NLS-1$
		blockElementsBuilder.add("h6"); //$NON-NLS-1$
		blockElementsBuilder.add("ol"); //$NON-NLS-1$
		blockElementsBuilder.add("p"); //$NON-NLS-1$
		blockElementsBuilder.add("pre"); //$NON-NLS-1$
		blockElementsBuilder.add("table"); //$NON-NLS-1$
		blockElementsBuilder.add("textarea"); //$NON-NLS-1$
		blockElementsBuilder.add("td"); //$NON-NLS-1$
		blockElementsBuilder.add("tr"); //$NON-NLS-1$
		blockElementsBuilder.add("ul"); //$NON-NLS-1$
		blockElementsBuilder.add("tbody"); //$NON-NLS-1$
		blockElementsBuilder.add("thead"); //$NON-NLS-1$
		blockElementsBuilder.add("tfoot"); //$NON-NLS-1$
		blockElementsBuilder.add("li"); //$NON-NLS-1$
		blockElementsBuilder.add("dd"); //$NON-NLS-1$
		blockElementsBuilder.add("dt"); //$NON-NLS-1$
		blockElementsBuilder.add("blockquote"); //$NON-NLS-1$
		blockElements = blockElementsBuilder.build();

		ImmutableSet.Builder<String> whitespaceCollapsingElementsBuilder = ImmutableSet.builder();
		whitespaceCollapsingElementsBuilder.add("br"); //$NON-NLS-1$
		whitespaceCollapsingElementsBuilder.add("hr"); //$NON-NLS-1$
		whitespaceCollapsingElements = whitespaceCollapsingElementsBuilder.build();

		ImmutableSet.Builder<String> noCharacterContentElementsBuilder = ImmutableSet.builder();
		noCharacterContentElementsBuilder.add("ul"); //$NON-NLS-1$
		noCharacterContentElementsBuilder.add("ol"); //$NON-NLS-1$
		noCharacterContentElementsBuilder.add("table"); //$NON-NLS-1$
		noCharacterContentElementsBuilder.add("tbody"); //$NON-NLS-1$
		noCharacterContentElementsBuilder.add("thead"); //$NON-NLS-1$
		noCharacterContentElementsBuilder.add("tr"); //$NON-NLS-1$
		noCharacterContentElements = noCharacterContentElementsBuilder.build();
	}

	private static final Map<String, SpanType> elementNameToSpanType = new HashMap<String, SpanType>();
	static {
		elementNameToSpanType.put("a", SpanType.LINK); //$NON-NLS-1$
		elementNameToSpanType.put("b", SpanType.BOLD); //$NON-NLS-1$
		elementNameToSpanType.put("cite", SpanType.CITATION); //$NON-NLS-1$
		elementNameToSpanType.put("i", SpanType.ITALIC); //$NON-NLS-1$
		elementNameToSpanType.put("em", SpanType.EMPHASIS); //$NON-NLS-1$
		elementNameToSpanType.put("strong", SpanType.STRONG); //$NON-NLS-1$
		elementNameToSpanType.put("del", SpanType.DELETED); //$NON-NLS-1$
		elementNameToSpanType.put("strike", SpanType.DELETED); //$NON-NLS-1$
		elementNameToSpanType.put("s", SpanType.DELETED); //$NON-NLS-1$
		elementNameToSpanType.put("ins", SpanType.INSERTED); //$NON-NLS-1$
		elementNameToSpanType.put("q", SpanType.QUOTE); //$NON-NLS-1$
		elementNameToSpanType.put("u", SpanType.UNDERLINED); //$NON-NLS-1$
		elementNameToSpanType.put("sup", SpanType.SUPERSCRIPT); //$NON-NLS-1$
		elementNameToSpanType.put("sub", SpanType.SUBSCRIPT); //$NON-NLS-1$
		elementNameToSpanType.put("span", SpanType.SPAN); //$NON-NLS-1$
		elementNameToSpanType.put("font", SpanType.SPAN); //$NON-NLS-1$
		elementNameToSpanType.put("code", SpanType.CODE); //$NON-NLS-1$
		elementNameToSpanType.put("tt", SpanType.MONOSPACE); //$NON-NLS-1$
		elementNameToSpanType.put("mark", SpanType.MARK); //$NON-NLS-1$
	}

	private static final Map<String, BlockType> elementNameToBlockType = new HashMap<String, DocumentBuilder.BlockType>();
	static {
		elementNameToBlockType.put("ul", BlockType.BULLETED_LIST); //$NON-NLS-1$
		elementNameToBlockType.put("code", BlockType.CODE); //$NON-NLS-1$
		elementNameToBlockType.put("div", BlockType.DIV); //$NON-NLS-1$
		elementNameToBlockType.put("footnote", BlockType.FOOTNOTE); //$NON-NLS-1$
		elementNameToBlockType.put("li", BlockType.LIST_ITEM); //$NON-NLS-1$
		elementNameToBlockType.put("ol", BlockType.NUMERIC_LIST); //$NON-NLS-1$
		elementNameToBlockType.put("dl", BlockType.DEFINITION_LIST); //$NON-NLS-1$
		elementNameToBlockType.put("dt", BlockType.DEFINITION_TERM); //$NON-NLS-1$
		elementNameToBlockType.put("dd", BlockType.DEFINITION_ITEM); //$NON-NLS-1$
		elementNameToBlockType.put("p", BlockType.PARAGRAPH); //$NON-NLS-1$
		elementNameToBlockType.put("pre", BlockType.PREFORMATTED); //$NON-NLS-1$
		elementNameToBlockType.put("blockquote", BlockType.QUOTE); //$NON-NLS-1$
		elementNameToBlockType.put("table", BlockType.TABLE); //$NON-NLS-1$
		elementNameToBlockType.put("th", BlockType.TABLE_CELL_HEADER); //$NON-NLS-1$
		elementNameToBlockType.put("td", BlockType.TABLE_CELL_NORMAL); //$NON-NLS-1$
		elementNameToBlockType.put("tr", BlockType.TABLE_ROW); //$NON-NLS-1$
	}

	private static final class ElementState {
		@SuppressWarnings("unused")
		final String elementName;

		final ElementState parent;

		final boolean preserveWhitespace;

		final boolean blockElement;

		final boolean noWhitespaceTextContainer;

		final boolean collapsesAdjacentWhitespace;

		final boolean canHaveCharacterContent;

		private ElementState(ElementState parent, String elementName) {
			this.parent = parent;
			this.elementName = elementName;
			blockElement = blockElements.contains(elementName);
			collapsesAdjacentWhitespace = blockElement || whitespaceCollapsingElements.contains(elementName);
			noWhitespaceTextContainer = "body".equals(elementName); //$NON-NLS-1$
			preserveWhitespace = (parent != null && parent.preserveWhitespace) || "pre".equals(elementName); //$NON-NLS-1$
			canHaveCharacterContent = !noCharacterContentElements.contains(elementName);
			if (parent != null) {
				parent.lastChild = this;
			}
		}

		int childCount = 0;

		int textChildCount = 0;

		/**
		 * The last child that was just processed for this element
		 */
		ElementState lastChild;

	}

	private class DocumentBuilderAdapter implements ContentHandler {

		private final Stack<ElementHandler> handlers = new Stack<ElementHandler>();

		private ElementState elementState;

		private final DocumentBuilder builder;

		private boolean processingContent;

		private final StringBuilder elementText = new StringBuilder();

		private final boolean asDocument;

		public DocumentBuilderAdapter(DocumentBuilder builder, boolean asDocument) {
			this.builder = builder;
			this.asDocument = asDocument;
		}

		public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
			final String lowerCaseName = localName.toLowerCase();
			if (processingContent) {
				emitText(elementState, lowerCaseName, false);
			}
			elementState = new ElementState(elementState, lowerCaseName);

			if (!processingContent) {
				if (lowerCaseName.equals("body")) { //$NON-NLS-1$
					processingContent = true;
				}
			}

			if (elementState.parent != null) {
				++elementState.parent.childCount;
			}

			ElementHandler handler = computeElementHandler(lowerCaseName);
			handlers.push(handler);
			handler.start(atts);
		}

		public void endElement(String uri, String localName, String qName) throws SAXException {
			emitText(elementState, null, true);

			final String lowerCaseName = localName.toLowerCase();
			elementState = elementState.parent;

			if (processingContent) {
				if (lowerCaseName.equals("body")) { //$NON-NLS-1$
					processingContent = false;
				}
			}
			if (!processingContent) {
				return;
			}
			ElementHandler handler = handlers.pop();
			handler.end();
		}

		private void emitText(ElementState elementState, String nextElementName, boolean elementClosing) {
			String text = elementText.toString();
			if (!elementState.canHaveCharacterContent) {
				text = text.trim();
			} else if (!elementState.preserveWhitespace) {
				if (elementClosing) {
					if (elementState.childCount == 0) {
						if (elementState.blockElement) {
							text = text.trim();
						}
					} else {
						if (elementState.blockElement) {
							text = trimRight(text);
						}
					}
				} else {
					// careful: this can result in losing significant whitespace
					String originalText = text;
					if (elementState.blockElement && elementState.childCount == 0) {
						text = trimLeft(text);
						if (text.length() == 0 && originalText.length() > 0) {
							text = originalText.substring(0, 1);
						}
					}
					if (nextElementName != null && blockElements.contains(nextElementName)) {
						text = trimRight(text);
					}
				}
			}

			elementText.delete(0, elementText.length());
			if (text.length() > 0) {
				handlers.peek().characters(text);
			}
		}

		public void characters(char[] ch, int start, int length) throws SAXException {
			if (processingContent) {
				if ((elementState.noWhitespaceTextContainer
						&& (elementState.lastChild == null || elementState.lastChild.blockElement))
						|| (elementState.blockElement && !elementState.preserveWhitespace
								&& elementState.textChildCount == 0 && elementState.childCount == 0)
						|| (elementState.lastChild != null && elementState.lastChild.collapsesAdjacentWhitespace)) {
					// trim left here
					int skip = 0;
					while (skip < length && Character.isWhitespace(ch[start + skip])) {
						++skip;
					}
					start += skip;
					length -= skip;
				}
				// receiving characters makes the last element child irrelevant
				elementState.lastChild = null;

				if (length != 0) {
					++elementState.textChildCount;
					append(elementState, ch, start, length);
				}
			}
		}

		private void append(ElementState elementState, char[] ch, int start, int length) {
			if (!elementState.preserveWhitespace) {
				// collapse adjacent whitespace, and replace newlines with a space character
				int previousWhitespaceIndex = Integer.MIN_VALUE;
				for (int x = 0; x < length; ++x) {
					int index = start + x;
					char c = ch[index];
					if (Character.isWhitespace(c)) {
						if (previousWhitespaceIndex == index - 1) {
							previousWhitespaceIndex = index;
							continue;
						}
						previousWhitespaceIndex = index;
						elementText.append(c == '\t' ? c : ' ');
					} else {
						elementText.append(c);
					}
				}
			} else {
				elementText.append(ch, start, length);
			}
		}

		public void setDocumentLocator(Locator locator) {
			// ignore
		}

		public void startDocument() throws SAXException {
			if (asDocument) {
				builder.beginDocument();
			}
		}

		public void endDocument() throws SAXException {
			if (asDocument) {
				builder.endDocument();
			} else {
				builder.flush();
			}
		}

		public void startPrefixMapping(String prefix, String uri) throws SAXException {
			// ignore
		}

		public void endPrefixMapping(String prefix) throws SAXException {
			// ignore
		}

		public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
			if (processingContent && elementState.preserveWhitespace) {
				characters(ch, start, length);
			}
		}

		public void processingInstruction(String target, String data) throws SAXException {
			// ignore
		}

		public void skippedEntity(String name) throws SAXException {
			// ignore
		}

		private abstract class ElementHandler {

			abstract void start(Attributes atts);

			abstract void end();

			void characters(String s) {
				builder.characters(s);
			}

		}

		private class BlockElementHandler extends ElementHandler {

			private final BlockType blockType;

			BlockElementHandler(BlockType blockType) {
				this.blockType = blockType;
			}

			@Override
			public void start(Attributes atts) {
				builder.beginBlock(blockType, computeAttributes(atts));
			}

			@Override
			public void end() {
				builder.endBlock();
			}

			@Override
			public void characters(String s) {
				builder.characters(s);
			}

		}

		private class NumericListElementHandler extends BlockElementHandler {

			NumericListElementHandler() {
				super(BlockType.NUMERIC_LIST);
			}

			@Override
			public void start(Attributes atts) {
				ListAttributes listAttributes = new ListAttributes();
				populateCommonAttributes(listAttributes, atts);
				listAttributes.setStart(getAttribute(atts, "start")); //$NON-NLS-1$
				if (listAttributes.getCssStyle() == null
						|| !listAttributes.getCssStyle().contains("list-style-type:")) {
					String typeAttribute = getAttribute(atts, "type");
					if (typeAttribute != null) {
						String listCssType = null;
						switch (typeAttribute) {
						case "1":
							listCssType = "decimal";
							break;
						case "a":
							listCssType = "lower-alpha";
							break;
						case "i":
							listCssType = "lower-roman";
							break;
						case "A":
							listCssType = "upper-alpha";
							break;
						case "I":
							listCssType = "upper-roman";
							break;
						}
						if (typeAttribute != null) {
							listAttributes.appendCssStyle("list-style-type: " + listCssType + ";");
						}
					}
				}
				builder.beginBlock(BlockType.NUMERIC_LIST, listAttributes);
			}
		}

		private class SpanElementHandler extends ElementHandler {

			private final SpanType spanType;

			private boolean noop;

			private SpanElementHandler(SpanType spanType) {
				this.spanType = spanType;
			}

			@Override
			public void start(Attributes atts) {
				org.eclipse.mylyn.wikitext.parser.Attributes attributes = computeAttributes(spanType, atts);
				if (spanType == SpanType.SPAN && attributes.getCssClass() == null && attributes.getCssStyle() == null
						&& attributes.getId() == null) {
					noop = true;
				} else {
					builder.beginSpan(spanType, attributes);
				}
			}

			@Override
			public void end() {
				if (!noop) {
					builder.endSpan();
				}
			}

		}

		private class FontElementHandler extends ElementHandler {

			private final SpanType spanType;

			private boolean noop;

			private FontElementHandler(SpanType spanType) {
				this.spanType = spanType;
			}

			@Override
			public void start(Attributes atts) {
				org.eclipse.mylyn.wikitext.parser.Attributes attributes = computeFontAttributes(atts);
				if (spanType == SpanType.SPAN && attributes.getCssClass() == null && attributes.getCssStyle() == null
						&& attributes.getId() == null) {
					noop = true;
				} else {
					builder.beginSpan(spanType, attributes);
				}
			}

			@Override
			public void end() {
				if (!noop) {
					builder.endSpan();
				}
			}

			private org.eclipse.mylyn.wikitext.parser.Attributes computeFontAttributes(Attributes atts) {
				org.eclipse.mylyn.wikitext.parser.Attributes attributes = computeAttributes(spanType, atts);
				for (int x = 0; x < atts.getLength(); ++x) {
					String localName = atts.getLocalName(x);
					if (localName.equals("face")) { //$NON-NLS-1$
						attributes.appendCssStyle("font-family: " + atts.getValue(x) + ";"); //$NON-NLS-1$ //$NON-NLS-2$
					} else if (localName.equals("size")) { //$NON-NLS-1$
						attributes.appendCssStyle("font-size: " + atts.getValue(x) + ";"); //$NON-NLS-1$ //$NON-NLS-2$
					}
				}
				return attributes;
			}
		}

		private class ContentElementHandler extends ElementHandler {

			@Override
			public void start(Attributes atts) {
				// ignore
			}

			@Override
			public void end() {
				// ignore
			}
		}

		private class HeadingElementHandler extends ElementHandler {

			int level;

			private HeadingElementHandler(int level) {
				this.level = level;
			}

			@Override
			void start(Attributes atts) {
				builder.beginHeading(level, computeAttributes(atts));
			}

			@Override
			void end() {
				builder.endHeading();
			}

		}

		private class ImageElementHandler extends ElementHandler {

			@Override
			public void start(Attributes atts) {
				org.eclipse.mylyn.wikitext.parser.Attributes attributes = computeAttributes(SpanType.SPAN, atts);
				builder.image(attributes, getValue("src", atts)); //$NON-NLS-1$
			}

			@Override
			public void end() {
				// nothing to do
			}

		}

		private class PreformattedBlockElementHandler extends ElementHandler {

			private Attributes atts;

			@Override
			void start(Attributes atts) {
				// delay start
				this.atts = new AttributesImpl(atts);
			}

			@Override
			void end() {
				if (atts == null) {
					builder.endBlock();
				}
			}

			@Override
			void characters(String s) {
				if (atts != null) {
					builder.beginBlock(BlockType.PREFORMATTED, computeAttributes(atts));
					atts = null;
				}
				super.characters(s);
			}

		}

		private class LineBreakHandler extends ElementHandler {

			@Override
			public void start(Attributes atts) {
				// ignore
			}

			@Override
			public void end() {
				builder.lineBreak();
			}
		}

		private class HorizontalRuleHandler extends ElementHandler {

			@Override
			public void start(Attributes atts) {
				// ignore
			}

			@Override
			public void end() {
				builder.horizontalRule();
			}
		}

		private ElementHandler computeElementHandler(String elementName) {

			BlockType blockType = elementNameToBlockType.get(elementName);
			if (blockType == null) {
				SpanType spanType = elementNameToSpanType.get(elementName);
				if (spanType != null) {
					if (elementName.equals("font")) { //$NON-NLS-1$
						return new FontElementHandler(spanType);
					}
					return new SpanElementHandler(spanType);
				}
				if (elementName.equals("img")) { //$NON-NLS-1$
					return new ImageElementHandler();
				}
				if (elementName.equals("br")) { //$NON-NLS-1$
					return new LineBreakHandler();
				}
				if (elementName.equals("hr")) { //$NON-NLS-1$
					return new HorizontalRuleHandler();
				}
				Matcher headingMatcher = HEADING_PATTERN.matcher(elementName);
				if (headingMatcher.matches()) {
					return new HeadingElementHandler(Integer.parseInt(headingMatcher.group(1)));
				}
				return new ContentElementHandler();
			}
			if (blockType == BlockType.CODE && !handlers.isEmpty()) {
				ElementHandler outerHandler = handlers.peek();
				if (!(outerHandler instanceof PreformattedBlockElementHandler)) {
					return new SpanElementHandler(SpanType.CODE);
				}
			}
			if (blockType == BlockType.PREFORMATTED) {
				return new PreformattedBlockElementHandler();
			}
			if (blockType == BlockType.NUMERIC_LIST) {
				return new NumericListElementHandler();
			}
			return new BlockElementHandler(blockType);
		}

	}

	private org.eclipse.mylyn.wikitext.parser.Attributes computeAttributes(SpanType spanType, Attributes atts) {
		org.eclipse.mylyn.wikitext.parser.Attributes attributes = spanType == SpanType.LINK
				? new LinkAttributes()
				: new org.eclipse.mylyn.wikitext.parser.Attributes();
		populateCommonAttributes(attributes, atts);
		if (spanType == SpanType.LINK) {
			String href = getValue("href", atts); //$NON-NLS-1$
			if (href != null) {
				((LinkAttributes) attributes).setHref(href);
			}
		}
		return attributes;
	}

	private String getValue(String name, Attributes atts) {
		for (int x = 0; x < atts.getLength(); ++x) {
			String localName = atts.getLocalName(x);
			if (localName.equals(name)) {
				return atts.getValue(x);
			}
		}
		return null;
	}

	private org.eclipse.mylyn.wikitext.parser.Attributes computeAttributes(Attributes atts) {
		org.eclipse.mylyn.wikitext.parser.Attributes attributes = new org.eclipse.mylyn.wikitext.parser.Attributes();
		populateCommonAttributes(attributes, atts);
		return attributes;
	}

	private String getAttribute(Attributes atts, String name) {
		for (int x = 0; x < atts.getLength(); ++x) {
			String localName = atts.getLocalName(x);
			if (name.equals(localName)) {
				return atts.getValue(x);
			}
		}
		return null;
	}

	private void populateCommonAttributes(org.eclipse.mylyn.wikitext.parser.Attributes attributes, Attributes atts) {
		for (int x = 0; x < atts.getLength(); ++x) {
			String localName = atts.getLocalName(x);
			if (localName.equals("id") || localName.equals("name")) { //$NON-NLS-1$ //$NON-NLS-2$
				attributes.setId(atts.getValue(x));
			} else if (localName.equals("style")) { //$NON-NLS-1$
				attributes.setCssStyle(atts.getValue(x));
			} else if (localName.equals("class")) { //$NON-NLS-1$
				attributes.setCssClass(atts.getValue(x));
			} else if (localName.equals("title")) { //$NON-NLS-1$
				attributes.setTitle(atts.getValue(x));
			} else if (localName.equals("color")) { //$NON-NLS-1$
				attributes.appendCssStyle("color: " + atts.getValue(x) + ";"); //$NON-NLS-1$ //$NON-NLS-2$
			}
		}
	}

	private static String trimRight(String text) {
		int len = text.length();

		while (0 < len && (text.charAt(len - 1) <= ' ')) {
			len--;
		}
		return len < text.length() ? text.substring(0, len) : text;
	}

	private static String trimLeft(String text) {
		final int len = text.length();
		int st = 0;

		while ((st < len) && (text.charAt(st) <= ' ')) {
			st++;
		}
		return st > 0 ? text.substring(st, len) : text;
	}

	protected abstract void parse(InputSource input, DocumentBuilder builder, ContentHandler contentHandler)
			throws IOException, SAXException;

	/**
	 * @param input
	 * @param builder
	 * @throws IOException
	 * @throws SAXException
	 */
	public void parse(InputSource input, DocumentBuilder builder, boolean asDocument) throws IOException, SAXException {
		parse(input, builder, createContentHandler(builder, asDocument));
	}

	protected ContentHandler createContentHandler(DocumentBuilder builder) {
		return createContentHandler(builder, true);
	}

	/**
	 *
	 */
	protected ContentHandler createContentHandler(DocumentBuilder builder, boolean asDocument) {
		return new DocumentBuilderAdapter(builder, asDocument);
	}

}
