/*******************************************************************************
 * Copyright (c) 2000, 2013 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *     Manuel Doninger - fixes for bug 360365
 *******************************************************************************/
package org.eclipse.mylyn.commons.core;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.mylyn.internal.commons.core.ICommonsCoreConstants;
import org.eclipse.mylyn.internal.commons.core.Messages;
import org.w3c.dom.Attr;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

/**
 * This class represents the default implementation of the <code>XMLMemento</code> interface.
 * <p>
 * This class is not intended to be extended by clients.
 * </p>
 * 
 * @see XmlMemento
 * @author Manuel Doninger
 * @since 3.7
 */
public final class XmlMemento {

	private final Document factory;

	private final Element element;

	private static final String TAG_ID = "XmlMemento.internal.id"; //$NON-NLS-1$

	/**
	 * Creates a <code>Document</code> from the <code>Reader</code> and returns a memento on the first
	 * <code>Element</code> for reading the document.
	 * <p>
	 * Same as calling createReadRoot(reader, null)
	 * </p>
	 * 
	 * @param reader
	 *            the <code>Reader</code> used to create the memento's document
	 * @return a memento on the first <code>Element</code> for reading the document
	 * @throws InvocationTargetException
	 *             if IO problems, invalid format, or no element.
	 */
	public static XmlMemento createReadRoot(Reader reader) throws InvocationTargetException {
		return createReadRoot(reader, null);
	}

	/**
	 * Creates a <code>Document</code> from the <code>Reader</code> and returns a memento on the first
	 * <code>Element</code> for reading the document.
	 * 
	 * @param reader
	 *            the <code>Reader</code> used to create the memento's document
	 * @param baseDir
	 *            the directory used to resolve relative file names in the XML document. This directory must exist and
	 *            include the trailing separator. The directory format, including the separators, must be valid for the
	 *            platform. Can be <code>null</code> if not needed.
	 * @return a memento on the first <code>Element</code> for reading the document
	 * @throws InvocationTargetException
	 *             if IO problems, invalid format, or no element.
	 */
	public static XmlMemento createReadRoot(Reader reader, String baseDir) throws InvocationTargetException {
		String errorMessage = null;
		Exception exception = null;

		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder parser = factory.newDocumentBuilder();
			InputSource source = new InputSource(reader);
			if (baseDir != null) {
				source.setSystemId(baseDir);
			}

			parser.setErrorHandler(new ErrorHandler() {
				/**
				 * @throws SAXException
				 */
				public void warning(SAXParseException exception) throws SAXException {
					// ignore
				}

				/**
				 * @throws SAXException
				 */
				public void error(SAXParseException exception) throws SAXException {
					// ignore
				}

				public void fatalError(SAXParseException exception) throws SAXException {
					throw exception;
				}
			});

			Document document = parser.parse(source);
			NodeList list = document.getChildNodes();
			for (int i = 0; i < list.getLength(); i++) {
				Node node = list.item(i);
				if (node instanceof Element) {
					return new XmlMemento(document, (Element) node);
				}
			}
		} catch (ParserConfigurationException e) {
			exception = e;
			errorMessage = Messages.XMLMemento_parserConfigError;
		} catch (IOException e) {
			exception = e;
			errorMessage = Messages.XMLMemento_ioError;
		} catch (SAXException e) {
			exception = e;
			errorMessage = Messages.XMLMemento_formatError;
		}

