/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtXmlPatterns module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QStack>

#include "qabstractxmlreceiver.h"
#include "qabstractxmlnodemodel_p.h"
#include "qacceliterators_p.h"
#include "qacceltree_p.h"
#include "qatomicstring_p.h"
#include "qcommonvalues_p.h"
#include "qcompressedwhitespace_p.h"
#include "qxmldebug_p.h"
#include "quntypedatomic_p.h"
#include "qxpathhelper_p.h"

QT_BEGIN_NAMESPACE

using namespace QPatternist;

namespace QPatternist {

    class AccelTreePrivate : public QAbstractXmlNodeModelPrivate
    {
        public:
            AccelTreePrivate(AccelTree *accelTree)
                : m_accelTree(accelTree)
            {
            }

            virtual QSourceLocation sourceLocation(const QXmlNodeModelIndex &index) const
            {
                return m_accelTree->sourceLocation(index);
            }

        private:
            AccelTree *m_accelTree;
    };
}

AccelTree::AccelTree(const QUrl &docURI, const QUrl &bURI)
     : QAbstractXmlNodeModel(new AccelTreePrivate(this))
     , m_documentURI(docURI)
     , m_baseURI(bURI)
{
    /* Pre-allocate at least a little bit. */
    // TODO. Do it according to what an average 4 KB doc contains.
    basicData.reserve(100);
    data.reserve(30);
}

void AccelTree::printStats(const NamePool::Ptr &np) const
{
    Q_ASSERT(np);
#ifdef QT_NO_DEBUG
    Q_UNUSED(np); /* Needed when compiling in release mode. */
#else
    const int len = basicData.count();

    pDebug() << "AccelTree stats for" << (m_documentURI.isEmpty() ? QString::fromLatin1("<empty URI>") : m_documentURI.toString());
    pDebug() << "Maximum pre number:" << maximumPreNumber();
    pDebug() << "+---------------+-------+-------+---------------+-------+--------------+-------+";
    pDebug() << "| Pre number    | Depth | Size  | Post Number   | Kind  | Name         | Value |";
    pDebug() << "+---------------+-------+-------+---------------+-------+--------------+-------+";
    for(int i = 0; i < len; ++i)
    {
        const BasicNodeData &v = basicData.at(i);
        pDebug() << '|' << i
                 << "\t\t|" << v.depth()
                 << "\t|" << v.size()
                 << "\t|" << postNumber(i)
                 << "\t|" << v.kind()
                 << "\t\t|" << (v.name().isNull() ? QString::fromLatin1("(none)") : np->displayName(v.name()))
                 << "\t\t|" << ((v.kind() == QXmlNodeModelIndex::Text && isCompressed(i)) ? CompressedWhitespace::decompress(data.value(i))
                                                                                          : data.value(i))
                 << "\t|";
        /*
        pDebug() << '|' << QString().arg(i, 14)
                 << '|' << QString().arg(v.depth(), 6)
                 << '|' << QString().arg(v.size(), 6)
                 << '|' << QString().arg(postNumber(i), 14)
                 << '|' << QString().arg(v.kind(), 6)
                 << '|';
                 */
    }
    pDebug() << "+---------------+-------+-------+---------------+-------+--------------+";
    pDebug() << "Namespaces(" << namespaces.count() << "):";

    for (auto it = namespaces.cbegin(), end = namespaces.cend(); it != end; ++it) {
        pDebug() << "PreNumber: " << QString::number(it.key());
        for(int i = 0; i < it.value().count(); ++i)
            pDebug() << "\t\t" << np->stringForPrefix(it.value().at(i).prefix()) << " = " << np->stringForNamespace(it.value().at(i).namespaceURI());
    }

#endif
}

