/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.internal.oxm.record;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
import org.eclipse.persistence.internal.oxm.Constants;
import org.eclipse.persistence.internal.oxm.NamespaceResolver;
import org.eclipse.persistence.internal.oxm.Unmarshaller;
import org.eclipse.persistence.internal.oxm.mappings.Login;
import org.eclipse.persistence.internal.oxm.mappings.Mapping;
import org.eclipse.persistence.internal.oxm.record.namespaces.StackUnmarshalNamespaceResolver;
import org.eclipse.persistence.oxm.documentpreservation.DocumentPreservationPolicy;

import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Comment;
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;
import org.xml.sax.SAXException;
import org.xml.sax.ext.Locator2;

/**
 *  INTERNAL:
 *  <p><b>Purpose:</b> An implementation of XMLReader for parsing DOM Nodes into SAX events.
 *  <p><b>Responsibilities:</b><ul>
 *  <li>Walk the DOM tree and report sax events to the provided content handler</li>
 *  <li>Report lexical events to the lexical handler if it's provided</li>
 *  <li>Listen for callbacks from the Mapping-Level framework to handle caching nodes for document preservation</li>
 *  </ul>
 *
 */
public class DOMReader extends XMLReaderAdapter {

    private Node currentNode;
    private DocumentPreservationPolicy docPresPolicy;

    public DOMReader() {
        super();
    }

    public DOMReader(Unmarshaller xmlUnmarshaller) {
        super(xmlUnmarshaller);
    }

    @Override
    public void parse(InputSource input) throws SAXException {
        if(input instanceof DOMInputSource) {
            Node node = ((DOMInputSource) input).getNode();
            if(contentHandler != null && contentHandler.getClass() == SAXUnmarshallerHandler.class){
                ((SAXUnmarshallerHandler)contentHandler).setUnmarshalNamespaceResolver(new StackUnmarshalNamespaceResolver());
            }
            parse(node);
        }
    }

    public void parse (Node node, String newURI, String newName) throws SAXException {
        if(null == contentHandler) {
            return;
        }
        Element rootNode = null;
        if(node.getNodeType() == Node.DOCUMENT_NODE) {
            rootNode = ((Document)node).getDocumentElement();
        }  else {
            rootNode = (Element)node;
        }
        if(rootNode == null) {
            return;
        }
        processParentNamespaces(rootNode);
        startDocument();
        setupLocator(rootNode.getOwnerDocument());

        reportElementEvents(rootNode, newURI, newName);


        endDocument();
    }

    public void parse (Node node) throws SAXException {
        parse(node, null, null);
    }

