/****************************************************************************
**
** 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$
**
****************************************************************************/

//
//  W A R N I N G
//  -------------
//
// This file is not part of the Qt API.  It exists purely as an
// implementation detail.  This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//

/**
 * @file
 * @short This file is included by qcastingplatform_p.h.
 * If you need includes in this file, put them in CasttingPlatform.h,
 * outside of the namespace.
 */

template<typename TokenLookupClass,
         typename LookupKey>
MaintainingReader<TokenLookupClass, LookupKey>::MaintainingReader(const typename ElementDescription<TokenLookupClass, LookupKey>::Hash &elementDescriptions,
                                                                  const QSet<typename TokenLookupClass::NodeName> &standardAttributes,
                                                                  const ReportContext::Ptr &context,
                                                                  QIODevice *const queryDevice) : QXmlStreamReader(queryDevice)
                                                                                                , m_hasHandledStandardAttributes(false)
                                                                                                , m_context(context)
                                                                                                , m_elementDescriptions(elementDescriptions)
                                                                                                , m_standardAttributes(standardAttributes)
{
    Q_ASSERT(m_context);
    Q_ASSERT(!m_elementDescriptions.isEmpty());

    /* We start with stripping. */
    m_stripWhitespace.push(true);
}

template<typename TokenLookupClass,
         typename LookupKey>
MaintainingReader<TokenLookupClass, LookupKey>::~MaintainingReader()
{
}

template<typename TokenLookupClass,
         typename LookupKey>
QSourceLocation MaintainingReader<TokenLookupClass, LookupKey>::currentLocation() const
{
    return QSourceLocation(documentURI(),
                           lineNumber(),
                           columnNumber());
}

template<typename TokenLookupClass,
         typename LookupKey>
QXmlStreamReader::TokenType MaintainingReader<TokenLookupClass, LookupKey>::readNext()
{
    const TokenType retval = QXmlStreamReader::readNext();

    switch(retval)
    {
        case StartElement:
        {
            m_currentElementName = TokenLookupClass::toToken(name());
            m_currentAttributes = attributes();
            m_hasHandledStandardAttributes = false;

            if(!m_currentAttributes.hasAttribute(QLatin1String("xml:space")))
                m_stripWhitespace.push(m_stripWhitespace.top());
            break;
        }
        case EndElement:
            m_currentElementName = TokenLookupClass::toToken(name());
            m_stripWhitespace.pop();
            break;
        default:
            break;
    }

    return retval;
}

template<typename TokenLookupClass,
         typename LookupKey>
bool MaintainingReader<TokenLookupClass, LookupKey>::isWhitespace() const
{
    return QXmlStreamReader::isWhitespace()
           || XPathHelper::isWhitespaceOnly(text());
}


template<typename TokenLookupClass,
         typename LookupKey>
void MaintainingReader<TokenLookupClass, LookupKey>::error(const QString &message,
                                                           const ReportContext::ErrorCode code) const
{
    m_context->error(message, code, currentLocation());
}

template<typename TokenLookupClass,
         typename LookupKey>
void MaintainingReader<TokenLookupClass, LookupKey>::warning(const QString &message) const
{
    m_context->warning(message, currentLocation());
}

template<typename TokenLookupClass,
         typename LookupKey>
typename TokenLookupClass::NodeName MaintainingReader<TokenLookupClass, LookupKey>::currentElementName() const
{
    return m_currentElementName;
}

template<typename TokenLookupClass,
         typename LookupKey>
