/*
 * Copyright 2004,2005 The Apache Software Foundation.
 *
 * 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
 *
 * 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.apache.axiom.om.impl.dom;

import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMException;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNode;
import org.apache.axiom.om.impl.OMContainerEx;
import org.apache.axiom.om.impl.OMNodeEx;
import org.apache.axiom.om.impl.traverse.OMChildrenIterator;
import org.apache.axiom.om.impl.traverse.OMChildrenQNameIterator;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.namespace.QName;
import java.util.Iterator;

public abstract class ParentNode extends ChildNode implements OMContainerEx {

    protected ChildNode firstChild;

    protected ChildNode lastChild;

    /**
     * @param ownerDocument
     */
    protected ParentNode(DocumentImpl ownerDocument, OMFactory factory) {
        super(ownerDocument, factory);
    }

    protected ParentNode(OMFactory factory) {
        super(factory);
    }

    // /
    // /OMContainer methods
    // /

    public void addChild(OMNode omNode) {
        this.appendChild((Node) omNode);
    }

    public void buildNext() {
        if (!this.done)
            builder.next();
    }

    public Iterator getChildren() {
        return new OMChildrenIterator(this.firstChild);
    }

    /**
     * Returns an iterator of child nodes having a given qname.
     * 
     * @see org.apache.axiom.om.OMContainer#getChildrenWithName
     * (javax.xml.namespace.QName)
     */
    public Iterator getChildrenWithName(QName elementQName) throws OMException {
        return new OMChildrenQNameIterator(getFirstOMChild(), elementQName);
    }

    /**
     * Returns the first OMElement child node.
     * 
     * @see org.apache.axiom.om.OMContainer#getFirstChildWithName
     * (javax.xml.namespace.QName)
     */
    public OMElement getFirstChildWithName(QName elementQName)
            throws OMException {
        Iterator children = new OMChildrenQNameIterator(getFirstOMChild(),
                elementQName);
        while (children.hasNext()) {
            OMNode node = (OMNode) children.next();

            // Return the first OMElement node that is found
            if (node instanceof OMElement) {
                return (OMElement) node;
            }
        }
        return null;
    }

    public OMNode getFirstOMChild() {
        while ((firstChild == null) && !done) {
            buildNext();
        }
        return firstChild;
    }

    public void setFirstChild(OMNode omNode) {
        if (firstChild != null) {
            ((OMNodeEx) omNode).setParent(this);
        }
        this.firstChild = (ChildNode) omNode;
    }

    // /
    // /DOM Node methods
    // /

    public NodeList getChildNodes() {
        if (!this.done) {
            this.build();
        }
        return new NodeListImpl(this, null, null);
    }

    public Node getFirstChild() {
        return (Node) this.getFirstOMChild();
    }

    public Node getLastChild() {
        if (!this.done) {
            this.build();
        }
        return this.lastChild;
    }

    public boolean hasChildNodes() {
        while ((firstChild == null) && !done) {
            buildNext();
        }
        return this.firstChild != null;
    }

    /**
     * Inserts newChild before the refChild. If the refChild is null then the
     * newChild is made the last child.
     */
    public Node insertBefore(Node newChild, Node refChild) throws DOMException {

        ChildNode newDomChild = (ChildNode) newChild;
        ChildNode refDomChild = (ChildNode) refChild;

        if (this == newChild || !isAncestor(newChild)) {
            throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
                    DOMMessageFormatter.formatMessage(
                            DOMMessageFormatter.DOM_DOMAIN,
                            "HIERARCHY_REQUEST_ERR", null));
        }

        if (!(this instanceof Document)
                && !(this.ownerNode == newDomChild.getOwnerDocument())) {
            throw new DOMException(DOMException.WRONG_DOCUMENT_ERR,
                    DOMMessageFormatter.formatMessage(
                            DOMMessageFormatter.DOM_DOMAIN,
                            "WRONG_DOCUMENT_ERR", null));
        }

        if (this.isReadonly()) {
            throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
                    DOMMessageFormatter.formatMessage(
                            DOMMessageFormatter.DOM_DOMAIN,
                            "NO_MODIFICATION_ALLOWED_ERR", null));
        }

        if (this instanceof Document) {
            if (((DocumentImpl) this).documentElement != null
                    && !(newDomChild instanceof CommentImpl)) {
                // Throw exception since there cannot be two document elements
                throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
                        DOMMessageFormatter.formatMessage(
                                DOMMessageFormatter.DOM_DOMAIN,
                                "HIERARCHY_REQUEST_ERR", null));
            } else if (newDomChild instanceof ElementImpl) {
                if (newDomChild.parentNode == null) {
                    newDomChild.parentNode = this;
                }
                // set the document element
                ((DocumentImpl) this).documentElement = (ElementImpl) newDomChild;
            }
        }

        if (refChild == null) { // Append the child to the end of the list
            // if there are no children
            if (this.lastChild == null && firstChild == null) {
                this.lastChild = newDomChild;
                this.firstChild = newDomChild;
                this.firstChild.isFirstChild(true);
                newDomChild.setParent(this);
            } else {
                this.lastChild.nextSibling = newDomChild;
                newDomChild.previousSibling = this.lastChild;

                this.lastChild = newDomChild;
                this.lastChild.nextSibling = null;
            }
            if (newDomChild.parentNode == null) {
                newDomChild.parentNode = this;
            }
            return newChild;
        } else {
            Iterator children = this.getChildren();
            boolean found = false;
            while (children.hasNext()) {
                ChildNode tempNode = (ChildNode) children.next();

                if (tempNode.equals(refChild)) {
                    // RefChild found
                    if (this.firstChild == tempNode) { // If the refChild is the
                                                    // first child

                        if (newChild instanceof DocumentFragmentimpl) {
                            // The new child is a DocumentFragment
                            DocumentFragmentimpl docFrag = 
                                                (DocumentFragmentimpl) newChild;
                            this.firstChild = docFrag.firstChild;
                            docFrag.lastChild.nextSibling = refDomChild;
                            refDomChild.previousSibling = 
                                                docFrag.lastChild.nextSibling;

                        } else {

                            // Make the newNode the first Child
                            this.firstChild = newDomChild;

                            newDomChild.nextSibling = refDomChild;
                            refDomChild.previousSibling = newDomChild;

                            this.firstChild.isFirstChild(true);
                            refDomChild.isFirstChild(false);
                            newDomChild.previousSibling = null; // Just to be
                                                                // sure :-)

                        }
                    } else { // If the refChild is not the fist child
                        ChildNode previousNode = refDomChild.previousSibling;

                        if (newChild instanceof DocumentFragmentimpl) {
                            // the newChild is a document fragment
                            DocumentFragmentimpl docFrag = 
                                                (DocumentFragmentimpl) newChild;

                            previousNode.nextSibling = docFrag.firstChild;
                            docFrag.firstChild.previousSibling = previousNode;

                            docFrag.lastChild.nextSibling = refDomChild;
                            refDomChild.previousSibling = docFrag.lastChild;
                        } else {

                            previousNode.nextSibling = newDomChild;
                            newDomChild.previousSibling = previousNode;

                            newDomChild.nextSibling = refDomChild;
                            refDomChild.previousSibling = newDomChild;
                        }

                    }
                    found = true;
                    break;
                }
            }

            if (!found) {
                throw new DOMException(DOMException.NOT_FOUND_ERR,
                        DOMMessageFormatter.formatMessage(
                                DOMMessageFormatter.DOM_DOMAIN,
                                "NOT_FOUND_ERR", null));
            }

            if (newDomChild.parentNode == null) {
                newDomChild.parentNode = this;
            }

            return newChild;
        }
    }

    /**
     * Replaces the oldChild with the newChild.
     */
    public Node replaceChild(Node newChild, Node oldChild) throws DOMException {
        ChildNode newDomChild = (ChildNode) newChild;
        ChildNode oldDomChild = (ChildNode) oldChild;

        if (this == newChild || !isAncestor(newChild)) {
            throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
                    DOMMessageFormatter.formatMessage(
                            DOMMessageFormatter.DOM_DOMAIN,
                            "HIERARCHY_REQUEST_ERR", null));
        }

        if (!this.ownerNode.equals(newDomChild.ownerNode)) {
            throw new DOMException(DOMException.WRONG_DOCUMENT_ERR,
                    DOMMessageFormatter.formatMessage(
                            DOMMessageFormatter.DOM_DOMAIN,
                            "WRONG_DOCUMENT_ERR", null));
        }

        if (this.isReadonly()) {
            throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
                    DOMMessageFormatter.formatMessage(
                            DOMMessageFormatter.DOM_DOMAIN,
                            "NO_MODIFICATION_ALLOWED_ERR", null));
        }

        Iterator children = this.getChildren();
        boolean found = false;
        while (children.hasNext()) {
            ChildNode tempNode = (ChildNode) children.next();
            if (tempNode.equals(oldChild)) {
                if (newChild instanceof DocumentFragmentimpl) {
                    DocumentFragmentimpl docFrag = 
                                            (DocumentFragmentimpl) newDomChild;
                    ChildNode child = (ChildNode) docFrag.getFirstChild();
                    child.parentNode = this;
                    this.replaceChild(child, oldChild);
                } else {
                    if (this.firstChild == oldDomChild) {
                        
                        newDomChild.parentNode = this;
                        
                        if(this.firstChild.nextSibling != null) {
                            this.firstChild.nextSibling.previousSibling = newDomChild;
                            newDomChild.nextSibling = this.firstChild.nextSibling;
                        }
                        
                        //Cleanup the current first child
                        this.firstChild.parentNode = null;
                        this.firstChild.nextSibling = null;
                        
                        //Set the new first child
                        this.firstChild = newDomChild;
                        
                    } else {
                        newDomChild.nextSibling = oldDomChild.nextSibling;
                        newDomChild.previousSibling = oldDomChild.previousSibling;

                        oldDomChild.previousSibling.nextSibling = newDomChild;

                        // If the old child is not the last
                        if (oldDomChild.nextSibling != null) {
                            oldDomChild.nextSibling.previousSibling = newDomChild;
                        } else {
                            this.lastChild = newDomChild;
                        }

                        if (newDomChild.parentNode == null) {
                            newDomChild.parentNode = this;
                        }
                    }
                }
                found = true;

                // remove the old child's references to this tree
                oldDomChild.nextSibling = null;
                oldDomChild.previousSibling = null;
                oldDomChild.parentNode = null;
            }
        }

        if (!found)
            throw new DOMException(DOMException.NOT_FOUND_ERR,
                    DOMMessageFormatter.formatMessage(
                            DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR",
                            null));

        return oldChild;
    }

    /**
     * Removes the given child from the DOM Tree.
     */
    public Node removeChild(Node oldChild) throws DOMException {
        // Check if this node is readonly
        if (this.isReadonly()) {
            throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
                    DOMMessageFormatter.formatMessage(
                            DOMMessageFormatter.DOM_DOMAIN,
                            "NO_MODIFICATION_ALLOWED_ERR", null));
        }

        // Check if the Child is there
        Iterator children = this.getChildren();
        boolean childFound = false;
        while (children.hasNext()) {
            ChildNode tempNode = (ChildNode) children.next();
            if (tempNode.equals(oldChild)) {

                if (this.firstChild == tempNode) {
                    // If this is the first child
                    this.firstChild = null;
                    this.lastChild = null;
                    tempNode.parentNode = null;
                } else if (this.lastChild == tempNode) {
                    // not the first child, but the last child
                    ChildNode prevSib = tempNode.previousSibling;
                    prevSib.nextSibling = null;
                    tempNode.parentNode = null;
                    tempNode.previousSibling = null;
                } else {

                    ChildNode oldDomChild = (ChildNode) oldChild;
                    ChildNode privChild = oldDomChild.previousSibling;

                    privChild.nextSibling = oldDomChild.nextSibling;
                    oldDomChild.nextSibling.previousSibling = privChild;

                    // Remove old child's references to this tree
                    oldDomChild.nextSibling = null;
                    oldDomChild.previousSibling = null;
                }
                // Child found
                childFound = true;
            }
        }

        if (!childFound)
            throw new DOMException(DOMException.NOT_FOUND_ERR,
                    DOMMessageFormatter.formatMessage(
                            DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR",
                            null));

        return oldChild;
    }

    private boolean isAncestor(Node newNode) {

        // TODO isAncestor
        return true;
    }

    public Node cloneNode(boolean deep) {

        ParentNode newnode = (ParentNode) super.cloneNode(deep);

        // set owner document
        newnode.ownerNode = ownerNode;

        // Need to break the association w/ original kids
        newnode.firstChild = null;
        newnode.lastChild = null;

        // Then, if deep, clone the kids too.
        if (deep) {
            for (ChildNode child = firstChild; child != null; 
                    child = child.nextSibling) {
                newnode.appendChild(child.cloneNode(true));
            }
        }

        return newnode;

    }
}
