/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** 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 General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** 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-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QFile>
#include <QStack>

#include <QXmlNamePool>
#include <QXmlStreamReader>
#include <QtDebug>
#include <QTest>

#include "LoadingModel.h"
LoadingModel::LoadingModel(const Node::Vector &content,
                           const QXmlNamePool &np) : QSimpleXmlNodeModel(np)
                                                   , m_nodes(content)
{
    /*
    for (const Node *n : content)
        qDebug() << "this:" << n
                 << "kind:" << n->kind
                 << "parent: " << n->parent
                 << "preceding: " << n->precedingSibling
                 << "following: " << n->followingSibling
                 << "firstChild: " << n->firstChild
                 << "value: " << n->value;
                 */
}

LoadingModel::~LoadingModel()
{
     qDeleteAll(m_nodes);
}

const LoadingModel::Node *LoadingModel::toInternal(const QXmlNodeModelIndex &ni) const
{
    return static_cast<const Node *>(ni.internalPointer());
}

QXmlNodeModelIndex LoadingModel::createIndex(const Node *const internal) const
{
    if (!internal)
        qFatal("%s: cannot construct a model index from a null pointer", Q_FUNC_INFO);
    return QAbstractXmlNodeModel::createIndex(const_cast<Node *>(internal));
}

QUrl LoadingModel::documentUri(const QXmlNodeModelIndex &) const
{
    qFatal("%s: This method should not be called during the test", Q_FUNC_INFO);
    return QUrl();
}

QXmlNodeModelIndex::NodeKind LoadingModel::kind(const QXmlNodeModelIndex &ni) const
{
    if (ni.isNull())
        qFatal("%s: node model index should not be null", Q_FUNC_INFO);
    return toInternal(ni)->kind;
}

QXmlNodeModelIndex::DocumentOrder LoadingModel::compareOrder(const QXmlNodeModelIndex &n1, const QXmlNodeModelIndex &n2) const
{
    const Node *const in1 = toInternal(n1);
    const Node *const in2 = toInternal(n2);
    if (m_nodes.indexOf(in1) == -1)
        qFatal("%s: node n1 is not in internal node list", Q_FUNC_INFO);
    if (m_nodes.indexOf(in2) == -1)
        qFatal("%s: node n2 is not in internal node list", Q_FUNC_INFO);

    if(in1 == in2)
        return QXmlNodeModelIndex::Is;
    else if(m_nodes.indexOf(in1) < m_nodes.indexOf(in2))
        return QXmlNodeModelIndex::Precedes;
    else
        return QXmlNodeModelIndex::Follows;
}

QXmlNodeModelIndex LoadingModel::root(const QXmlNodeModelIndex &) const
{
    if (kind(createIndex(m_nodes.first())) != QXmlNodeModelIndex::Document) {
        qWarning("%s: first node must be a Document node", Q_FUNC_INFO);
        return QXmlNodeModelIndex();
    }
    return createIndex(m_nodes.first());
}

QXmlName LoadingModel::name(const QXmlNodeModelIndex &ni) const
{
    return toInternal(ni)->name;
}

QVariant LoadingModel::typedValue(const QXmlNodeModelIndex &ni) const
{
    const Node *const internal = toInternal(ni);

    if (internal->kind != QXmlNodeModelIndex::Attribute
        && internal->kind != QXmlNodeModelIndex::Element) {
        qWarning("%s: node must be an attribute or element", Q_FUNC_INFO);
        return QVariant();
    }

    return internal->value;
}

QString LoadingModel::stringValue(const QXmlNodeModelIndex &ni) const
{
    const Node *const internal = toInternal(ni);

    switch(internal->kind)
    {
        case QXmlNodeModelIndex::Text:
        /* Fallthrough. */
        case QXmlNodeModelIndex::ProcessingInstruction:
        /* Fallthrough. */
        case QXmlNodeModelIndex::Comment:
        /* Fallthrough. */
        case QXmlNodeModelIndex::Attribute:
            return internal->value;
        default:
            return QString();
    }
}

QXmlNodeModelIndex LoadingModel::nextFromSimpleAxis(QAbstractXmlNodeModel::SimpleAxis axis,
                                                    const QXmlNodeModelIndex &ni) const
{
    const Node *const internal = toInternal(ni);

    /* Note that a QXmlNodeModelIndex containing a null pointer is not a null node. */
    switch(axis)
    {
        case Parent:
            return internal->parent ? createIndex(internal->parent) : QXmlNodeModelIndex();
        case FirstChild:
            return internal->firstChild ? createIndex(internal->firstChild) : QXmlNodeModelIndex();
        case PreviousSibling:
            return internal->precedingSibling ? createIndex(internal->precedingSibling) : QXmlNodeModelIndex();
        case NextSibling:
            return internal->followingSibling ? createIndex(internal->followingSibling) : QXmlNodeModelIndex();
        default:
            qWarning("%s: unknown axis enum value %d", Q_FUNC_INFO, static_cast<int>(axis));
            return QXmlNodeModelIndex();
    }
}

QVector<QXmlNodeModelIndex> LoadingModel::attributes(const QXmlNodeModelIndex &ni) const
{
    QVector<QXmlNodeModelIndex> retval;
    for (const Node *n : toInternal(ni)->attributes)
        retval.append(createIndex(n));

    return retval;
}

class Loader
{
public:
    inline Loader(const QXmlNamePool &namePool) : m_namePool(namePool)
                                                , m_currentNode(0)
    {
        m_parentStack.push(0);
    }

private:
    inline void adjustSiblings(LoadingModel::Node *const justBorn);
    friend class LoadingModel;
    Q_DISABLE_COPY(Loader);