void MaintainingReader<TokenLookupClass, LookupKey>::validateElement(const LookupKey elementName) const
{
    Q_ASSERT(tokenType() == QXmlStreamReader::StartElement);

    if(m_elementDescriptions.contains(elementName))
    {
        // QHash::value breaks in Metrowerks Compiler
        const ElementDescription<TokenLookupClass, LookupKey> &desc = *m_elementDescriptions.find(elementName);
        const int attCount = m_currentAttributes.count();

        QSet<typename TokenLookupClass::NodeName> encounteredXSLTAtts;

        for(int i = 0; i < attCount; ++i)
        {
            const QXmlStreamAttribute &attr = m_currentAttributes.at(i);
            if(attr.namespaceUri().isEmpty())
            {
                const typename TokenLookupClass::NodeName attrName(TokenLookupClass::toToken(attr.name()));
                encounteredXSLTAtts.insert(attrName);

                if(!desc.requiredAttributes.contains(attrName) &&
                   !desc.optionalAttributes.contains(attrName) &&
                   !m_standardAttributes.contains(attrName) &&
                   !isAnyAttributeAllowed())
                {
                    QString translationString;

                    QList<typename TokenLookupClass::NodeName> all(desc.requiredAttributes.values() + desc.optionalAttributes.values());
                    const int totalCount = all.count();
                    QStringList allowed;

                    for(int i = 0; i < totalCount; ++i)
                        allowed.append(QPatternist::formatKeyword(TokenLookupClass::toString(all.at(i))));

                    /* Note, we can't run toString() on attrName, because we're in this branch,
                     * the token lookup doesn't have the string(!).*/
                    const QString stringedName(attr.name().toString());

                    if(totalCount == 0)
                    {
                        translationString = QtXmlPatterns::tr("Attribute %1 cannot appear on the element %2. Only the standard attributes can appear.")
                                            .arg(formatKeyword(stringedName),
                                                 formatKeyword(name()));
                    }
                    else if(totalCount == 1)
                    {
                        translationString = QtXmlPatterns::tr("Attribute %1 cannot appear on the element %2. Only %3 is allowed, and the standard attributes.")
                                            .arg(formatKeyword(stringedName),
                                                 formatKeyword(name()),
                                                 allowed.first());
                    }
                    else if(totalCount == 2)
                    {
                        /* Note, allowed has already had formatKeyword() applied. */
                        translationString = QtXmlPatterns::tr("Attribute %1 cannot appear on the element %2. Allowed is %3, %4, and the standard attributes.")
                                            .arg(formatKeyword(stringedName),
                                                 formatKeyword(name()),
                                                 allowed.first(),
                                                 allowed.last());
                    }
                    else
                    {
                        /* Note, allowed has already had formatKeyword() applied. */
                        translationString = QtXmlPatterns::tr("Attribute %1 cannot appear on the element %2. Allowed is %3, and the standard attributes.")
                                            .arg(formatKeyword(stringedName),
                                                 formatKeyword(name()),
                                                 allowed.join(QLatin1String(", ")));
                    }

                    m_context->error(translationString,
                                     ReportContext::XTSE0090,
                                     currentLocation());
                }
            }
            else if(attr.namespaceUri() == namespaceUri())
            {
                m_context->error(QtXmlPatterns::tr("XSL-T attributes on XSL-T elements must be in the null namespace, not in the XSL-T namespace which %1 is.")
                                                  .arg(formatKeyword(attr.name())),
                                 ReportContext::XTSE0090,
                                 currentLocation());
            }
            /* Else, attributes in other namespaces are allowed, continue. */
        }

        const QSet<typename TokenLookupClass::NodeName> requiredButMissing(QSet<typename TokenLookupClass::NodeName>(desc.requiredAttributes).subtract(encounteredXSLTAtts));

        if(!requiredButMissing.isEmpty())
        {
            error(QtXmlPatterns::tr("The attribute %1 must appear on element %2.")
                             .arg(QPatternist::formatKeyword(TokenLookupClass::toString(*requiredButMissing.constBegin())),
                                  formatKeyword(name())),
                  ReportContext::XTSE0010);
        }
    }
    else
    {
        error(QtXmlPatterns::tr("The element with local name %1 does not exist in XSL-T.").arg(formatKeyword(name())),
              ReportContext::XTSE0010);
    }
}

template<typename TokenLookupClass,
         typename LookupKey>
bool MaintainingReader<TokenLookupClass, LookupKey>::hasAttribute(const QString &namespaceURI,
                                 const QString &localName) const
{
    Q_ASSERT(tokenType() == QXmlStreamReader::StartElement);
    return m_currentAttributes.hasAttribute(namespaceURI, localName);
}

template<typename TokenLookupClass,
         typename LookupKey>
bool MaintainingReader<TokenLookupClass, LookupKey>::hasAttribute(const QString &localName) const
{
    return hasAttribute(QString(), localName);
}

template<typename TokenLookupClass,
         typename LookupKey>
QString MaintainingReader<TokenLookupClass, LookupKey>::readAttribute(const QString &localName,
                                                                      const QString &namespaceURI) const
{
    Q_ASSERT(tokenType() == QXmlStreamReader::StartElement);

    Q_ASSERT_X(m_currentAttributes.hasAttribute(namespaceURI, localName),
               Q_FUNC_INFO,
               "Validation must be done before this function is called.");

    return m_currentAttributes.value(namespaceURI, localName).toString();
}