		String problemText = null;
		if (exception != null) {
			problemText = exception.getMessage();
		}
		if (problemText == null || problemText.length() == 0) {
			problemText = errorMessage != null ? errorMessage : Messages.XMLMemento_noElement;
		}
		throw new InvocationTargetException(exception, errorMessage);
	}

	/**
	 * Returns a root memento for writing a document.
	 * 
	 * @param type
	 *            the element node type to create on the document
	 * @return the root memento for writing a document
	 * @throws DOMException
	 */
	public static XmlMemento createWriteRoot(String type) throws DOMException {
		Document document;
		try {
			document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
			Element element = document.createElement(type);
			document.appendChild(element);
			return new XmlMemento(document, element);
		} catch (ParserConfigurationException e) {
//            throw new Error(e);
			throw new Error(e.getMessage());
		}
	}

	/**
	 * Creates a memento for the specified document and element.
	 * <p>
	 * Clients should use <code>createReadRoot</code> and <code>createWriteRoot</code> to create the initial memento on
	 * a document.
	 * </p>
	 * 
	 * @param document
	 *            the document for the memento
	 * @param element
	 *            the element node for the memento
	 */
	public XmlMemento(Document document, Element element) {
		super();
		this.factory = document;
		this.element = element;
	}

	/**
	 * Creates a new child of this memento with the given type.
	 * <p>
	 * The <code>getChild</code> and <code>getChildren</code> methods are used to retrieve children of a given type.
	 * </p>
	 * 
	 * @param type
	 *            the type
	 * @return a new child memento
	 * @see #getChild
	 * @see #getChildren
	 * @throws DOMException
	 *             if the child cannot be created
	 */
	public XmlMemento createChild(String type) throws DOMException {
		Element child = factory.createElement(type);
		element.appendChild(child);
		return new XmlMemento(factory, child);
	}

	/**
	 * Creates a new child of this memento with the given type and id. The id is stored in the child memento (using a
	 * special reserved key, <code>TAG_ID</code>) and can be retrieved using <code>getId</code>.
	 * <p>
	 * The <code>getChild</code> and <code>getChildren</code> methods are used to retrieve children of a given type.
	 * </p>
	 * 
	 * @param type
	 *            the type
	 * @param id
	 *            the child id
	 * @return a new child memento with the given type and id
	 * @see #getID
	 * @throws DOMException
	 *             if the child cannot be created
	 */
	public XmlMemento createChild(String type, String id) throws DOMException {
		Element child = factory.createElement(type);
		child.setAttribute(TAG_ID, id == null ? "" : id); //$NON-NLS-1$
		element.appendChild(child);
		return new XmlMemento(factory, child);
	}

	/**
	 * Create a copy of the child node and append it to this node.
	 * 
	 * @param child
	 * @return An IMenento for the new child node.
	 * @throws DOMException
	 *             if the child cannot be created
	 */
	public XmlMemento copyChild(XmlMemento child) throws DOMException {
		Element childElement = child.element;
		Element newElement = (Element) factory.importNode(childElement, true);
		element.appendChild(newElement);
		return new XmlMemento(factory, newElement);
	}

	/* (non-Javadoc)
	 * Method declared in XMLMemento.
	 */
	public XmlMemento getChild(String type) {

		// Get the nodes.
		NodeList nodes = element.getChildNodes();
		int size = nodes.getLength();
		if (size == 0) {
			return null;
		}

		// Find the first node which is a child of this node.
		for (int nX = 0; nX < size; nX++) {
			Node node = nodes.item(nX);
			if (node instanceof Element) {
				Element element = (Element) node;
				if (element.getNodeName().equals(type)) {
					return new XmlMemento(factory, element);
				}
			}
		}

		// A child was not found.
		return null;
	}

	/* (non-Javadoc)
	 * Method declared in XMLMemento.
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public XmlMemento[] getChildren(String type) {

		// Get the nodes.
		NodeList nodes = element.getChildNodes();
		int size = nodes.getLength();
		if (size == 0) {
			return new XmlMemento[0];
		}

		// Extract each node with given type.
		ArrayList list = new ArrayList(size);
		for (int nX = 0; nX < size; nX++) {
			Node node = nodes.item(nX);
			if (node instanceof Element) {
				Element element = (Element) node;
				if (element.getNodeName().equals(type)) {
					list.add(element);
				}
			}
		}

		// Create a memento for each node.
		size = list.size();
		XmlMemento[] results = new XmlMemento[size];
		for (int x = 0; x < size; x++) {
			results[x] = new XmlMemento(factory, (Element) list.get(x));
		}
		return results;
	}

	/* (non-Javadoc)
	 * Method declared in XMLMemento.
	 */
	public Float getFloat(String key) {
		Attr attr = element.getAttributeNode(key);
		if (attr == null) {
			return null;
		}
		String strValue = attr.getValue();
		try {
			return new Float(strValue);
		} catch (NumberFormatException e) {
			StatusHandler.log(new Status(IStatus.ERROR, ICommonsCoreConstants.ID_PLUGIN,
					"Memento problem - Invalid float for key: " //$NON-NLS-1$
							+ key + " value: " + strValue, e)); //$NON-NLS-1$
			return null;
		}
	}

	/**
	 * @since 3.4
	 */
	public String getType() {
		return element.getNodeName();
	}

	/* (non-Javadoc)
	 * Method declared in XMLMemento.
	 */
	public String getID() {
		return element.getAttribute(TAG_ID);
	}

	/* (non-Javadoc)
	 * Method declared in XMLMemento.
	 */
	public Integer getInteger(String key) {
		Attr attr = element.getAttributeNode(key);
		if (attr == null) {
			return null;
		}
		String strValue = attr.getValue();
		try {
			return Integer.valueOf(strValue);
		} catch (NumberFormatException e) {
			StatusHandler.log(new Status(IStatus.ERROR, ICommonsCoreConstants.ID_PLUGIN,
					"Memento problem - invalid integer for key: " + key //$NON-NLS-1$
							+ " value: " + strValue, e)); //$NON-NLS-1$
			return null;
		}
	}

	/* (non-Javadoc)
	 * Method declared in XMLMemento.
	 */
	public String getString(String key) {
		Attr attr = element.getAttributeNode(key);
		if (attr == null) {
			return null;
		}
		return attr.getValue();
	}

	/**
	 * @since 3.4
	 */
	public Boolean getBoolean(String key) {
		Attr attr = element.getAttributeNode(key);
		if (attr == null) {
			return null;
		}
		return Boolean.valueOf(attr.getValue());
	}

	/**
	 * Returns the data of the Text node of the memento. Each memento is allowed only one Text node.
	 * 
	 * @return the data of the Text node of the memento, or <code>null</code> if the memento has no Text node.
	 * @since 2.0
	 * @throws DOMException
	 *             if the text node is too big
	 */
	public String getTextData() throws DOMException {
		Text textNode = getTextNode();
		if (textNode != null) {
			return textNode.getData();
		}
		return null;
	}

	/**
	 * @since 3.4
	 */
	public String[] getAttributeKeys() {
		NamedNodeMap map = element.getAttributes();
		int size = map.getLength();
		String[] attributes = new String[size];
		for (int i = 0; i < size; i++) {
			Node node = map.item(i);
			attributes[i] = node.getNodeName();
		}
		return attributes;
	}

	/**
	 * Returns the Text node of the memento. Each memento is allowed only one Text node.
	 * 
	 * @return the Text node of the memento, or <code>null</code> if the memento has no Text node.
	 */
	private Text getTextNode() {
		// Get the nodes.
		NodeList nodes = element.getChildNodes();
		int size = nodes.getLength();
		if (size == 0) {
			return null;
		}
		for (int nX = 0; nX < size; nX++) {
			Node node = nodes.item(nX);
			if (node instanceof Text) {
				return (Text) node;
			}
		}
		// a Text node was not found
		return null;
	}

	/**
	 * Places the element's attributes into the document.
	 * 
	 * @param copyText
	 *            true if the first text node should be copied
	 * @throws DOMException
	 *             if the attributes or children cannot be copied to this node.
	 */
	private void putElement(Element element, boolean copyText) throws DOMException {
		NamedNodeMap nodeMap = element.getAttributes();
		int size = nodeMap.getLength();
		for (int i = 0; i < size; i++) {
			Attr attr = (Attr) nodeMap.item(i);
			putString(attr.getName(), attr.getValue());
		}

		NodeList nodes = element.getChildNodes();
		size = nodes.getLength();
		// Copy first text node (fixes bug 113659).
		// Note that text data will be added as the first child (see putTextData)
		boolean needToCopyText = copyText;
		for (int i = 0; i < size; i++) {
			Node node = nodes.item(i);
			if (node instanceof Element) {
				XmlMemento child = createChild(node.getNodeName());
				child.putElement((Element) node, true);
			} else if (node instanceof Text && needToCopyText) {
				putTextData(((Text) node).getData());
				needToCopyText = false;
			}
		}
	}

	/**
	 * Sets the value of the given key to the given floating point number.
	 * 
	 * @param key
	 *            the key
	 * @param f
	 *            the value
	 * @throws DOMException
	 *             if the attribute cannot be set
	 */
	public void putFloat(String key, float f) throws DOMException {
		element.setAttribute(key, String.valueOf(f));
	}

	/**
	 * Sets the value of the given key to the given integer.
	 * 
	 * @param key
	 *            the key
	 * @param n
	 *            the value
	 * @throws DOMException
	 *             if the attribute cannot be set
	 */
	public void putInteger(String key, int n) throws DOMException {
		element.setAttribute(key, String.valueOf(n));
	}

	/**
	 * Copy the attributes and children from <code>memento</code> to the receiver.
	 * 
	 * @param memento
	 *            the XMLMemento to be copied.
	 * @throws DOMException
	 *             if the attributes or children cannot be copied to this node.
	 */
	public void putMemento(XmlMemento memento) throws DOMException {
		// Do not copy the element's top level text node (this would overwrite the existing text).
		// Text nodes of children are copied.
		putElement(memento.element, false);
	}

	/**
	 * Sets the value of the given key to the given string.
	 * 
	 * @param key
	 *            the key
	 * @param value
	 *            the value
	 * @throws DOMException
	 *             if the attribute cannot be set
	 */
	public void putString(String key, String value) throws DOMException {
		if (value == null) {
			return;
		}
		element.setAttribute(key, value);
	}

	/**
	 * Sets the value of the given key to the given boolean value.
	 * 
	 * @param key
	 *            the key
	 * @param value
	 *            the value
	 * @since 3.4
	 * @throws DOMException
	 *             if the attribute cannot be set
	 */
	public void putBoolean(String key, boolean value) throws DOMException {
		element.setAttribute(key, value ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Sets the memento's Text node to contain the given data. Creates the Text node if none exists. If a Text node does
	 * exist, it's current contents are replaced. Each memento is allowed only one text node.
	 * 
	 * @param data
	 *            the data to be placed on the Text node
	 * @since 2.0
	 * @throws DOMException
	 *             if the text node cannot be created under this node.
	 */
	public void putTextData(String data) throws DOMException {
		Text textNode = getTextNode();
		if (textNode == null) {
			textNode = factory.createTextNode(data);
			// Always add the text node as the first child (fixes bug 93718) 
			element.insertBefore(textNode, element.getFirstChild());
		} else {
			textNode.setData(data);
		}
	}

	/**
	 * Saves this memento's document current values to the specified writer.
	 * 
	 * @param writer
	 *            the writer used to save the memento's document
	 * @throws IOException
	 *             if there is a problem serializing the document to the stream.
	 */
	public void save(Writer writer) throws IOException {
		DOMWriter out = new DOMWriter(writer);
		try {
			out.print(element);
		} finally {
			out.close();
		}
	}

	/**
	 * A simple XML writer. Using this instead of the javax.xml.transform classes allows compilation against JCL
	 * Foundation (bug 80053).
	 */
	private static final class DOMWriter extends PrintWriter {

		/* constants */
		private static final String XML_VERSION = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; //$NON-NLS-1$

		/**
		 * Creates a new DOM writer on the given output writer.
		 * 
		 * @param output
		 *            the output writer
		 */
		public DOMWriter(Writer output) {
			super(output);
			println(XML_VERSION);
		}

		/**
		 * Prints the given element.
		 * 
		 * @param element
		 *            the element to print
		 */
		public void print(Element element) {
			// Ensure extra whitespace is not emitted next to a Text node,
			// as that will result in a situation where the restored text data is not the
			// same as the saved text data.
			boolean hasChildren = element.hasChildNodes();
			startTag(element, hasChildren);
			if (hasChildren) {
				boolean prevWasText = false;
				NodeList children = element.getChildNodes();
				for (int i = 0; i < children.getLength(); i++) {
					Node node = children.item(i);
					if (node instanceof Element) {
						if (!prevWasText) {
							println();
						}
						print((Element) children.item(i));
						prevWasText = false;
					} else if (node instanceof Text) {
						print(getEscaped(node.getNodeValue()));
						prevWasText = true;
					}
				}
				if (!prevWasText) {
					println();
				}
				endTag(element);
			}
		}

		private void startTag(Element element, boolean hasChildren) {
			StringBuffer sb = new StringBuffer();
			sb.append("<"); //$NON-NLS-1$
			sb.append(element.getTagName());
			NamedNodeMap attributes = element.getAttributes();
			for (int i = 0; i < attributes.getLength(); i++) {
				Attr attribute = (Attr) attributes.item(i);
				sb.append(" "); //$NON-NLS-1$
				sb.append(attribute.getName());
				sb.append("=\""); //$NON-NLS-1$
				sb.append(getEscaped(String.valueOf(attribute.getValue())));
				sb.append("\""); //$NON-NLS-1$
			}
			sb.append(hasChildren ? ">" : "/>"); //$NON-NLS-1$ //$NON-NLS-2$
			print(sb.toString());
		}

		private void endTag(Element element) {
			StringBuffer sb = new StringBuffer();
			sb.append("</"); //$NON-NLS-1$
			sb.append(element.getNodeName());
			sb.append(">"); //$NON-NLS-1$
			print(sb.toString());
		}

		private static void appendEscapedChar(StringBuffer buffer, char c) {
			String replacement = getReplacement(c);
			if (replacement != null) {
				buffer.append('&');
				buffer.append(replacement);
				buffer.append(';');
			} else if (c == 9 || c == 10 || c == 13 || c >= 32) {
				buffer.append(c);
			}
		}

		private static String getEscaped(String s) {
			StringBuffer result = new StringBuffer(s.length() + 10);
			for (int i = 0; i < s.length(); ++i) {
				appendEscapedChar(result, s.charAt(i));
			}
			return result.toString();
		}

		private static String getReplacement(char c) {
			// Encode special XML characters into the equivalent character references.
			// The first five are defined by default for all XML documents.
			// The next three (#xD, #xA, #x9) are encoded to avoid them
			// being converted to spaces on deserialization
			// (fixes bug 93720)
			switch (c) {
			case '<':
				return "lt"; //$NON-NLS-1$
			case '>':
				return "gt"; //$NON-NLS-1$
			case '"':
				return "quot"; //$NON-NLS-1$
			case '\'':
				return "apos"; //$NON-NLS-1$
			case '&':
				return "amp"; //$NON-NLS-1$
			case '\r':
				return "#x0D"; //$NON-NLS-1$
			case '\n':
				return "#x0A"; //$NON-NLS-1$
			case '\u0009':
				return "#x09"; //$NON-NLS-1$
			}
			return null;
		}
	}

}