QUrl AccelTree::baseUri(const QXmlNodeModelIndex &ni) const
{
    switch(kind(toPreNumber(ni)))
    {
        case QXmlNodeModelIndex::Document:
            return baseUri();
        case QXmlNodeModelIndex::Element:
        {
            const QXmlNodeModelIndex::Iterator::Ptr it(iterate(ni, QXmlNodeModelIndex::AxisAttribute));
            QXmlNodeModelIndex next(it->next());

            while(!next.isNull())
            {
                if(next.name() == QXmlName(StandardNamespaces::xml, StandardLocalNames::base))
                {
                    const QUrl candidate(next.stringValue());
                    //  TODO. The xml:base spec says to do URI escaping here.

                    if(!candidate.isValid())
                        return QUrl();
                    else if(candidate.isRelative())
                    {
                        const QXmlNodeModelIndex par(parent(ni));

                        if(par.isNull())
                            return baseUri().resolved(candidate);
                        else
                            return par.baseUri().resolved(candidate);
                    }
                    else
                        return candidate;
                }

                next = it->next();
            }

            /* We have no xml:base-attribute. Can any parent supply us a base URI? */
            const QXmlNodeModelIndex par(parent(ni));

            if(par.isNull())
                return baseUri();
            else
                return par.baseUri();
        }
        case QXmlNodeModelIndex::ProcessingInstruction:
        case QXmlNodeModelIndex::Comment:
        case QXmlNodeModelIndex::Attribute:
        case QXmlNodeModelIndex::Text:
        {
            const QXmlNodeModelIndex par(ni.iterate(QXmlNodeModelIndex::AxisParent)->next());
            if(par.isNull())
                return QUrl();
            else
                return par.baseUri();
        }
        case QXmlNodeModelIndex::Namespace:
            return QUrl();
    }

    Q_ASSERT_X(false, Q_FUNC_INFO, "This line is never supposed to be reached.");
    return QUrl();
}

QUrl AccelTree::documentUri(const QXmlNodeModelIndex &ni) const
{
    if(kind(toPreNumber(ni)) == QXmlNodeModelIndex::Document)
        return documentUri();
    else
        return QUrl();
}

QXmlNodeModelIndex::NodeKind AccelTree::kind(const QXmlNodeModelIndex &ni) const
{
    return kind(toPreNumber(ni));
}

QXmlNodeModelIndex::DocumentOrder AccelTree::compareOrder(const QXmlNodeModelIndex &ni1,
                                                          const QXmlNodeModelIndex &ni2) const
{
    Q_ASSERT_X(ni1.model() == ni2.model(), Q_FUNC_INFO,
               "The API docs guarantees the two nodes are from the same model");

    const PreNumber p1 = ni1.data();
    const PreNumber p2 = ni2.data();

    if(p1 == p2)
        return QXmlNodeModelIndex::Is;
    else if(p1 < p2)
        return QXmlNodeModelIndex::Precedes;
    else
        return QXmlNodeModelIndex::Follows;
}

QXmlNodeModelIndex AccelTree::root(const QXmlNodeModelIndex &) const
{
    return createIndex(qint64(0));
}

QXmlNodeModelIndex AccelTree::parent(const QXmlNodeModelIndex &ni) const
{
    const AccelTree::PreNumber p = basicData.at(toPreNumber(ni)).parent();

    if(p == -1)
        return QXmlNodeModelIndex();
    else
        return createIndex(p);
}

