/*
 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
 */
/*
 * 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 com.sun.org.apache.xalan.internal.xsltc.dom;

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.StripFilter;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.BasisLibrary;
import com.sun.org.apache.xml.internal.dtm.Axis;
import com.sun.org.apache.xml.internal.dtm.DTM;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.dtm.DTMManager;
import com.sun.org.apache.xml.internal.dtm.ref.DTMAxisIteratorBase;
import com.sun.org.apache.xml.internal.dtm.ref.DTMAxisIterNodeList;
import com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBase;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import com.sun.org.apache.xml.internal.utils.SuballocatedIntVector;
import java.util.HashMap;
import java.util.Map;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * @author Jacek Ambroziak
 * @author Morten Jorgensen
 * @author Erwin Bolwidt <ejb@klomp.org>
 */
public final class MultiDOM implements DOM {

    private static final int NO_TYPE = DOM.FIRST_TYPE - 2;
    private static final int INITIAL_SIZE = 4;

    private DOM[] _adapters;
    private DOMAdapter _main;
    private DTMManager _dtmManager;
    private int _free;
    private int _size;

    private Map<String, Integer> _documents = new HashMap<>();

    private final class AxisIterator extends DTMAxisIteratorBase {
        // constitutive data
        private final int _axis;
        private final int _type;
        // implementation mechanism
        private DTMAxisIterator _source;
        private int _dtmId = -1;

        public AxisIterator(final int axis, final int type) {
            _axis = axis;
            _type = type;
        }

        public int next() {
            if (_source == null) {
                return(END);
            }
            return _source.next();
        }


        public void setRestartable(boolean flag) {
            if (_source != null) {
                _source.setRestartable(flag);
            }
        }

        public DTMAxisIterator setStartNode(final int node) {
            if (node == DTM.NULL) {
                return this;
            }

            int dom = node >>> DTMManager.IDENT_DTM_NODE_BITS;

            // Get a new source first time and when mask changes
            if (_source == null || _dtmId != dom) {
                if (_type == NO_TYPE) {
                    _source = _adapters[dom].getAxisIterator(_axis);
                } else if (_axis == Axis.CHILD) {
                    _source = _adapters[dom].getTypedChildren(_type);
                } else {
                    _source = _adapters[dom].getTypedAxisIterator(_axis, _type);
                }
            }

            _dtmId = dom;
            _source.setStartNode(node);
            return this;
        }

        public DTMAxisIterator reset() {
            if (_source != null) {
                _source.reset();
            }
            return this;
        }

        public int getLast() {
            if (_source != null) {
                return _source.getLast();
            }
            else {
                return END;
            }
        }

        public int getPosition() {
            if (_source != null) {
                return _source.getPosition();
            }
            else {
                return END;
            }
        }

        public boolean isReverse() {
            return Axis.isReverse(_axis);
        }

        public void setMark() {
            if (_source != null) {
                _source.setMark();
            }
        }

        public void gotoMark() {
            if (_source != null) {
                _source.gotoMark();
            }
        }

        public DTMAxisIterator cloneIterator() {
            final AxisIterator clone = new AxisIterator(_axis, _type);
            if (_source != null) {
                clone._source = _source.cloneIterator();
            }
            clone._dtmId = _dtmId;
            return clone;
        }
    } // end of AxisIterator


    /**************************************************************
     * This is a specialised iterator for predicates comparing node or
     * attribute values to variable or parameter values.
     */
    private final class NodeValueIterator extends DTMAxisIteratorBase {

        private DTMAxisIterator _source;
        private String _value;
        private boolean _op;
        private final boolean _isReverse;
        private int _returnType = RETURN_PARENT;

        public NodeValueIterator(DTMAxisIterator source, int returnType,
                                 String value, boolean op) {
            _source = source;
            _returnType = returnType;
            _value = value;
            _op = op;
            _isReverse = source.isReverse();
        }

        public boolean isReverse() {
            return _isReverse;
        }

        public DTMAxisIterator cloneIterator() {
            try {
                NodeValueIterator clone = (NodeValueIterator)super.clone();
                clone._source = _source.cloneIterator();
                clone.setRestartable(false);
                return clone.reset();
            }
            catch (CloneNotSupportedException e) {
                BasisLibrary.runTimeError(BasisLibrary.ITERATOR_CLONE_ERR,
                                          e.toString());
                return null;
            }
        }


        public void setRestartable(boolean isRestartable) {
            _isRestartable = isRestartable;
            _source.setRestartable(isRestartable);
        }

