/*
 * 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.ode.il;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.transform.Source;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMContainer;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.OMNode;
import org.apache.axiom.om.OMText;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.ode.utils.DOMUtils;
import org.apache.ode.utils.NSContext;
import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Document;
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;
import org.xml.sax.InputSource;

/**
 * Utility methods to convert from/to AxiOM and DOM.
 */
public class OMUtils {

    private static Logger __log = LoggerFactory.getLogger(OMUtils.class);

    public static OMElement getFirstChildWithName(OMElement parent, String name) {
        if (parent == null)
            throw new IllegalArgumentException("null parent");
        if (name == null)
            throw new IllegalArgumentException("null name");
        for (Iterator it = parent.getChildElements(); it.hasNext();) {
            OMElement e = (OMElement) it.next();
            if (name.equals(e.getQName().getLocalPart())) return e;
        }
        return null;
    }

    public static Element toDOM(OMElement element) {
        return toDOM(element, DOMUtils.newDocument());
    }

    public static Element toDOM(OMElement element, Document doc) {
        return toDOM(element,doc,true);
    }

    @SuppressWarnings("unchecked")
    public static Element toDOM(OMElement element, Document doc, boolean deepNS) {
        //
        //  Fix regarding lost qnames on response of invoke activity:
        //    * copy an element including its prefix.
        //    * add all namespase attributes.
        //
        String domElementNsUri = element.getQName().getNamespaceURI();
        String domElementQName;
        if (element.getQName().getPrefix() == null || element.getQName().getPrefix().trim().length() == 0) {
            domElementQName = element.getQName().getLocalPart();
        } else {
            domElementQName = element.getQName().getPrefix() + ":" + element.getQName().getLocalPart();
        }
        if (__log.isTraceEnabled())
            __log.trace("toDOM: creating element with nsUri=" + domElementNsUri
                    + " qname=" + domElementQName
                    + " from omElement, name=" + element.getLocalName());

        final Element domElement = doc.createElementNS(
                domElementNsUri,
                domElementQName);
        

        if (deepNS) {
            NSContext nscontext = new NSContext();
            buildNScontext(nscontext, element);
            DOMUtils.injectNamespacesWithAllPrefixes(domElement,nscontext);
        } else {
            if (element.getAllDeclaredNamespaces() != null) {
                for (Iterator<OMNamespace> i = element.getAllDeclaredNamespaces(); i.hasNext(); ) {
                    OMNamespace omns = i.next();
                    if (omns.getPrefix().equals(""))
                        domElement.setAttributeNS(DOMUtils.NS_URI_XMLNS, "xmlns", omns.getNamespaceURI() == null ? "" : omns.getNamespaceURI());
                    else
                        domElement.setAttributeNS(DOMUtils.NS_URI_XMLNS, "xmlns:"+ omns.getPrefix(), omns.getNamespaceURI());
                }

            }
        }
        if (__log.isTraceEnabled())
            __log.trace("toDOM: created root element (deepNS=" + deepNS + "): " + DOMUtils.domToString(domElement));

        for (Iterator i = element.getAllAttributes(); i.hasNext();) {
            final OMAttribute attr = (OMAttribute) i.next();
            Attr newAttr;
            if (attr.getNamespace() != null) newAttr = doc.createAttributeNS(attr.getNamespace().getNamespaceURI(), attr.getLocalName());
            else newAttr = doc.createAttributeNS(null,attr.getLocalName());

            newAttr.appendChild(doc.createTextNode(attr.getAttributeValue()));
            domElement.setAttributeNodeNS(newAttr);

            // Case of qualified attribute values, we're forced to add corresponding namespace declaration manually...
            int colonIdx = attr.getAttributeValue().indexOf(":");
            if (colonIdx > 0) {
                OMNamespace attrValNs = element.findNamespaceURI(attr.getAttributeValue().substring(0, colonIdx));
                if (attrValNs != null)
                    domElement.setAttributeNS(DOMUtils.NS_URI_XMLNS, "xmlns:"+ attrValNs.getPrefix(), attrValNs.getNamespaceURI());
            }
        }

        for (Iterator<OMNode> i = element.getChildren(); i.hasNext();) {
            OMNode omn = i.next();

            switch (omn.getType()) {
            case OMNode.CDATA_SECTION_NODE:
                domElement.appendChild(doc.createCDATASection(((OMText)omn).getText()));
                break;
            case OMNode.TEXT_NODE:
                domElement.appendChild(doc.createTextNode(((OMText)omn).getText()));
                break;
            case OMNode.ELEMENT_NODE:
                domElement.appendChild(toDOM((OMElement)omn,doc, false));
                break;
            }

        }

        return domElement;

    }

