/************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 * 
 * Copyright 2008, 2010 Oracle and/or its affiliates. All rights reserved.
 * 
 * Use is subject to license terms.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy
 * of the License at http://www.apache.org/licenses/LICENSE-2.0. You can also
 * obtain a copy of the License at http://odftoolkit.org/docs/license.txt
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * 
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ************************************************************************/
package org.odftoolkit.odfdom.pkg;

import java.util.ArrayList;

import org.apache.xerces.dom.ElementNSImpl;
import org.apache.xerces.dom.ParentNode;
import org.odftoolkit.odfdom.dom.OdfDocumentNamespace;
import org.w3c.dom.DOMException;
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;

abstract public class OdfElement extends ElementNSImpl {

	private static final long serialVersionUID = -4939293285696678939L;

	/** Creates a new instance of OdfElement */
	public OdfElement(OdfFileDom ownerDocument, String namespaceURI,
			String qualifiedName) throws DOMException {
		super(ownerDocument, namespaceURI, qualifiedName);
	}

	/** Creates a new instance of OdfElement */
	public OdfElement(OdfFileDom ownerDocument, OdfName aName)
			throws DOMException {
		super(ownerDocument, aName.getUri(), aName.getQName());
	}

	abstract public OdfName getOdfName();

	protected <T extends OdfElement> T getParentAs(Class<T> clazz) {
		Node parent = getParentNode();
		if (parent != null && clazz.isInstance(parent)) {
			return clazz.cast(parent);
		} else {
			return null;
		}
	}

	protected <T extends OdfElement> T getAncestorAs(Class<T> clazz) {
		Node node = getParentNode();
		while (node != null) {
			if (clazz.isInstance(node)) {
				return clazz.cast(node);
			}
			node = node.getParentNode();
		}
		return null;
	}

	@Override
	public String toString() {
		return mapNode(this, new StringBuilder()).toString();
	}

	/** Only Siblings will be traversed by this method as Children */
	static private StringBuilder mapNodeTree(Node node, StringBuilder xml) {
		while (node != null) {
			// mapping node and this mapping include always all descendants
			xml = mapNode(node, xml);
			// next sibling will be mapped to XML
			node = node.getNextSibling();
		}
		return xml;
	}

	private static StringBuilder mapNode(Node node, StringBuilder xml) {
		if (node instanceof Element) {
			xml = mapElementNode(node, xml);
		} else if (node instanceof Text) {
			xml = mapTextNode(node, xml);
		}
		return xml;
	}

	private static StringBuilder mapTextNode(Node node, StringBuilder xml) {
		if (node != null) {
			xml = xml.append(node.getTextContent());
		}
		return xml;
	}

	private static StringBuilder mapElementNode(Node node, StringBuilder xml) {
		if (node != null) {
			xml = xml.append("<");
			xml = xml.append(node.getNodeName());
			xml = mapAttributeNode(node, xml);
			xml = xml.append(">");
			xml = mapNodeTree(node.getFirstChild(), xml);
			xml = xml.append("</");
			xml = xml.append(node.getNodeName());
			xml = xml.append(">");
		}
		return xml;
	}

	private static StringBuilder mapAttributeNode(Node node, StringBuilder xml) {
		NamedNodeMap attrs = null;
		int length;
		if ((attrs = node.getAttributes()) != null
				&& (length = attrs.getLength()) > 0) {
			for (int i = 0; length > i; i++) {
				xml = xml.append(" ");
				xml = xml.append(attrs.item(i).getNodeName());
				xml = xml.append("=\"");
				xml = xml.append(attrs.item(i).getNodeValue());
				xml = xml.append("\"");
			}
		}
		return xml;
	}

	/**
	 * Set the value of an ODF attribute by <code>OdfName</code>.
	 * 
	 * @param name
	 *            The qualified name of the ODF attribute.
	 * @param value
	 *            The value to be set in <code>String</code> form
	 */
	public void setOdfAttributeValue(OdfName name, String value) {
		setAttributeNS(name.getUri(), name.getQName(), value);
	}

	/**
	 * Set an ODF attribute to this element
	 * 
	 * @param attribute
	 *            the attribute to be set
	 */
	public void setOdfAttribute(OdfAttribute attribute) {
		setAttributeNodeNS(attribute);
	}

	/**
	 * Retrieves a value of an ODF attribute by <code>OdfName</code>.
	 * 
	 * @param name
	 *            The qualified name of the ODF attribute.
	 * @return The value of the attribute as <code>String</code> or
	 *         <code>null</code> if the attribute does not exist.
	 */
	public String getOdfAttributeValue(OdfName name) {
		return getAttributeNS(name.getUri(), name.getLocalName());
	}