QXmlNodeModelIndex::Iterator::Ptr AccelTree::iterate(const QXmlNodeModelIndex &ni,
                                                     QXmlNodeModelIndex::Axis axis) const
{
    const PreNumber preNumber = toPreNumber(ni);

    switch(axis)
    {
        case QXmlNodeModelIndex::AxisChildOrTop:
        {
            if(!hasParent(preNumber))
            {
                switch(kind(preNumber))
                {
                    case QXmlNodeModelIndex::Comment:
                    case QXmlNodeModelIndex::ProcessingInstruction:
                    case QXmlNodeModelIndex::Element:
                    case QXmlNodeModelIndex::Text:
                        return makeSingletonIterator(ni);
                    case QXmlNodeModelIndex::Attribute:
                    case QXmlNodeModelIndex::Document:
                    case QXmlNodeModelIndex::Namespace:
                        /* Do nothing. */;
                }
            }
            Q_FALLTHROUGH();
        }
        case QXmlNodeModelIndex::AxisChild:
        {
            if(hasChildren(preNumber))
                return QXmlNodeModelIndex::Iterator::Ptr(new ChildIterator(this, preNumber));
            else
                return makeEmptyIterator<QXmlNodeModelIndex>();
        }
        case QXmlNodeModelIndex::AxisAncestor:
        {
            if(hasParent(preNumber))
                return QXmlNodeModelIndex::Iterator::Ptr(new AncestorIterator<false>(this, preNumber));
            else
                return makeEmptyIterator<QXmlNodeModelIndex>();
        }
        case QXmlNodeModelIndex::AxisAncestorOrSelf:
            return QXmlNodeModelIndex::Iterator::Ptr(new AncestorIterator<true>(this, preNumber));
        case QXmlNodeModelIndex::AxisParent:
        {
            if(hasParent(preNumber))
                return makeSingletonIterator(createIndex(parent(preNumber)));
            else
                return makeEmptyIterator<QXmlNodeModelIndex>();
        }
        case QXmlNodeModelIndex::AxisDescendant:
        {
            if(hasChildren(preNumber))
                return QXmlNodeModelIndex::Iterator::Ptr(new DescendantIterator<false>(this, preNumber));
            else
                return makeEmptyIterator<QXmlNodeModelIndex>();
        }
        case QXmlNodeModelIndex::AxisDescendantOrSelf:
            return QXmlNodeModelIndex::Iterator::Ptr(new DescendantIterator<true>(this, preNumber));
        case QXmlNodeModelIndex::AxisFollowing:
        {
            if(preNumber == maximumPreNumber())
                return makeEmptyIterator<QXmlNodeModelIndex>();
            else
                return QXmlNodeModelIndex::Iterator::Ptr(new FollowingIterator(this, preNumber));
        }
        case QXmlNodeModelIndex::AxisAttributeOrTop:
        {
            if(!hasParent(preNumber) && kind(preNumber) == QXmlNodeModelIndex::Attribute)
                return makeSingletonIterator(ni);
            Q_FALLTHROUGH();
        }
        case QXmlNodeModelIndex::AxisAttribute:
        {
            if(hasChildren(preNumber) && kind(preNumber + 1) == QXmlNodeModelIndex::Attribute)
                return QXmlNodeModelIndex::Iterator::Ptr(new AttributeIterator(this, preNumber));
            else
                return makeEmptyIterator<QXmlNodeModelIndex>();
        }
        case QXmlNodeModelIndex::AxisPreceding:
        {
            if(preNumber == 0)
                return makeEmptyIterator<QXmlNodeModelIndex>();
            else
                return QXmlNodeModelIndex::Iterator::Ptr(new PrecedingIterator(this, preNumber));
        }
        case QXmlNodeModelIndex::AxisSelf:
            return makeSingletonIterator(createIndex(toPreNumber(ni)));
        case QXmlNodeModelIndex::AxisFollowingSibling:
        {
            if(preNumber == maximumPreNumber())
                return makeEmptyIterator<QXmlNodeModelIndex>();
            else
                return QXmlNodeModelIndex::Iterator::Ptr(new SiblingIterator<true>(this, preNumber));
        }
        case QXmlNodeModelIndex::AxisPrecedingSibling:
        {
            if(preNumber == 0)
                return makeEmptyIterator<QXmlNodeModelIndex>();
            else
                return QXmlNodeModelIndex::Iterator::Ptr(new SiblingIterator<false>(this, preNumber));
        }
        case QXmlNodeModelIndex::AxisNamespace:
            return makeEmptyIterator<QXmlNodeModelIndex>();
    }

    Q_ASSERT(false);
    return QXmlNodeModelIndex::Iterator::Ptr();
}

