/*******************************************************************************
 * Copyright (c) 2001, 2005 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
 *     Jens Lukowski/Innoopract - initial renaming/restructuring
 *     
 *******************************************************************************/
package org.eclipse.wst.xml.core.internal.document;



import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;


/**
 * NodeContainer class
 */
public abstract class NodeContainer extends NodeImpl implements Node, NodeList {

	/**
	 */
	private class ChildNodesCache implements NodeList {
		private Node curChild = null;
		private int curIndex = -1;
		private int length = 0;

		ChildNodesCache() {
			initializeCache();
		}

		public int getLength() {
			// atomic
			return this.length;
		}

		private void initializeCache() {
			// note we use the outter objects lockobject
			// (since we are using their "children".
			synchronized (lockObject) {
				for (Node child = firstChild; child != null; child = child.getNextSibling()) {
					this.length++;
				}
			}
		}

		public Node item(int index) {
			synchronized (lockObject) {
				if (this.length == 0)
					return null;
				if (index < 0)
					return null;
				if (index >= this.length)
					return null;

				if (this.curIndex < 0) { // first time
					if (index * 2 >= this.length) { // search from the last
						this.curIndex = this.length - 1;
						this.curChild = lastChild;
					} else { // search from the first
						this.curIndex = 0;
						this.curChild = firstChild;
					}
				}

				if (index == this.curIndex)
					return this.curChild;

				if (index > this.curIndex) {
					while (index > this.curIndex) {
						this.curIndex++;
						this.curChild = this.curChild.getNextSibling();
					}
				} else { // index < this.curIndex
					while (index < this.curIndex) {
						this.curIndex--;
						this.curChild = this.curChild.getPreviousSibling();
					}
				}

				return this.curChild;
			}
		}
	}

	private NodeList childNodesCache = null;

	private boolean fChildEditable = true;
	NodeImpl firstChild = null;
	NodeImpl lastChild = null;

	Object lockObject = new byte[0];

	/**
	 * NodeContainer constructor
	 */
	protected NodeContainer() {
		super();
	}

	/**
	 * NodeContainer constructor
	 * 
	 * @param that
	 *            NodeContainer
	 */
	protected NodeContainer(NodeContainer that) {
		super(that);
	}

	/**
	 * appendChild method
	 * 
	 * @return org.w3c.dom.Node
	 * @param newChild
	 *            org.w3c.dom.Node
	 */
	public Node appendChild(Node newChild) throws DOMException {
		return insertBefore(newChild, null);
	}

	/**
	 * cloneChildNodes method
	 * 
	 * @param container
	 *            org.w3c.dom.Node
	 * @param deep
	 *            boolean
	 */
	protected void cloneChildNodes(Node newParent, boolean deep) {
		if (newParent == null || newParent == this)
			return;
		if (!(newParent instanceof NodeContainer))
			return;

		NodeContainer container = (NodeContainer) newParent;
		container.removeChildNodes();

		for (Node child = getFirstChild(); child != null; child = child.getNextSibling()) {
			Node cloned = child.cloneNode(deep);
			if (cloned != null)
				container.appendChild(cloned);
		}
	}

	/**
	 * getChildNodes method
	 * 
	 * @return org.w3c.dom.NodeList
	 */
	public NodeList getChildNodes() {
		return this;
	}

	/**
	 * getFirstChild method
	 * 
	 * @return org.w3c.dom.Node
	 */
	public Node getFirstChild() {
		return this.firstChild;
	}

	/**
	 * getLastChild method
	 * 
	 * @return org.w3c.dom.Node
	 */
	public Node getLastChild() {
		return this.lastChild;
	}

	/**
	 * getLength method
	 * 
	 * @return int
	 */
	public int getLength() {
		if (this.firstChild == null)
			return 0;
		synchronized (lockObject) {
			if (this.childNodesCache == null)
				this.childNodesCache = new ChildNodesCache();
			return this.childNodesCache.getLength();
		}
	}