	/**
	 * Retrieves an ODF attribute by <code>OdfName</code>.
	 * 
	 * @param name
	 *            The qualified name of the ODF attribute.
	 * @return The <code>OdfAttribute</code> or <code>null</code> if the
	 *         attribute does not exist.
	 */
	public OdfAttribute getOdfAttribute(OdfName name) {
		return (OdfAttribute) getAttributeNodeNS(name.getUri(), name.getLocalName());
	}

	/**
	 * Retrieves an ODF attribute by <code>NamespaceName</code>, and local name.
	 * 
	 * @param namespace
	 *            The namespace of the ODF attribute.
	 * @param localname
	 *            The local name of the ODF attribute.
	 * @return The <code>OdfAttribute</code> or <code>null</code> if the
	 *         attribute does not exist.
	 */
	public OdfAttribute getOdfAttribute(NamespaceName namespace, String localname) {
		return (OdfAttribute) getAttributeNodeNS(namespace.getUri(),
				localname);
	}

	/**
	 * Determines if an ODF attribute exists.
	 * 
	 * @param name
	 *            The qualified name of the ODF attribute.
	 * @return True if the attribute exists.
	 */
	public boolean hasOdfAttribute(OdfName name) {
		return hasAttributeNS(name.getUri(), name.getLocalName());
	}

	/**
	 * returns the first child node that implements the given class.
	 * 
	 * @param <T>
	 *            The type of the ODF element to be found.
	 * @param clazz
	 *            is a class that extends OdfElement.
	 * @param parentNode
	 *            is the parent O of the children to be found.
	 * @return the first child node of the given parentNode that is a clazz or
	 *         null if none is found.
	 */
	@SuppressWarnings("unchecked")
	static public <T extends OdfElement> T findFirstChildNode(Class<T> clazz,
			Node parentNode) {
		if (parentNode != null && parentNode instanceof ParentNode) {
			Node node = ((ParentNode) parentNode).getFirstChild();
			while ((node != null) && !clazz.isInstance(node)) {
				node = node.getNextSibling();
			}

			if (node != null) {
				return (T) node;
			}
		}

		return null;
	}

	/**
	 * returns the first sibling after the given reference node that implements
	 * the given class.
	 * 
	 * @param <T>
	 *            The type of the ODF element to be found.
	 * @param clazz
	 *            is a class that extends OdfElement.
	 * @param refNode
	 *            the reference node of the siblings to be found.
	 * @return the first sibbling of the given reference node that is a clazz or
	 *         null if none is found.
	 */
	@SuppressWarnings("unchecked")
	static public <T extends OdfElement> T findNextChildNode(Class<T> clazz,
			Node refNode) {
		if (refNode != null) {
			Node node = refNode.getNextSibling();
			while (node != null && !clazz.isInstance(node)) {
				node = node.getNextSibling();
			}

			if (node != null) {
				return (T) node;
			}
		}

		return null;
	}

	/**
	 * returns the first previous sibling before the given reference node that
	 * implements the given class.
	 * 
	 * @param clazz
	 *            is a class that extends OdfElement.
	 * @param refNode
	 *            the reference node which siblings are to be searched.
	 * @return the first previous sibbling of the given reference node that is a
	 *         clazz or null if none is found.
	 */
	@SuppressWarnings("unchecked")
	static public <T extends OdfElement> T findPreviousChildNode(
			Class<T> clazz, Node refNode) {
		if (refNode != null) {
			Node node = refNode.getPreviousSibling();
			while (node != null && !clazz.isInstance(node)) {
				node = node.getPreviousSibling();
			}

			if (node != null) {
				return (T) node;
			}
		}

		return null;
	}

	@Override
	public Node cloneNode(boolean deep) {
		OdfElement cloneElement = ((OdfFileDom) this.ownerDocument).newOdfElement(this.getClass());

		if (attributes != null) {
			for (int i = 0; i < attributes.getLength(); i++) {
				Node item = attributes.item(i);
				String qname = null;
				String prefix = item.getPrefix();
				if (prefix == null) {
					qname = item.getLocalName();
				} else {
					qname = prefix + ":" + item.getLocalName();
				}
				cloneElement.setAttributeNS(item.getNamespaceURI(), qname, item.getNodeValue());
			}
		}

		if (deep) {
			Node childNode = getFirstChild();
			while (childNode != null) {
				cloneElement.appendChild(childNode.cloneNode(true));
				childNode = childNode.getNextSibling();
			}
		}

		return cloneElement;
	}