QXmlNodeModelIndex AccelTree::nextFromSimpleAxis(QAbstractXmlNodeModel::SimpleAxis,
                                                 const QXmlNodeModelIndex&) const
{
    Q_ASSERT_X(false, Q_FUNC_INFO, "This function is not supposed to be called.");
    return QXmlNodeModelIndex();
}

QVector<QXmlNodeModelIndex> AccelTree::attributes(const QXmlNodeModelIndex &element) const
{
    Q_ASSERT_X(false, Q_FUNC_INFO, "This function is not supposed to be called.");
    Q_UNUSED(element);
    return QVector<QXmlNodeModelIndex>();
}

QXmlName AccelTree::name(const QXmlNodeModelIndex &ni) const
{
    /* If this node type does not have a name(for instance, it's a comment)
     * we will return the default constructed value, which is conformant with
     * this function's contract. */
    return name(toPreNumber(ni));
}

QVector<QXmlName> AccelTree::namespaceBindings(const QXmlNodeModelIndex &ni) const
{
    /* We get a hold of the ancestor, and loop them in reverse document
     * order(first the parent, then the parent's parent, etc). As soon
     * we find a binding that hasn't already been added, we add it to the
     * result list. In that way, declarations appearing further down override
     * those further up. */

    const PreNumber preNumber = toPreNumber(ni);

    const QXmlNodeModelIndex::Iterator::Ptr it(new AncestorIterator<true>(this, preNumber));
    QVector<QXmlName> result;
    QXmlNodeModelIndex n(it->next());

    /* Whether xmlns="" has been encountered. */
    bool hasUndeclaration = false;

    while(!n.isNull())
    {
        const QVector<QXmlName> &forNode = namespaces.value(toPreNumber(n));
        const int len = forNode.size();
        bool stopInheritance = false;

        for(int i = 0; i < len; ++i)
        {
            const QXmlName &nsb = forNode.at(i);

            if(nsb.namespaceURI() == StandardNamespaces::StopNamespaceInheritance)
            {
                stopInheritance = true;
                continue;
            }

            if(nsb.prefix() == StandardPrefixes::empty &&
               nsb.namespaceURI() == StandardNamespaces::empty)
            {
                hasUndeclaration = true;
                continue;
            }

            if(!hasPrefix(result, nsb.prefix()))
            {
                /* We've already encountered an undeclaration, so we're supposed to skip
                 * them. */
                if(hasUndeclaration && nsb.prefix() == StandardPrefixes::empty)
                    continue;
                else
                    result.append(nsb);
            }
        }

        if(stopInheritance)
            break;
        else
            n = it->next();
    }

    result.append(QXmlName(StandardNamespaces::xml, StandardLocalNames::empty, StandardPrefixes::xml));

    return result;
}

void AccelTree::sendNamespaces(const QXmlNodeModelIndex &n,
                               QAbstractXmlReceiver *const receiver) const
{
    Q_ASSERT(n.kind() == QXmlNodeModelIndex::Element);

    const QXmlNodeModelIndex::Iterator::Ptr it(iterate(n, QXmlNodeModelIndex::AxisAncestorOrSelf));
    QXmlNodeModelIndex next(it->next());
    QVector<QXmlName::PrefixCode> alreadySent;

    while(!next.isNull())
    {
        const PreNumber preNumber = toPreNumber(next);

        const QVector<QXmlName> &nss = namespaces.value(preNumber);

        /* This is by far the most common case. */
        if(nss.isEmpty())
        {
            next = it->next();
            continue;
        }

        const int len = nss.count();
        bool stopInheritance = false;

        for(int i = 0; i < len; ++i)
        {
            const QXmlName &name = nss.at(i);

            if(name.namespaceURI() == StandardNamespaces::StopNamespaceInheritance)
            {
                stopInheritance = true;
                continue;
            }

            if(!alreadySent.contains(name.prefix()))
            {
                alreadySent.append(name.prefix());
                receiver->namespaceBinding(name);
            }
        }

        if(stopInheritance)
            break;
        else
            next = it->next();
    }
}