        public DTMAxisIterator reset() {
            _source.reset();
            return resetPosition();
        }

        public int next() {

            int node;
            while ((node = _source.next()) != END) {
                String val = getStringValueX(node);
                if (_value.equals(val) == _op) {
                    if (_returnType == RETURN_CURRENT)
                        return returnNode(node);
                    else
                        return returnNode(getParent(node));
                }
            }
            return END;
        }

        public DTMAxisIterator setStartNode(int node) {
            if (_isRestartable) {
                _source.setStartNode(_startNode = node);
                return resetPosition();
            }
            return this;
        }

        public void setMark() {
            _source.setMark();
        }

        public void gotoMark() {
            _source.gotoMark();
        }
    }

    public MultiDOM(DOM main) {
        _size = INITIAL_SIZE;
        _free = 1;
        _adapters = new DOM[INITIAL_SIZE];
        DOMAdapter adapter = (DOMAdapter)main;
        _adapters[0] = adapter;
        _main = adapter;
        DOM dom = adapter.getDOMImpl();
        if (dom instanceof DTMDefaultBase) {
            _dtmManager = ((DTMDefaultBase)dom).getManager();
        }

        // %HZ% %REVISIT% Is this the right thing to do here?  In the old
        // %HZ% %REVISIT% version, the main document did not get added through
        // %HZ% %REVISIT% a call to addDOMAdapter, which meant it couldn't be
        // %HZ% %REVISIT% found by a call to getDocumentMask.  The problem is
        // %HZ% %REVISIT% TransformerHandler is typically constructed with a
        // %HZ% %REVISIT% system ID equal to the stylesheet's URI; with SAX
        // %HZ% %REVISIT% input, it ends up giving that URI to the document.
        // %HZ% %REVISIT% Then, any references to document('') are resolved
        // %HZ% %REVISIT% using the stylesheet's URI.
        // %HZ% %REVISIT% MultiDOM.getDocumentMask is called to verify that
        // %HZ% %REVISIT% a document associated with that URI has not been
        // %HZ% %REVISIT% encountered, and that method ends up returning the
        // %HZ% %REVISIT% mask of the main document, when what we really what
        // %HZ% %REVISIT% is to read the stylesheet itself!
        addDOMAdapter(adapter, false);
    }

    public int nextMask() {
        return _free;
    }

    public void setupMapping(String[] names, String[] uris, int[] types, String[] namespaces) {
        // This method only has a function in DOM adapters
    }

    public int addDOMAdapter(DOMAdapter adapter) {
        return addDOMAdapter(adapter, true);
    }

    private int addDOMAdapter(DOMAdapter adapter, boolean indexByURI) {
        // Add the DOM adapter to the array of DOMs
        DOM dom = adapter.getDOMImpl();

        int domNo = 1;
        int dtmSize = 1;
        SuballocatedIntVector dtmIds = null;
        if (dom instanceof DTMDefaultBase) {
            DTMDefaultBase dtmdb = (DTMDefaultBase)dom;
            dtmIds = dtmdb.getDTMIDs();
            dtmSize = dtmIds.size();
            domNo = dtmIds.elementAt(dtmSize-1) >>> DTMManager.IDENT_DTM_NODE_BITS;
        }
        else if (dom instanceof SimpleResultTreeImpl) {
            SimpleResultTreeImpl simpleRTF = (SimpleResultTreeImpl)dom;
            domNo = simpleRTF.getDocument() >>> DTMManager.IDENT_DTM_NODE_BITS;
        }

        if (domNo >= _size) {
            int oldSize = _size;
            do {
                _size *= 2;
            } while (_size <= domNo);

            final DOMAdapter[] newArray = new DOMAdapter[_size];
            System.arraycopy(_adapters, 0, newArray, 0, oldSize);
            _adapters = newArray;
        }

        _free = domNo + 1;

        if (dtmSize == 1) {
            _adapters[domNo] = adapter;
        }
        else if (dtmIds != null) {
            int domPos = 0;
            for (int i = dtmSize - 1; i >= 0; i--) {
                domPos = dtmIds.elementAt(i) >>> DTMManager.IDENT_DTM_NODE_BITS;
                _adapters[domPos] = adapter;
            }
            domNo = domPos;
        }

        // Store reference to document (URI) in the Map
        if (indexByURI) {
            String uri = adapter.getDocumentURI(0);
            _documents.put(uri, domNo);
        }

        // If the dom is an AdaptiveResultTreeImpl, we need to create a
        // DOMAdapter around its nested dom object (if it is non-null) and
        // add the DOMAdapter to the list.
        if (dom instanceof AdaptiveResultTreeImpl) {
            AdaptiveResultTreeImpl adaptiveRTF = (AdaptiveResultTreeImpl)dom;
            DOM nestedDom = adaptiveRTF.getNestedDOM();
            if (nestedDom != null) {
                DOMAdapter newAdapter = new DOMAdapter(nestedDom,
                                                       adapter.getNamesArray(),
                                                       adapter.getUrisArray(),
                                                       adapter.getTypesArray(),
                                                       adapter.getNamespaceArray());
                addDOMAdapter(newAdapter);
            }
        }

        return domNo;
    }