    void load();

    QXmlNamePool                        m_namePool;
    QXmlStreamReader                    m_reader;
    LoadingModel::Node::Vector          m_result;
    LoadingModel::Node *                m_currentNode;
    QStack<LoadingModel::Node *>        m_parentStack;
};

inline void Loader::adjustSiblings(LoadingModel::Node *const justBorn)
{
    if(m_currentNode)
    {
        if(m_currentNode->parent == justBorn->parent)
            justBorn->precedingSibling = m_currentNode;

        m_currentNode->followingSibling = justBorn;
    }

    m_currentNode = justBorn;

    /* Otherwise we're the first child, and our precedingSibling should remain null. */

    if(m_parentStack.top() && !m_parentStack.top()->firstChild)
        m_parentStack.top()->firstChild = justBorn;
}

void Loader::load()
{
    QFile in(QLatin1String("tree.xml"));

    /* LoadingModel::m_result will be null, signalling failure. */
    if(!in.open(QIODevice::ReadOnly))
        return;

    QXmlStreamReader reader(&in);
    while(!reader.atEnd())
    {
        reader.readNext();

        switch(reader.tokenType())
        {
            case QXmlStreamReader::StartDocument:
            /* Fallthrough. */
            case QXmlStreamReader::StartElement:
            {
                QXmlName name;
                if(reader.tokenType() == QXmlStreamReader::StartElement)
                {
                    name = QXmlName(m_namePool,
                                    reader.name().toString(),
                                    reader.namespaceUri().toString(),
                                    reader.prefix().toString());
                }
                /* Else, the name is null. */

                LoadingModel::Node *const tmp = new LoadingModel::Node(reader.tokenType() == QXmlStreamReader::StartElement
                                                                       ? QXmlNodeModelIndex::Element
                                                                       : QXmlNodeModelIndex::Document,
                                                                       m_parentStack.top(),
                                                                       QString(),
                                                                       name);
                m_result.append(tmp);

                if(m_currentNode)
                {
                    if(m_currentNode->parent == m_parentStack.top())
                        m_currentNode->followingSibling = tmp;
                }

                const QXmlStreamAttributes attributes(reader.attributes());
                const int len = attributes.count();

                for(int i = 0; i < len; ++i)
                {
                    const QXmlStreamAttribute &attr = attributes.at(i);
                    const LoadingModel::Node *const a = new LoadingModel::Node(QXmlNodeModelIndex::Attribute,
                                                                               m_parentStack.top(),
                                                                               attr.value().toString(),
                                                                               QXmlName(m_namePool,
                                                                                       attr.name().toString(),
                                                                                       attr.namespaceUri().toString(),
                                                                                       attr.prefix().toString()));
                    /* We add it also to m_result such that compareOrder() is correct
                     * for attributes. m_result owns a. */
                    tmp->attributes.append(a);
                    m_result.append(a);
                }

                adjustSiblings(tmp);
                m_parentStack.push(m_currentNode);
                break;
            }
            case QXmlStreamReader::EndDocument:
            /* Fallthrough. */
            case QXmlStreamReader::EndElement:
            {
                m_currentNode->followingSibling = 0;
                m_currentNode = m_parentStack.pop();

                if(reader.tokenType() == QXmlStreamReader::EndDocument)
                    const_cast<LoadingModel::Node *>(m_result.first())->followingSibling = 0;

                break;
            }
            case QXmlStreamReader::Characters:
            {
                LoadingModel::Node *const tmp = new LoadingModel::Node(QXmlNodeModelIndex::Text, m_parentStack.top(), reader.text().toString());
                m_result.append(tmp);
                adjustSiblings(tmp);
                break;
            }
            case QXmlStreamReader::ProcessingInstruction:
            {
                LoadingModel::Node *const tmp = new LoadingModel::Node(QXmlNodeModelIndex::ProcessingInstruction,
                                                                       m_parentStack.top(),
                                                                       reader.processingInstructionData().toString(),
                                                                       QXmlName(m_namePool, reader.processingInstructionTarget().toString()));
                m_result.append(tmp);
                adjustSiblings(tmp);
                break;
            }
            case QXmlStreamReader::Comment:
            {
                LoadingModel::Node *const tmp = new LoadingModel::Node(QXmlNodeModelIndex::Comment, m_parentStack.top(), reader.text().toString());
                m_result.append(tmp);
                adjustSiblings(tmp);
                break;
            }
            case QXmlStreamReader::DTD:
                qFatal("%s: QXmlStreamReader::DTD token is not supported", Q_FUNC_INFO);
                break;
            case QXmlStreamReader::EntityReference:
                qFatal("%s: QXmlStreamReader::EntityReference token is not supported", Q_FUNC_INFO);
                break;
            case QXmlStreamReader::NoToken:
            /* Fallthrough. */
            case QXmlStreamReader::Invalid:
            {
                qWarning("%s", qPrintable(reader.errorString()));
                m_result.clear();
                return;
            }
        }
    }

    if(reader.hasError())
    {
        qWarning("%s", qPrintable(reader.errorString()));
        m_result.clear();
    }
}

QAbstractXmlNodeModel::Ptr LoadingModel::create(const QXmlNamePool &np)
{
    Loader loader(np);
    loader.load();
    if (loader.m_result.isEmpty()) {
        qWarning("%s: attempt to create model with no content", Q_FUNC_INFO);
        return Ptr(0);
    }

    return Ptr(new LoadingModel(loader.m_result, np));
}