	/**
	 */
	public String getSource() {
		StringBuffer buffer = new StringBuffer();

		IStructuredDocumentRegion startStructuredDocumentRegion = getStartStructuredDocumentRegion();
		if (startStructuredDocumentRegion != null) {
			String source = startStructuredDocumentRegion.getText();
			if (source != null)
				buffer.append(source);
		}

		for (NodeImpl child = firstChild; child != null; child = (NodeImpl) child.getNextSibling()) {
			String source = child.getSource();
			if (source != null)
				buffer.append(source);
		}

		IStructuredDocumentRegion endStructuredDocumentRegion = getEndStructuredDocumentRegion();
		if (endStructuredDocumentRegion != null) {
			String source = endStructuredDocumentRegion.getText();
			if (source != null)
				buffer.append(source);
		}

		return buffer.toString();
	}

	/**
	 * hasChildNodes method
	 * 
	 * @return boolean
	 */
	public boolean hasChildNodes() {
		return (this.firstChild != null);
	}

	/**
	 * insertBefore method
	 * 
	 * @return org.w3c.dom.Node
	 * @param newChild
	 *            org.w3c.dom.Node
	 * @param refChild
	 *            org.w3c.dom.Node
	 */
	public Node insertBefore(Node newChild, Node refChild) throws DOMException {
		if (newChild == null)
			return null; // nothing to do
		if (refChild != null && refChild.getParentNode() != this) {
			throw new DOMException(DOMException.NOT_FOUND_ERR, new String());
		}
		if (!isChildEditable()) {
			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
		}
		if (newChild == refChild)
			return newChild; // nothing to do

		if (newChild.getNodeType() == DOCUMENT_FRAGMENT_NODE) {
			// insert child nodes instead
			for (Node child = newChild.getFirstChild(); child != null; child = newChild.getFirstChild()) {
				newChild.removeChild(child);
				insertBefore(child, refChild);
			}
			return newChild;
		}
		// synchronized in case another thread is getting item, or length
		synchronized (lockObject) {
			this.childNodesCache = null; // invalidate child nodes cache
		}

		NodeImpl child = (NodeImpl) newChild;
		NodeImpl next = (NodeImpl) refChild;
		NodeImpl prev = null;
		Node oldParent = child.getParentNode();
		if (oldParent != null)
			oldParent.removeChild(child);
		if (next == null) {
			prev = this.lastChild;
			this.lastChild = child;
		} else {
			prev = (NodeImpl) next.getPreviousSibling();
			next.setPreviousSibling(child);
		}
		if (prev == null)
			this.firstChild = child;
		else
			prev.setNextSibling(child);
		child.setPreviousSibling(prev);
		child.setNextSibling(next);
		child.setParentNode(this);
		// make sure having the same owner document
		if (child.getOwnerDocument() == null) {
			if (getNodeType() == DOCUMENT_NODE) {
				child.setOwnerDocument((Document) this);
			} else {
				child.setOwnerDocument(getOwnerDocument());
			}
		}

		notifyChildReplaced(child, null);

		return child;
	}

	public boolean isChildEditable() {
		if (!fChildEditable) {
			DOMModelImpl model = (DOMModelImpl) getModel();
			if (model != null && model.isReparsing()) {
				return true;
			}
		}
		return fChildEditable;
	}

	/**
	 * isContainer method
	 * 
	 * @return boolean
	 */
	public boolean isContainer() {
		return true;
	}

	/**
	 * item method
	 * 
	 * @return org.w3c.dom.Node
	 * @param index
	 *            int
	 */
	public Node item(int index) {
		if (this.firstChild == null)
			return null;
		synchronized (lockObject) {
			if (this.childNodesCache == null)
				this.childNodesCache = new ChildNodesCache();
			return this.childNodesCache.item(index);
		}
	}

	/**
	 * notifyChildReplaced method
	 * 
	 * @param newChild
	 *            org.w3c.dom.Node
	 * @param oldChild
	 *            org.w3c.dom.Node
	 */
	protected void notifyChildReplaced(Node newChild, Node oldChild) {
		DocumentImpl document = (DocumentImpl) getContainerDocument();
		if (document == null)
			return;

		syncChildEditableState(newChild);

		DOMModelImpl model = (DOMModelImpl) document.getModel();
		if (model == null)
			return;
		model.childReplaced(this, newChild, oldChild);
	}