    public int getDocumentMask(String uri) {
        Integer domIdx = _documents.get(uri);
        if (domIdx == null) {
            return(-1);
        } else {
            return domIdx.intValue();
        }
    }

    public DOM getDOMAdapter(String uri) {
        Integer domIdx = _documents.get(uri);
        if (domIdx == null) {
            return(null);
        } else {
            return(_adapters[domIdx.intValue()]);
        }
    }

    public int getDocument()
    {
        return _main.getDocument();
    }

    public DTMManager getDTMManager() {
        return _dtmManager;
    }

    /**
      * Returns singleton iterator containing the document root
      */
    public DTMAxisIterator getIterator() {
        // main source document @ 0
        return _main.getIterator();
    }

    public String getStringValue() {
        return _main.getStringValue();
    }

    public DTMAxisIterator getChildren(final int node) {
        return _adapters[getDTMId(node)].getChildren(node);
    }

    public DTMAxisIterator getTypedChildren(final int type) {
        return new AxisIterator(Axis.CHILD, type);
    }

    public DTMAxisIterator getAxisIterator(final int axis) {
        return new AxisIterator(axis, NO_TYPE);
    }

    public DTMAxisIterator getTypedAxisIterator(final int axis, final int type)
    {
        return new AxisIterator(axis, type);
    }

    public DTMAxisIterator getNthDescendant(int node, int n,
                                            boolean includeself)
    {
        return _adapters[getDTMId(node)].getNthDescendant(node, n, includeself);
    }

    public DTMAxisIterator getNodeValueIterator(DTMAxisIterator iterator,
                                                int type, String value,
                                                boolean op)
    {
        return(new NodeValueIterator(iterator, type, value, op));
    }

    public DTMAxisIterator getNamespaceAxisIterator(final int axis,
                                                    final int ns)
    {
        DTMAxisIterator iterator = _main.getNamespaceAxisIterator(axis, ns);
        return(iterator);
    }

    public DTMAxisIterator orderNodes(DTMAxisIterator source, int node) {
        return _adapters[getDTMId(node)].orderNodes(source, node);
    }