QString AccelTree::stringValue(const QXmlNodeModelIndex &ni) const
{
    const PreNumber preNumber = toPreNumber(ni);

    switch(kind(preNumber))
    {
        case QXmlNodeModelIndex::Element:
        {
            /* Concatenate all text nodes that are descendants of this node. */
            if(!hasChildren(preNumber))
                return QString();

            const AccelTree::PreNumber stop = preNumber + size(preNumber);
            AccelTree::PreNumber pn = preNumber + 1; /* Jump over ourselves. */
            QString result;

            for(; pn <= stop; ++pn)
            {
                if(kind(pn) == QXmlNodeModelIndex::Text)
                {
                    if(isCompressed(pn))
                        result += CompressedWhitespace::decompress(data.value(pn));
                    else
                        result += data.value(pn);
                }
            }

            return result;
        }
        case QXmlNodeModelIndex::Text:
        {
            if(isCompressed(preNumber))
                return CompressedWhitespace::decompress(data.value(preNumber));
            /* It's not compressed so use it as it is. */
            Q_FALLTHROUGH();
        }
        case QXmlNodeModelIndex::Attribute:
        case QXmlNodeModelIndex::ProcessingInstruction:
        case QXmlNodeModelIndex::Comment:
            return data.value(preNumber);
        case QXmlNodeModelIndex::Document:
        {
            /* Concatenate all text nodes in the whole document. */

            QString result;
            // Perhaps we can QString::reserve() the result based on the size?
            const AccelTree::PreNumber max = maximumPreNumber();

            for(AccelTree::PreNumber i = 0; i <= max; ++i)
            {
                if(kind(i) == QXmlNodeModelIndex::Text)
                {
                    if(isCompressed(i))
                        result += CompressedWhitespace::decompress(data.value(i));
                    else
                        result += data.value(i);
                }
            }

            return result;
        }
        default:
        {
            Q_ASSERT_X(false, Q_FUNC_INFO,
                       "A node type that doesn't exist in the XPath Data Model was encountered.");
            return QString(); /* Dummy, silence compiler warning. */
        }
    }
}

QVariant AccelTree::typedValue(const QXmlNodeModelIndex &n) const
{
    return stringValue(n);
}

bool AccelTree::hasPrefix(const QVector<QXmlName> &nbs, const QXmlName::PrefixCode prefix)
{
    const int size = nbs.size();

    for(int i = 0; i < size; ++i)
    {
        if(nbs.at(i).prefix() == prefix)
            return true;
    }

    return false;
}

ItemType::Ptr AccelTree::type(const QXmlNodeModelIndex &ni) const
{
    /* kind() is manually inlined here to avoid a virtual call. */
    return XPathHelper::typeFromKind(basicData.at(toPreNumber(ni)).kind());
}

Item::Iterator::Ptr AccelTree::sequencedTypedValue(const QXmlNodeModelIndex &n) const
{
    const PreNumber preNumber = toPreNumber(n);

    switch(kind(preNumber))
    {
        case QXmlNodeModelIndex::Element:
        case QXmlNodeModelIndex::Document:
        case QXmlNodeModelIndex::Attribute:
            return makeSingletonIterator(Item(UntypedAtomic::fromValue(stringValue(n))));

        case QXmlNodeModelIndex::Text:
        case QXmlNodeModelIndex::ProcessingInstruction:
        case QXmlNodeModelIndex::Comment:
            return makeSingletonIterator(Item(AtomicString::fromValue(stringValue(n))));
        default:
        {
            Q_ASSERT_X(false, Q_FUNC_INFO,
                       qPrintable(QString::fromLatin1("A node type that doesn't exist "
                                                      "in the XPath Data Model was encountered.").arg(kind(preNumber))));
            return Item::Iterator::Ptr(); /* Dummy, silence compiler warning. */
        }
    }
}

