/************************************************************************
 *
 * 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;
	}

    protected OdfElement cloneOdfElement() {
		return ((OdfFileDom) this.ownerDocument).newOdfElement(this.getClass());
	}

	@Override
	public Node cloneNode(boolean deep) {
		OdfElement cloneElement = this.cloneOdfElement();
        
		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);
	}
}