    public int getExpandedTypeID(final int node) {
        if (node != DTM.NULL) {
            return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].getExpandedTypeID(node);
        }
        else {
            return DTM.NULL;
        }
    }

    public int getNamespaceType(final int node) {
        return _adapters[getDTMId(node)].getNamespaceType(node);
    }

    public int getNSType(int node)
   {
        return _adapters[getDTMId(node)].getNSType(node);
   }

    public int getParent(final int node) {
        if (node == DTM.NULL) {
            return DTM.NULL;
        }
        return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].getParent(node);
    }

    public int getAttributeNode(final int type, final int el) {
        if (el == DTM.NULL) {
            return DTM.NULL;
        }
        return _adapters[el >>> DTMManager.IDENT_DTM_NODE_BITS].getAttributeNode(type, el);
    }

    public String getNodeName(final int node) {
        if (node == DTM.NULL) {
            return "";
        }
        return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].getNodeName(node);
    }

    public String getNodeNameX(final int node) {
        if (node == DTM.NULL) {
            return "";
        }
        return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].getNodeNameX(node);
    }

    public String getNamespaceName(final int node) {
        if (node == DTM.NULL) {
            return "";
        }
        return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].getNamespaceName(node);
    }

    public String getStringValueX(final int node) {
        if (node == DTM.NULL) {
            return "";
        }
        return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].getStringValueX(node);
    }

    public void copy(final int node, SerializationHandler handler)
        throws TransletException
    {
        if (node != DTM.NULL) {
            _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].copy(node, handler);
        }
    }

    public void copy(DTMAxisIterator nodes, SerializationHandler handler)
            throws TransletException
    {
        int node;
        while ((node = nodes.next()) != DTM.NULL) {
            _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].copy(node, handler);
        }
    }


    public String shallowCopy(final int node, SerializationHandler handler)
            throws TransletException
    {
        if (node == DTM.NULL) {
            return "";
        }
        return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].shallowCopy(node, handler);
    }

    public boolean lessThan(final int node1, final int node2) {
        if (node1 == DTM.NULL) {
            return true;
        }
        if (node2 == DTM.NULL) {
            return false;
        }
        final int dom1 = getDTMId(node1);
        final int dom2 = getDTMId(node2);
        return dom1 == dom2 ? _adapters[dom1].lessThan(node1, node2)
                            : dom1 < dom2;
    }

    public void characters(final int textNode, SerializationHandler handler)
                 throws TransletException
    {
        if (textNode != DTM.NULL) {
            _adapters[textNode >>> DTMManager.IDENT_DTM_NODE_BITS].characters(textNode, handler);
        }
    }

    public void setFilter(StripFilter filter) {
        for (int dom=0; dom<_free; dom++) {
            if (_adapters[dom] != null) {
                _adapters[dom].setFilter(filter);
            }
        }
    }

    public Node makeNode(int index) {
        if (index == DTM.NULL) {
            return null;
        }
        return _adapters[getDTMId(index)].makeNode(index);
    }

    public Node makeNode(DTMAxisIterator iter) {
        // TODO: gather nodes from all DOMs ?
        return _main.makeNode(iter);
    }

    public NodeList makeNodeList(int index) {
        if (index == DTM.NULL) {
            return null;
        }
        return _adapters[getDTMId(index)].makeNodeList(index);
    }

    public NodeList makeNodeList(DTMAxisIterator iter) {
        int index = iter.next();
        if (index == DTM.NULL) {
            return new DTMAxisIterNodeList(null, null);
        }
        iter.reset();
        return _adapters[getDTMId(index)].makeNodeList(iter);
    }

    public String getLanguage(int node) {
        return _adapters[getDTMId(node)].getLanguage(node);
    }

    public int getSize() {
        int size = 0;
        for (int i=0; i<_size; i++) {
            size += _adapters[i].getSize();
        }
        return(size);
    }

    public String getDocumentURI(int node) {
        if (node == DTM.NULL) {
            node = DOM.NULL;
        }
        return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].getDocumentURI(0);
    }

    public boolean isElement(final int node) {
        if (node == DTM.NULL) {
            return false;
        }
        return(_adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].isElement(node));
    }

    public boolean isAttribute(final int node) {
        if (node == DTM.NULL) {
            return false;
        }
        return(_adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].isAttribute(node));
    }

    public int getDTMId(int nodeHandle)
    {
        if (nodeHandle == DTM.NULL)
            return 0;

        int id = nodeHandle >>> DTMManager.IDENT_DTM_NODE_BITS;
        while (id >= 2 && _adapters[id] == _adapters[id-1]) {
            id--;
        }
        return id;
    }

    public DOM getDTM(int nodeHandle) {
        return _adapters[getDTMId(nodeHandle)];
    }

    public int getNodeIdent(int nodeHandle)
    {
        return _adapters[nodeHandle >>> DTMManager.IDENT_DTM_NODE_BITS].getNodeIdent(nodeHandle);
    }

    public int getNodeHandle(int nodeId)
    {
        return _main.getNodeHandle(nodeId);
    }

    public DOM getResultTreeFrag(int initSize, int rtfType)
    {
        return _main.getResultTreeFrag(initSize, rtfType);
    }

    public DOM getResultTreeFrag(int initSize, int rtfType, boolean addToManager)
    {
        return _main.getResultTreeFrag(initSize, rtfType, addToManager);
    }

    public DOM getMain()
    {
        return _main;
    }

    /**
     * Returns a DOMBuilder class wrapped in a SAX adapter.
     */
    public SerializationHandler getOutputDomBuilder()
    {
        return _main.getOutputDomBuilder();
    }

    public String lookupNamespace(int node, String prefix)
        throws TransletException
    {
        return _main.lookupNamespace(node, prefix);
    }

    // %HZ% Does this method make any sense here???
    public String getUnparsedEntityURI(String entity) {
        return _main.getUnparsedEntityURI(entity);
    }

    // %HZ% Does this method make any sense here???
    public Map<String, Integer> getElementsWithIDs() {
        return _main.getElementsWithIDs();
    }
}
