/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.OMComment;
import org.apache.axiom.om.OMDocType;
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.OMProcessingInstruction;
import org.apache.axiom.om.OMSourcedElement;
import org.apache.axiom.om.OMText;
import org.apache.axiom.om.OMXMLParserWrapper;
import org.apache.axiom.om.OMXMLStreamReaderConfiguration;
import org.apache.axiom.om.impl.OMContainerEx;
import org.apache.axiom.om.impl.OMNodeEx;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axiom.om.impl.common.OMChildrenLocalNameIterator;
import org.apache.axiom.om.impl.common.OMChildrenNamespaceIterator;
import org.apache.axiom.om.impl.common.OMChildrenQNameIterator;
import org.apache.axiom.om.impl.common.OMDescendantsIterator;
import org.apache.axiom.om.impl.common.OMStAXWrapper;
import org.apache.axiom.om.impl.dom.factory.OMDOMFactory;
import org.apache.axiom.om.impl.jaxp.OMSource;
import org.apache.axiom.om.impl.traverse.OMChildrenIterator;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.sax.SAXSource;

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 OMXMLParserWrapper getBuilder() {
        return this.builder;
    }

    public void addChild(OMNode omNode) {
        if (omNode.getOMFactory() instanceof OMDOMFactory) {
            Node domNode = (Node) omNode;
            if (this.ownerNode != null && !domNode.getOwnerDocument().equals(this.ownerNode)) {
                this.appendChild(this.ownerNode.importNode(domNode, true));
            } else {
                this.appendChild(domNode);
            }
        } else {
            addChild(importNode(omNode));
        }

    }

    public void buildNext() {
        if (builder != null) {
            builder.next();
        }
    }

    public Iterator getChildren() {
        return new OMChildrenIterator(getFirstOMChild());
    }

    public Iterator getDescendants(boolean includeSelf) {
        return new OMDescendantsIterator(this, includeSelf);
    }

    /**
     * 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);
    }
    
    public Iterator getChildrenWithLocalName(String localName) {
        return new OMChildrenLocalNameIterator(getFirstOMChild(),
                                               localName);
    }


    public Iterator getChildrenWithNamespaceURI(String uri) {
        return new OMChildrenNamespaceIterator(getFirstOMChild(),
                                               uri);
    }

    /**
     * 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 (OMNode)firstChild;
    }

    public OMNode getFirstOMChildIfAvailable() {
        return (OMNode)firstChild;
    }

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

    /**
     * Forcefully set the last child
     * @param omNode
     */
    public void setLastChild(OMNode omNode) {
        this.lastChild = (ChildNode) omNode;
    }

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

    public NodeList getChildNodes() {
        if (!this.done) {
            this.build();
        }
        return new NodeListImpl() {
            protected Iterator getIterator() {
                return getChildren();
            }
        };
    }

    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,
                                           DOMException.HIERARCHY_REQUEST_ERR, null));
        }

        if (newDomChild.parentNode != null && newDomChild.ownerNode == this.ownerNode) {
            //If the newChild is already in the tree remove it
            newDomChild.parentNode.removeChild(newDomChild);
        }

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

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

        if (this instanceof Document) {
            if (newDomChild instanceof ElementImpl) {
                if (((DocumentImpl) this).getOMDocumentElement(false) != null) {
                    // Throw exception since there cannot be two document elements
                    throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
                                           DOMMessageFormatter.formatMessage(
                                                   DOMMessageFormatter.DOM_DOMAIN,
                                                   DOMException.HIERARCHY_REQUEST_ERR, null));
                }
                if (newDomChild.parentNode == null) {
                    newDomChild.parentNode = this;
                }
            } else if (!(newDomChild instanceof CommentImpl
                    || newDomChild instanceof ProcessingInstructionImpl
                    || newDomChild instanceof DocumentFragmentImpl
                    || newDomChild instanceof DocumentTypeImpl)) {
                throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
                        DOMMessageFormatter.formatMessage(
                                DOMMessageFormatter.DOM_DOMAIN,
                                DOMException.HIERARCHY_REQUEST_ERR, null));
            }
        }
        
        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;
            }
        } 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;
                            
                            ChildNode child = docFrag.firstChild;
                            while (child != null) {
                                child.parentNode = this;
                                child = child.nextSibling;
                            }
                            
                            this.firstChild = docFrag.firstChild;
                            docFrag.lastChild.nextSibling = refDomChild;
                            refDomChild.previousSibling =
                                    docFrag.lastChild.nextSibling;

                            docFrag.firstChild = null;
                            docFrag.lastChild = null;
                        } 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;

                            ChildNode child = docFrag.firstChild;
                            while (child != null) {
                                child.parentNode = this;
                                child = child.nextSibling;
                            }
                            
                            previousNode.nextSibling = docFrag.firstChild;
                            docFrag.firstChild.previousSibling = previousNode;

                            docFrag.lastChild.nextSibling = refDomChild;
                            refDomChild.previousSibling = docFrag.lastChild;

                            docFrag.firstChild = null;
                            docFrag.lastChild = null;
                        } 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,
                                               DOMException.NOT_FOUND_ERR, null));
            }

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

        }
        
        if (!newDomChild.isComplete() && !(newDomChild instanceof OMSourcedElement)) {
            setComplete(false);
        }
        
        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 (newChild == null) {
            return this.removeChild(oldChild);
        }

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

        if (newDomChild != null &&
                //This is the case where this is an Element in the document
                (this.ownerNode != null && !this.ownerNode.equals(newDomChild.ownerNode)) ||
                //This is the case where this is the Document itself
                (this.ownerNode == null && !this.equals(newDomChild.ownerNode))) {
            throw new DOMException(DOMException.WRONG_DOCUMENT_ERR,
                                   DOMMessageFormatter.formatMessage(
                                           DOMMessageFormatter.DOM_DOMAIN,
                                           DOMException.WRONG_DOCUMENT_ERR, null));
        }

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

        Iterator children = this.getChildren();
        boolean found = false;
        while (!found && children.hasNext()) {
            ChildNode tempNode = (ChildNode) children.next();
            if (tempNode.equals(oldChild)) {
                if (newChild instanceof DocumentFragmentImpl) {
                    DocumentFragmentImpl docFrag =
                            (DocumentFragmentImpl) newDomChild;
                    ChildNode child = (ChildNode) docFrag.getFirstChild();
                    this.replaceChild(child, oldChild);
                    
                    //set the parent of all kids to me
                    while(child != null) {
                        child.parentNode = this;
                        child = child.nextSibling;
                    }

                    this.lastChild = (ChildNode)docFrag.getLastChild();
                    
                } else {
                    if (this.firstChild == oldDomChild) {

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

                    }

                    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, DOMException.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,
                                           DOMException.NO_MODIFICATION_ALLOWED_ERR, null));
        }

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

                if (this.firstChild == tempNode) {
                    // If this is the first child
                    ChildNode nextSib = tempNode.nextSibling;
                    this.firstChild = nextSib;
                    if (nextSib == null) {
                        this.lastChild = null;
                    } else {
                        nextSib.previousSibling = null;
                    }
                    tempNode.parentNode = null;
                    tempNode.nextSibling = null;
                } else if (this.lastChild == tempNode) {
                    // not the first child, but the last child
                    ChildNode prevSib = tempNode.previousSibling;
                    this.lastChild = prevSib;
                    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, DOMException.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;
    }

    /**
     * This method is intended only to be used by Axiom intenals when merging Objects from different
     * Axiom implementations to the DOOM implementation.
     *
     * @param child
     */
    protected OMNode importNode(OMNode child) {
        int type = child.getType();
        switch (type) {
            case (OMNode.ELEMENT_NODE): {
                OMElement childElement = (OMElement) child;
                OMElement newElement = (new StAXOMBuilder(this.factory,
                                                          childElement.getXMLStreamReader()))
                        .getDocumentElement();
                newElement.build();
                return (OMNode) this.ownerNode.importNode((Element) newElement,
                                                          true);
            }
            case (OMNode.TEXT_NODE): {
                OMText importedText = (OMText) child;
                OMText newText;
                if (importedText.isBinary()) {
                    boolean isOptimize = importedText.isOptimized();
                    newText = this.factory.createOMText(importedText
                            .getDataHandler(), isOptimize);
                } else if (importedText.isCharacters()) {
                    newText = new TextImpl((DocumentImpl) this.getOwnerDocument(),
                                           importedText.getTextCharacters(), this.factory);
                } else {
                    newText = new TextImpl((DocumentImpl) this.getOwnerDocument(),
                                           importedText.getText(), this.factory);
                }
                return newText;
            }

            case (OMNode.PI_NODE): {
                OMProcessingInstruction importedPI = (OMProcessingInstruction) child;
                OMProcessingInstruction newPI = this.factory
                        .createOMProcessingInstruction(this,
                                                       importedPI.getTarget(),
                                                       importedPI.getValue());
                return newPI;
            }
            case (OMNode.COMMENT_NODE): {
                OMComment importedComment = (OMComment) child;
                OMComment newComment = this.factory.createOMComment(this,
                                                                    importedComment.getValue());
                DocumentImpl doc;
                if (this instanceof DocumentImpl) {
                    doc = (DocumentImpl) this;
                } else {
                    doc = (DocumentImpl) getOwnerDocument();
                }
                newComment = new CommentImpl(doc, importedComment.getValue(),
                                             this.factory);
                return newComment;
            }
            case (OMNode.DTD_NODE): {
                OMDocType importedDocType = (OMDocType) child;
                OMDocType newDocType = this.factory.createOMDocType(this,
                                                                    importedDocType.getValue());
                return newDocType;
            }
            default: {
                throw new UnsupportedOperationException(
                        "Not Implemented Yet for the given node type");
            }
        }
    }
    
    public String getTextContent() throws DOMException {
        Node child = getFirstChild();
        if (child != null) {
            Node next = child.getNextSibling();
            if (next == null) {
                return hasTextContent(child) ? ((NodeImpl)child).getTextContent() : "";
            }
            StringBuffer buf = new StringBuffer();
            getTextContent(buf);
            return buf.toString();
        } else {
            return "";
        }
    }

    void getTextContent(StringBuffer buf) throws DOMException {
        Node child = getFirstChild();
        while (child != null) {
            if (hasTextContent(child)) {
                ((NodeImpl)child).getTextContent(buf);
            }
            child = child.getNextSibling();
        }
    }
    
    // internal method returning whether to take the given node's text content
    private static boolean hasTextContent(Node child) {
        return child.getNodeType() != Node.COMMENT_NODE &&
            child.getNodeType() != Node.PROCESSING_INSTRUCTION_NODE /* &&
            (child.getNodeType() != Node.TEXT_NODE ||
             ((TextImpl) child).isIgnorableWhitespace() == false)*/;
    }
    
    public void setTextContent(String textContent) throws DOMException {
        // get rid of any existing children
        // TODO: there is probably a better way to remove all children
        Node child;
        while ((child = getFirstChild()) != null) {
            removeChild(child);
        }
        // create a Text node to hold the given content
        if (textContent != null && textContent.length() != 0) {
            addChild(factory.createOMText(textContent));
        }
    }

    public XMLStreamReader getXMLStreamReaderWithoutCaching() {
        return getXMLStreamReader(false);
    }

    public XMLStreamReader getXMLStreamReader() {
        return getXMLStreamReader(true);
    }

    public XMLStreamReader getXMLStreamReader(boolean cache) {
        return getXMLStreamReader(cache, new OMXMLStreamReaderConfiguration());
    }
    
    public XMLStreamReader getXMLStreamReader(boolean cache, OMXMLStreamReaderConfiguration configuration) {
        if ((builder == null) && !cache) {
            throw new UnsupportedOperationException(
                    "This element was not created in a manner to be switched");
        }
        if (builder != null && builder.isCompleted() && !cache) {
            throw new UnsupportedOperationException(
                    "The parser is already consumed!");
        }
        return new OMStAXWrapper(builder, this, cache, configuration.isPreserveNamespaceContext());
    }

    public SAXSource getSAXSource(boolean cache) {
        return new OMSource(this);
    }

    void notifyChildComplete() {
        if (!this.done && builder == null) {
            Iterator iterator = getChildren();
            while (iterator.hasNext()) {
                OMNode node = (OMNode) iterator.next();
                if (!node.isComplete()) {
                    return;
                }
            }
            this.setComplete(true);
        }
    }

    void normalize(DOMConfigurationImpl config) {
        OMNode child = getFirstOMChild();
        while (child != null) {
            ((NodeImpl)child).normalize(config);
            child = child.getNextOMSibling();
        }
    }
}