	/**
	 * indicates if some other object is equal to this one.
	 * 
	 * @param obj
	 *            - the reference object with which to compare.
	 * @return true if this object is the same as the obj argument; false
	 *         otherwise.
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}

		if ((obj == null) || !(obj instanceof OdfElement)) {
			return false;
		}

		OdfElement compare = (OdfElement) obj;

		// compare node name
		if (!localName.equals(compare.localName)) {
			return false;
		}

		if (!this.namespaceURI.equals(compare.namespaceURI)) {
			return false;
		}

		// compare node attributes
		if (attributes == compare.attributes) {
			return true;
		}

		if ((attributes == null) || (compare.attributes == null)) {
			return false;
		}

		int attr_count1 = attributes.getLength();
		int attr_count2 = compare.attributes.getLength();

		ArrayList<Node> attr1 = new ArrayList<Node>();
		for (int i = 0; i < attr_count1; i++) {
			Node node = attributes.item(i);
			if (node.getNodeValue().length() == 0) {
				continue;
			}
			attr1.add(node);
		}

		ArrayList<Node> attr2 = new ArrayList<Node>();
		for (int i = 0; i < attr_count2; i++) {
			Node node = compare.attributes.item(i);
			if (node.getNodeValue().length() == 0) {
				continue;
			}
			attr2.add(node);
		}

		if (attr1.size() != attr2.size()) {
			return false;
		}

		for (int i = 0; i < attr1.size(); i++) {
			Node n1 = attr1.get(i);
			if (n1.getLocalName().equals("name")
					&& n1.getNamespaceURI().equals(
					OdfDocumentNamespace.STYLE.getUri())) {
				continue; // do not compare style names
			}
			Node n2 = null;
			int j = 0;
			for (j = 0; j < attr2.size(); j++) {
				n2 = attr2.get(j);
				if (n1.getLocalName().equals(n2.getLocalName())
						&& n1.getNamespaceURI().equals(n2.getNamespaceURI())) {
					break;
				}
			}
			if (j == attr2.size()) {
				return false;
			}

			if (!n1.getTextContent().equals(n2.getTextContent())) {
				return false;
			}
		}

		// now compare child elements
		NodeList childs1 = this.getChildNodes();
		NodeList childs2 = compare.getChildNodes();

		int child_count1 = childs1.getLength();
		int child_count2 = childs2.getLength();
		if ((child_count1 == 0) && (child_count2 == 0)) {
			return true;
		}

		ArrayList<Node> nodes1 = new ArrayList<Node>();
		for (int i = 0; i < child_count1; i++) {
			Node node = childs1.item(i);
			if (node.getNodeType() == Node.TEXT_NODE) {
				if (node.getNodeValue().trim().length() == 0) {
					continue; // skip whitespace text nodes
				}
			}
			nodes1.add(node);
		}

		ArrayList<Node> nodes2 = new ArrayList<Node>();
		for (int i = 0; i < child_count2; i++) {
			Node node = childs2.item(i);
			if (node.getNodeType() == Node.TEXT_NODE) {
				if (node.getNodeValue().trim().length() == 0) {
					continue; // skip whitespace text nodes
				}
			}
			nodes2.add(node);
		}

		if (nodes1.size() != nodes2.size()) {
			return false;
		}

		for (int i = 0; i < nodes1.size(); i++) {
			Node n1 = nodes1.get(i);
			Node n2 = nodes2.get(i);
			if (!n1.equals(n2)) {
				return false;
			}
		}
		return true;
	}

	protected void onRemoveNode(Node node) {
		Node child = node.getFirstChild();
		while (child != null) {
			this.onRemoveNode(child);
			child = child.getNextSibling();
		}

		if (OdfElement.class.isInstance(node)) {
			((OdfElement) node).onRemoveNode();
		}
	}

	protected void onInsertNode(Node node) {
		Node child = node.getFirstChild();
		while (child != null) {
			this.onInsertNode(child);
			child = child.getNextSibling();
		}

		if (OdfElement.class.isInstance(node)) {
			((OdfElement) node).onInsertNode();
		}
	}

	protected void onRemoveNode() {
	}

	protected void onInsertNode() {
	}

	@Override
	public Node insertBefore(Node newChild, Node refChild) throws DOMException {
		onInsertNode(newChild);
		return super.insertBefore(newChild, refChild);
	}

	@Override
	public Node removeChild(Node oldChild) throws DOMException {
		onRemoveNode(oldChild);
		return super.removeChild(oldChild);
	}

	@Override
	public Node replaceChild(Node newChild, Node oldChild) throws DOMException {
		onInsertNode(newChild);
		onRemoveNode(oldChild);
		return super.replaceChild(newChild, oldChild);
	}

	/**
	 * Accept an visitor instance to allow the visitor to do some operations.
	 * Refer to visitor design pattern to get a better understanding.
	 * @param visitor	an instance of DefaultElementVisitor
	 */
	public void accept(ElementVisitor visitor) {
		visitor.visit(this);
	}
}