void AccelTree::copyNodeTo(const QXmlNodeModelIndex &node,
                           QAbstractXmlReceiver *const receiver,
                           const NodeCopySettings &settings) const
{
    /* This code piece can be seen as a customized version of
     * QAbstractXmlReceiver::item/sendAsNode(). */
    Q_ASSERT(receiver);
    Q_ASSERT(!node.isNull());

    typedef QHash<QXmlName::PrefixCode, QXmlName::NamespaceCode> Binding;
    QStack<Binding> outputted;

    switch(node.kind())
    {
        case QXmlNodeModelIndex::Element:
        {
            outputted.push(Binding());

            /* Add the namespace for our element name. */
            const QXmlName elementName(node.name());

            receiver->startElement(elementName);

            if(!settings.testFlag(InheritNamespaces))
                receiver->namespaceBinding(QXmlName(StandardNamespaces::StopNamespaceInheritance, 0,
                                                    StandardPrefixes::StopNamespaceInheritance));

            if(settings.testFlag(PreserveNamespaces))
                node.sendNamespaces(receiver);
            else
            {
                /* Find the namespaces that we actually use and add them to outputted. These are drawn
                 * from the element name, and the node's attributes. */
                outputted.top().insert(elementName.prefix(), elementName.namespaceURI());

                const QXmlNodeModelIndex::Iterator::Ptr attributes(iterate(node, QXmlNodeModelIndex::AxisAttribute));
                QXmlNodeModelIndex attr(attributes->next());

                while(!attr.isNull())
                {
                    const QXmlName &attrName = attr.name();
                    outputted.top().insert(attrName.prefix(), attrName.namespaceURI());
                    attr = attributes->next();
                }

                Binding::const_iterator it(outputted.top().constBegin());
                const Binding::const_iterator end(outputted.top().constEnd());

                for(; it != end; ++it)
                    receiver->namespaceBinding(QXmlName(it.value(), 0, it.key()));
            }

            /* Send the attributes of the element. */
            {
                QXmlNodeModelIndex::Iterator::Ptr attributes(node.iterate(QXmlNodeModelIndex::AxisAttribute));
                QXmlNodeModelIndex attribute(attributes->next());

                while(!attribute.isNull())
                {
                    const QString &v = attribute.stringValue();
                    receiver->attribute(attribute.name(), QStringRef(&v));
                    attribute = attributes->next();
                }
            }

            /* Send the children of the element. */
            copyChildren(node, receiver, settings);

            receiver->endElement();
            outputted.pop();
            break;
        }
        case QXmlNodeModelIndex::Document:
        {
            /* We need to intercept and grab the elements of the document node, such
             * that we preserve/inherit preference applies to them. */
            receiver->startDocument();
            copyChildren(node, receiver, settings);
            receiver->endDocument();
            break;
        }
        default:
            receiver->item(node);
    }

}

QSourceLocation AccelTree::sourceLocation(const QXmlNodeModelIndex &index) const
{
    const PreNumber key = toPreNumber(index);
    if (sourcePositions.contains(key)) {
        const QPair<qint64, qint64> position = sourcePositions.value(key);
        return QSourceLocation(m_documentURI, position.first, position.second);
    } else {
        return QSourceLocation();
    }
}

void AccelTree::copyChildren(const QXmlNodeModelIndex &node,
                             QAbstractXmlReceiver *const receiver,
                             const NodeCopySettings &settings) const
{
    QXmlNodeModelIndex::Iterator::Ptr children(node.iterate(QXmlNodeModelIndex::AxisChild));
    QXmlNodeModelIndex child(children->next());

    while(!child.isNull())
    {
        copyNodeTo(child, receiver, settings);
        child = children->next();
    }
}

QXmlNodeModelIndex AccelTree::elementById(const QXmlName &id) const
{
    const PreNumber pre = m_IDs.value(id.localName(), -1);
    if(pre == -1)
        return QXmlNodeModelIndex();
    else
        return createIndex(pre);
}

QVector<QXmlNodeModelIndex> AccelTree::nodesByIdref(const QXmlName &) const
{
    return QVector<QXmlNodeModelIndex>();
}

QT_END_NAMESPACE

