package com.r11.tools.xml;

import net.sf.saxon.om.NamespaceMap;
import net.sf.saxon.s9api.XPathCompiler;
import net.sf.saxon.s9api.XdmNode;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 * Handler for saxon namespace scan engine.
 * All found namespaces are stored within {@link #namespaceMap}
 * @author Wojciech Czop
 */
public class NewNamespaceResolver {
    private static final Logger LOG = LogManager.getLogger("NewNamespaceResolver");

    private NamespaceMap namespaceMap;

    /**
     * Initializes {@link #namespaceMap} with namespace values
     * @param doc dom structure object
     * @return map of namespaces
     */

    // TODO: Closer inspection. Return value is never used according to IntelliJ
    //
    public NamespaceMap process(XdmNode doc) {
        namespaceMap = NamespaceMap.emptyMap();
        //        TODO: remove
        for (XdmNode tmp : doc.children()) {
            extractNamespace(tmp);
        }
//        end
        return namespaceMap;
    }

    /**
     * Iterates through {@link #namespaceMap} and declares namespaces in {@link XPathCompiler}
     * @param compiler compiler used to compile xpath statements
     */
    public void exportNamespaces(XPathCompiler compiler){
        namespaceMap.forEach(namespaceBinding -> compiler.declareNamespace(namespaceBinding.getPrefix(), namespaceBinding.getURI()));
    }

    /**
     * Uses recurrency to dive deep dom structure and appends {@link #namespaceMap} with every found namespace
     * @param node dom structure object
     */
    private void extractNamespace(XdmNode node) {
        NamespaceMap tmp;
        if ((tmp = node.getUnderlyingNode().getAllNamespaces()) != null) {
            namespaceMap = namespaceMap.putAll(tmp);
        }
        if (node.children().iterator().hasNext()) {

            for (XdmNode rNode : node.children()) {
                if (rNode.getUnderlyingNode().getPrefix().isEmpty() && !rNode.getParent().getUnderlyingNode().getPrefix().isEmpty()) {
                    LOG.warn("Missing prefix. Parent has " + rNode.getParent().getUnderlyingNode().getPrefix() + ", but child has none");
                }

                extractNamespace(rNode);
            }
        }
    }
}