    @SuppressWarnings("unchecked")
    private static void buildNScontext(NSContext nscontext, OMElement element) {
        if (element == null)
            return;

        if (element.getParent() instanceof OMElement)
            buildNScontext(nscontext, (OMElement) element.getParent());

        if (element.getAllDeclaredNamespaces() != null)
            for (Iterator<OMNamespace> i=element.getAllDeclaredNamespaces(); i.hasNext(); ){
                OMNamespace omn = i.next();
                nscontext.register(omn.getPrefix(), omn.getNamespaceURI());
            }

        if (element.getDefaultNamespace() != null)
            nscontext.register("", element.getDefaultNamespace().getNamespaceURI());
    }

    public static OMElement toOM(Element src, OMFactory omf) {
        return toOM(src,omf,null);
    }

    public static OMElement toOM(Element src, OMFactory omf, OMContainer parent) {
        OMNamespace namespace = null;

        String srcPrefix = src.getPrefix();
        String srcNamespaceURI = src.getNamespaceURI();

        //AXIOM 1.2.13 doesn't allow setting of default namespace unless a namespace has been associated with the OMElement at object creation,
        //hence create the namespace first and use it during OMElement creation.
        //Avoid using declareDefaultNamespace() as it's found to be adding an empty namespaceURI in some cases.
        if (srcNamespaceURI != null) {

            //if no prefix then it's default namespace
            if(srcPrefix == null) srcPrefix = "";

            namespace = omf.createOMNamespace(srcNamespaceURI, srcPrefix);
        }

        OMElement omElement = parent == null ? omf.createOMElement(src.getLocalName(), namespace) :
        omf.createOMElement(src.getLocalName(), namespace, parent);

        if (parent == null) {
            NSContext nscontext = DOMUtils.getMyNSContext(src);
            injectNamespaces(omElement,nscontext.toMap(),omf);
        } else {
            Map<String,String> nss = DOMUtils.getMyNamespaces(src);
            injectNamespaces(omElement, nss,omf);
        }

        NamedNodeMap attrs = src.getAttributes();
        for (int i = 0; i <attrs.getLength(); ++i) {
            Attr attr = (Attr)attrs.item(i);
            if (attr.getLocalName().equals("xmlns")
                    || (attr.getNamespaceURI() != null && attr.getNamespaceURI().equals(DOMUtils.NS_URI_XMLNS)))
                continue;
            OMNamespace attrOmNs = null;
            String attrNs = attr.getNamespaceURI();
            String attrPrefix = attr.getPrefix();
            if (attrNs != null)
                attrOmNs = omElement.findNamespace(attrNs,null);
            if (attrOmNs == null && attrPrefix != null)
                attrOmNs = omElement.findNamespace(null, attrPrefix);
            omElement.addAttribute(attr.getLocalName(), attr.getValue(), attrOmNs);
        }

        NodeList children = src.getChildNodes();
        for (int i = 0 ; i < children.getLength(); ++i) {
            Node n = children.item(i);

            switch (n.getNodeType()) {
            case Node.CDATA_SECTION_NODE:
                omElement.addChild(omf.createOMText(((CDATASection)n).getTextContent(),XMLStreamConstants.CDATA));
                break;
            case Node.TEXT_NODE:
                omElement.addChild(omf.createOMText(((Text)n).getTextContent(),XMLStreamConstants.CHARACTERS));
                break;
            case Node.ELEMENT_NODE:
                toOM((Element)n,omf,omElement);
                break;
            }

        }

        return omElement;
    }


    private static void injectNamespaces(OMElement omElement, Map<String,String> nscontext,OMFactory omf) {
        for (String prefix : nscontext.keySet()) {
            String uri = nscontext.get(prefix);
            if (prefix.equals(""))
                omElement.declareNamespace(omf.createOMNamespace(uri, ""));
            else
                omElement.declareNamespace(uri, prefix);
        }
    }

    /**
     * Axiom is supposed to handle this properly however this method is buggy and doesn't work (whereas setting a QName as text
     * works).
     *
     * @param elmt
     * @return text qname
     */
    public static QName getTextAsQName(OMElement elmt) {
        QName qname = elmt.getTextAsQName();
        // The getTextAsQName is buggy, it sometimes return the full text without extracting namespace
        if (qname == null || qname.getNamespaceURI().length() == 0) {
            int colonIdx = elmt.getText().indexOf(":");
            String localpart = elmt.getText().substring(colonIdx + 1, elmt.getText().length());
            String prefix = elmt.getText().substring(0, colonIdx);
            String ns = elmt.findNamespaceURI(prefix).getNamespaceURI();
            qname = new QName(ns, localpart, prefix);
        }
        return qname;
    }

    /**
     * Parse an XML document located using an {@link InputSource} using the
     * pooled document builder.
     */
    public static OMElement toOM(Source inputSource) throws IOException {
        Document doc = DOMUtils.sourceToDOM(inputSource);
        return toOM(doc.getDocumentElement(), OMAbstractFactory.getOMFactory());
    }

}