    /**
     * Process namespace declarations on parent elements if not the root.
     * For each parent node from current to root push each onto a stack,
     * then pop each off, calling startPrefixMapping for each XMLNS
     * attribute.  Using a stack ensures that the parent nodes are
     * processed top down.
     *
     * @param element
     */
    protected void processParentNamespaces(Element element) throws SAXException {
        Node parent = element.getParentNode();
        // If we're already at the root, do nothing
        if (parent != null && parent.getNodeType() == Node.DOCUMENT_NODE) {
            return;
        }
        // Add each parent node up to root to the stack
        List<Node> parentElements = new ArrayList<>();
        while (parent != null && parent.getNodeType() != Node.DOCUMENT_NODE) {
            parentElements.add(parent);
            parent = parent.getParentNode();
        }
        // Pop off each node and call startPrefixMapping for each XMLNS attribute
        for (Iterator stackIt = parentElements.iterator(); stackIt.hasNext(); ) {
            NamedNodeMap attrs = parentElements.remove(parentElements.size() - 1).getAttributes();
            if (attrs != null) {
                for (int i=0, length = attrs.getLength(); i < length; i++) {
                    Attr next = (Attr)attrs.item(i);
                    String attrPrefix = next.getPrefix();
                    if (attrPrefix != null && attrPrefix.equals(javax.xml.XMLConstants.XMLNS_ATTRIBUTE)) {
                        contentHandler.startPrefixMapping(next.getLocalName(), next.getValue());
                    }
                }
            }
        }
    }
    protected void reportElementEvents(Element elem) throws SAXException {
        reportElementEvents(elem, null, null);
    }
    protected void reportElementEvents(Element elem, String newUri, String newName) throws SAXException {
        this.currentNode = elem;
        IndexedAttributeList attributes = buildAttributeList(elem);
        String namespaceUri = null;
        String qname = null;
        String lname = null;

        if(newName == null){
            // Handle null local name
            lname = elem.getLocalName();
            if (lname == null) {
                // If local name is null, use the node name
                lname = elem.getNodeName();
                qname = lname;
                handlePrefixedAttribute(elem);
            } else {
                qname = getQName(elem);
            }
            namespaceUri = elem.getNamespaceURI();
            if(namespaceUri == null) {
                namespaceUri = "";
            }
        } else {
            namespaceUri = newUri;
            lname = newName;
            qname = newName;
            if(namespaceUri != null && isNamespaceAware()){
                NamespaceResolver tmpNR = new NamespaceResolver();
                tmpNR.setDOM(elem);

                 String prefix = tmpNR.resolveNamespaceURI(namespaceUri);
                 if(prefix == null || prefix.length() == 0){
                     String defaultNamespace = elem.getAttributeNS(javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI, javax.xml.XMLConstants.XMLNS_ATTRIBUTE);

                     if(defaultNamespace == null){
                         prefix = tmpNR.generatePrefix();
                         contentHandler.startPrefixMapping(prefix, namespaceUri);
                     }else if(defaultNamespace != namespaceUri){
                         prefix = tmpNR.generatePrefix();
                         contentHandler.startPrefixMapping(prefix, namespaceUri);
                     }else{
                         prefix = Constants.EMPTY_STRING;
                     }
                 }

                 if(prefix != null && prefix.length() >0){
                    qname = prefix + Constants.COLON + qname;
                 }
            }

        }



        contentHandler.startElement(namespaceUri, lname, qname, attributes);

        handleChildNodes(elem.getChildNodes());
        contentHandler.endElement(namespaceUri, lname, qname);
        endPrefixMappings(elem);
    }