	/**
	 * removeChild method
	 * 
	 * @return org.w3c.dom.Node
	 * @param oldChild
	 *            org.w3c.dom.Node
	 */
	public Node removeChild(Node oldChild) throws DOMException {
		if (oldChild == null)
			return null;
		if (oldChild.getParentNode() != this) {
			throw new DOMException(DOMException.NOT_FOUND_ERR, new String());
		}

		if (!isChildEditable()) {
			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
		}

		// synchronized in case another thread is getting item, or length
		synchronized (lockObject) {
			this.childNodesCache = null; // invalidate child nodes cache
		}

		NodeImpl child = (NodeImpl) oldChild;
		NodeImpl prev = (NodeImpl) child.getPreviousSibling();
		NodeImpl next = (NodeImpl) child.getNextSibling();

		child.setEditable(true, true); // clear ReadOnly flags

		if (prev == null)
			this.firstChild = next;
		else
			prev.setNextSibling(next);
		if (next == null)
			this.lastChild = prev;
		else
			next.setPreviousSibling(prev);
		child.setPreviousSibling(null);
		child.setNextSibling(null);
		child.setParentNode(null);

		notifyChildReplaced(null, child);

		return child;
	}

	/**
	 * removeChildNodes method
	 */
	public void removeChildNodes() {
		if (!isChildEditable()) {
			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
		}

		Node nextChild = null;
		for (Node child = getFirstChild(); child != null; child = nextChild) {
			nextChild = child.getNextSibling();
			removeChild(child);
		}
	}

	/**
	 * removeChildNodes method
	 * 
	 * @return org.w3c.dom.DocumentFragment
	 * @param firstChild
	 *            org.w3c.dom.Node
	 * @param lastChild
	 *            org.w3c.dom.Node
	 */
	public DocumentFragment removeChildNodes(Node firstChild, Node lastChild) {
		if (!hasChildNodes())
			return null;
		if (!isChildEditable()) {
			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
		}

		Document document = null;
		if (getNodeType() == DOCUMENT_NODE)
			document = (Document) this;
		else
			document = getOwnerDocument();
		if (document == null)
			return null;
		DocumentFragment fragment = document.createDocumentFragment();
		if (fragment == null)
			return null;

		if (firstChild == null)
			firstChild = getFirstChild();
		if (lastChild == null)
			lastChild = getLastChild();
		Node nextChild = null;
		for (Node child = firstChild; child != null; child = nextChild) {
			nextChild = child.getNextSibling();
			removeChild(child);
			fragment.appendChild(child);
			if (child == lastChild)
				break;
		}

		return fragment;
	}

	/**
	 * replaceChild method
	 * 
	 * @return org.w3c.dom.Node
	 * @param newChild
	 *            org.w3c.dom.Node
	 * @param oldChild
	 *            org.w3c.dom.Node
	 */
	public Node replaceChild(Node newChild, Node oldChild) throws DOMException {
		if (!isChildEditable()) {
			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
		}

		if (oldChild == null)
			return newChild;
		if (newChild != null)
			insertBefore(newChild, oldChild);
		return removeChild(oldChild);
	}

	public void setChildEditable(boolean editable) {
		if (fChildEditable == editable) {
			return;
		}

		ReadOnlyController roc = ReadOnlyController.getInstance();
		Node node;
		if (editable) {
			for (node = getFirstChild(); node != null; node = node.getNextSibling()) {
				roc.unlockNode((IDOMNode) node);
			}
		} else {
			for (node = getFirstChild(); node != null; node = node.getNextSibling()) {
				roc.lockNode((IDOMNode) node);
			}
		}

		fChildEditable = editable;
		notifyEditableChanged();
	}

	protected void syncChildEditableState(Node child) {
		ReadOnlyController roc = ReadOnlyController.getInstance();
		if (fChildEditable) {
			roc.unlockNode((NodeImpl) child);
		} else {
			roc.lockNode((NodeImpl) child);
		}
	}
}