    protected IndexedAttributeList buildAttributeList(Element elem) throws SAXException {
        IndexedAttributeList attributes = new IndexedAttributeList();
        NamedNodeMap attrs = elem.getAttributes();
        for (int i = 0, length = attrs.getLength(); i < length; i++) {
            Attr next = (Attr)attrs.item(i);
            String attrPrefix = next.getPrefix();
            if(attrPrefix != null && attrPrefix.equals(javax.xml.XMLConstants.XMLNS_ATTRIBUTE)) {
                contentHandler.startPrefixMapping(next.getLocalName(), next.getValue());
                // Handle XMLNS prefixed attributes
                handleNewNamespaceDeclaration(elem, next.getLocalName(), next.getValue());

            } else if(attrPrefix == null) {
                String name = next.getLocalName();
                if(name == null) {
                    name = next.getNodeName();
                }
                if(name != null && name.equals(javax.xml.XMLConstants.XMLNS_ATTRIBUTE)) {
                    contentHandler.startPrefixMapping(Constants.EMPTY_STRING, next.getValue());
                    handleNewNamespaceDeclaration(elem, Constants.EMPTY_STRING, next.getValue());
                }
            }
            if(next.getNamespaceURI() != null && next.getNamespaceURI().equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI) && next.getLocalName().equals("type")) {
                handleXsiTypeAttribute(next);
            }
            attributes.addAttribute(next);
        }
        return attributes;
    }

    protected void endPrefixMappings(Element elem) throws SAXException {
        NamedNodeMap attrs = elem.getAttributes();
        for(int i = 0, numOfAtts = attrs.getLength(); i < numOfAtts; i++) {
            Attr next = (Attr)attrs.item(i);
            String attrPrefix = next.getPrefix();
            if (attrPrefix != null && attrPrefix.equals(javax.xml.XMLConstants.XMLNS_ATTRIBUTE)) {
                contentHandler.endPrefixMapping(next.getLocalName());
            } else if(attrPrefix == null) {
                String name = next.getLocalName();
                if(name == null) {
                    name = next.getNodeName();
                }
                if(javax.xml.XMLConstants.XMLNS_ATTRIBUTE.equals(name)) {
                    contentHandler.endPrefixMapping(Constants.EMPTY_STRING);
                }
            }
        }
    }

    protected String getQName(Element elem) throws SAXException {
        handlePrefixedAttribute(elem);
        String prefix = elem.getPrefix();
        if (prefix != null && prefix.length() > 0) {
            String qname = prefix + Constants.COLON + elem.getLocalName();
            return qname;
        } else {
            return elem.getLocalName();
        }
    }

    protected void handleNewNamespaceDeclaration(Element elem, String emptyString, String value) {
        // DO NOTHING
    }

    protected void handleXsiTypeAttribute(Attr attr) throws SAXException {

    }

    /**
     * Handle prefixed attribute - may need to declare the namespace
     * URI locally.
     *
     */
    protected void handlePrefixedAttribute(Element elem) throws SAXException {
        // DO NOTHING
    }

    protected void handleChildNodes(NodeList children) throws SAXException {
        Node nextChild = null;
        if(children.getLength() > 0) {
            nextChild = children.item(0);
        }
        while(nextChild != null) {
            if(nextChild.getNodeType() == Node.TEXT_NODE) {
                char[] value = nextChild.getNodeValue().toCharArray();
                contentHandler.characters(value, 0, value.length);
            } else if(nextChild.getNodeType() == Node.COMMENT_NODE) {
                char[] value = nextChild.getNodeValue().toCharArray();
                if (lexicalHandler != null) {
                    lexicalHandler.comment(value, 0, value.length);
                }
            } else if(nextChild.getNodeType() == Node.ELEMENT_NODE) {
                Element childElement = (Element)nextChild;
                reportElementEvents(childElement);
            } else if(nextChild.getNodeType() == Node.CDATA_SECTION_NODE) {
                if(lexicalHandler != null) {
                    lexicalHandler.startCDATA();
                }
                char[] value = ((CDATASection)nextChild).getData().toCharArray();
                contentHandler.characters(value, 0, value.length);
                if(lexicalHandler != null) {
                    lexicalHandler.endCDATA();
                }
            }
            nextChild = nextChild.getNextSibling();
        }
    }

    /**
     * Trigger an endDocument event on the contenthandler.
     */
    protected void endDocument() throws SAXException {
        contentHandler.endDocument();
    }

    /**
     * Trigger a startDocument event on the contenthandler.
     */
    protected void startDocument() throws SAXException {
        contentHandler.startDocument();
    }

    /**
     * An EclipseLink specific callback into the Reader. This allows Objects to be
     * associated with the XML Nodes they came from.
     */
    @Override
    public void newObjectEvent(Object object, Object parent, Mapping selfRecordMapping) {
        docPresPolicy.addObjectToCache(object, currentNode, selfRecordMapping);
    }

    @Override
    public Object getCurrentObject(CoreAbstractSession session, Mapping selfRecordMapping) {
        //if session == null then this is a marshal of a non-root
        //if docPres policy is null, then we never unmarshalled anything, and can
        //safely return null;
        if(session == null && docPresPolicy == null) {
            return null;
        }
        if(docPresPolicy == null) {
            Login login = (Login)session.getDatasourceLogin();
            docPresPolicy = login.getDocumentPreservationPolicy();
        }
        return docPresPolicy.getObjectForNode(currentNode, selfRecordMapping);
    }

    public DocumentPreservationPolicy getDocPresPolicy() {
        return docPresPolicy;
    }

    public void setDocPresPolicy(DocumentPreservationPolicy policy) {
        docPresPolicy = policy;
    }

    protected void setupLocator(Document doc) {
        LocatorImpl locator = new LocatorImpl();
        try {
            locator.setEncoding(doc.getXmlEncoding());
            locator.setXMLVersion(doc.getXmlVersion());
        } catch(Exception ex) {
            //if unable to invoke these methods, just return and don't invoke
            return;
        }
        this.contentHandler.setDocumentLocator(locator);
    }

    // Made static final for performance reasons.
    /**
     * Implementation of Attributes - used to pass along a given node's attributes
     * to the startElement method of the reader's content handler.
     */
    protected static final class IndexedAttributeList implements org.xml.sax.Attributes {

        private List<Attr> attrs;

        public IndexedAttributeList() {
            attrs = new ArrayList();
        }

        public void addAttribute(Attr attribute) {
            attrs.add(attribute);
        }

        @Override
        public String getQName(int index) {
            try {
                Attr item = attrs.get(index);
                if (item.getName() != null) {
                    return item.getName();
                }
                return Constants.EMPTY_STRING;
            } catch (IndexOutOfBoundsException iobe) {
                return null;
            }
        }

        @Override
        public String getType(String namespaceUri, String localName) {
            return Constants.CDATA;
        }

        @Override
        public String getType(int index) {
            return Constants.CDATA;
        }

        @Override
        public String getType(String qname) {
            return Constants.CDATA;
        }

        @Override
        public int getIndex(String qname) {
            for (int i=0, size = attrs.size(); i<size; i++) {
                if (attrs.get(i).getName().equals(qname)) {
                    return i;
                }
            }
            return -1;
        }

        @Override
        public int getIndex(String uri, String localName) {
            for (int i=0, size = attrs.size(); i<size; i++) {
                Attr item = attrs.get(i);
                try {
                    if (item.getNamespaceURI().equals(uri) && item.getLocalName().equals(localName)) {
                        return i;
                    }
                } catch (Exception x) {}
            }
            return -1;
        }

        @Override
        public int getLength() {
            return attrs.size();
        }

        @Override
        public String getLocalName(int index) {
            try {
                Attr item = attrs.get(index);
                if (item.getLocalName() != null) {
                    return item.getLocalName();
                }
                return item.getName();
            } catch (IndexOutOfBoundsException iobe) {
                return null;
            }
        }

        @Override
        public String getURI(int index) {
            String uri = attrs.get(index).getNamespaceURI();
            if(uri == null) {
                uri = Constants.EMPTY_STRING;
            }
            return uri;
        }

        @Override
        public String getValue(int index) {
            return (attrs.get(index)).getValue();
        }

        @Override
        public String getValue(String qname) {
            for (int i=0, size = attrs.size(); i<size; i++) {
                Attr item = attrs.get(i);
                if (item.getName().equals(qname)) {
                    return item.getValue();
                }
            }
            return null;
        }

        @Override
        public String getValue(String uri, String localName) {
            for (int i=0, size = attrs.size(); i<size; i++) {
                Attr item = attrs.get(i);
                if (item != null) {
                    String itemNS = item.getNamespaceURI();
                    // Need to handle null/empty URI
                    if (item.getNamespaceURI() == null) {
                        itemNS = Constants.EMPTY_STRING;
                    }

                    String itemName = item.getLocalName();
                    if(itemName == null){
                        itemName = item.getNodeName();
                    }
                    if ((itemNS.equals(uri)) && (itemName != null && itemName.equals(localName))) {
                        return item.getValue();
                    }
                }
            }
            return null;
        }
    }

    // Made static final for performance reasons.
    protected static final class LocatorImpl implements Locator2 {

        private String encoding;
        private String version;

        public LocatorImpl() {
            encoding = "UTF-8";
            version = "1.0";
        }

        @Override
        public String getEncoding() {
            return encoding;
        }

        @Override
        public int getColumnNumber() {
            //not supported here
            return 0;
        }

        @Override
        public String getSystemId() {
            return Constants.EMPTY_STRING;
        }

        @Override
        public String getPublicId() {
            return Constants.EMPTY_STRING;
        }

        @Override
        public String getXMLVersion() {
            return version;
        }

        @Override
        public int getLineNumber() {
            //not supported
            return 0;
        }

        protected void setEncoding(String enc) {
            this.encoding = enc;
        }

        protected void setXMLVersion(String xmlVersion) {
            this.version = xmlVersion;
        }

    }

}
