/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQml 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 "qqmldirparser_p.h"

#include <QtCore/QtDebug>

QT_BEGIN_NAMESPACE

static int parseInt(const QStringRef &str, bool *ok)
{
    int pos = 0;
    int number = 0;
    while (pos < str.length() && str.at(pos).isDigit()) {
        if (pos != 0)
            number *= 10;
        number += str.at(pos).unicode() - '0';
        ++pos;
    }
    if (pos != str.length())
        *ok = false;
    else
        *ok = true;
    return number;
}

static bool parseVersion(const QString &str, int *major, int *minor)
{
    const int dotIndex = str.indexOf(QLatin1Char('.'));
    if (dotIndex != -1 && str.indexOf(QLatin1Char('.'), dotIndex + 1) == -1) {
        bool ok = false;
        *major = parseInt(QStringRef(&str, 0, dotIndex), &ok);
        if (ok)
            *minor = parseInt(QStringRef(&str, dotIndex + 1, str.length() - dotIndex - 1), &ok);
        return ok;
    }
    return false;
}

void QQmlDirParser::clear()
{
    _errors.clear();
    _typeNamespace.clear();
    _components.clear();
    _dependencies.clear();
    _imports.clear();
    _scripts.clear();
    _plugins.clear();
    _designerSupported = false;
    _typeInfos.clear();
    _className.clear();
}

inline static void scanSpace(const QChar *&ch) {
    while (ch->isSpace() && !ch->isNull() && *ch != QLatin1Char('\n'))
        ++ch;
}

inline static void scanToEnd(const QChar *&ch) {
    while (*ch != QLatin1Char('\n') && !ch->isNull())
        ++ch;
}

inline static void scanWord(const QChar *&ch) {
    while (!ch->isSpace() && !ch->isNull())
        ++ch;
}

/*!
\a url is used for generating errors.
*/
bool QQmlDirParser::parse(const QString &source)
{
    quint16 lineNumber = 0;
    bool firstLine = true;

    const QChar *ch = source.constData();
    while (!ch->isNull()) {
        ++lineNumber;

        bool invalidLine = false;
        const QChar *lineStart = ch;

        scanSpace(ch);
        if (*ch == QLatin1Char('\n')) {
            ++ch;
            continue;
        }
        if (ch->isNull())
            break;

        QString sections[4];
        int sectionCount = 0;

        do {
            if (*ch == QLatin1Char('#')) {
                scanToEnd(ch);
                break;
            }
            const QChar *start = ch;
            scanWord(ch);
            if (sectionCount < 4) {
                sections[sectionCount++] = source.mid(start-source.constData(), ch-start);
            } else {
                reportError(lineNumber, start-lineStart, QLatin1String("unexpected token"));
                scanToEnd(ch);
                invalidLine = true;
                break;
            }
            scanSpace(ch);
        } while (*ch != QLatin1Char('\n') && !ch->isNull());

        if (!ch->isNull())
            ++ch;

        if (invalidLine) {
            reportError(lineNumber, 0,
                        QStringLiteral("invalid qmldir directive contains too many tokens"));
            continue;
        } else if (sectionCount == 0) {
            continue; // no sections, no party.

        } else if (sections[0] == QLatin1String("module")) {
            if (sectionCount != 2) {
                reportError(lineNumber, 0,
                            QStringLiteral("module identifier directive requires one argument, but %1 were provided").arg(sectionCount - 1));
                continue;
            }
            if (!_typeNamespace.isEmpty()) {
                reportError(lineNumber, 0,
                            QStringLiteral("only one module identifier directive may be defined in a qmldir file"));
                continue;
            }
            if (!firstLine) {
                reportError(lineNumber, 0,
                            QStringLiteral("module identifier directive must be the first directive in a qmldir file"));
                continue;
            }

            _typeNamespace = sections[1];

        } else if (sections[0] == QLatin1String("plugin")) {
            if (sectionCount < 2 || sectionCount > 3) {
                reportError(lineNumber, 0,
                            QStringLiteral("plugin directive requires one or two arguments, but %1 were provided").arg(sectionCount - 1));

                continue;
            }

            const Plugin entry(sections[1], sections[2]);

            _plugins.append(entry);

        } else if (sections[0] == QLatin1String("classname")) {
            if (sectionCount < 2) {
                reportError(lineNumber, 0,
                            QStringLiteral("classname directive requires an argument, but %1 were provided").arg(sectionCount - 1));

                continue;
            }

            _className = sections[1];

        } else if (sections[0] == QLatin1String("internal")) {
            if (sectionCount != 3) {
                reportError(lineNumber, 0,
                            QStringLiteral("internal types require 2 arguments, but %1 were provided").arg(sectionCount - 1));
                continue;
            }
            Component entry(sections[1], sections[2], -1, -1);
            entry.internal = true;
            _components.insertMulti(entry.typeName, entry);
        } else if (sections[0] == QLatin1String("singleton")) {
            if (sectionCount < 3 || sectionCount > 4) {
                reportError(lineNumber, 0,
                            QStringLiteral("singleton types require 2 or 3 arguments, but %1 were provided").arg(sectionCount - 1));
                continue;
            } else if (sectionCount == 3) {
                // handle qmldir directory listing case where singleton is defined in the following pattern:
                // singleton TestSingletonType TestSingletonType.qml
                Component entry(sections[1], sections[2], -1, -1);
                entry.singleton = true;
                _components.insertMulti(entry.typeName, entry);
            } else {
                // handle qmldir module listing case where singleton is defined in the following pattern:
                // singleton TestSingletonType 2.0 TestSingletonType20.qml
                int major, minor;
                if (parseVersion(sections[2], &major, &minor)) {
                    const QString &fileName = sections[3];
                    Component entry(sections[1], fileName, major, minor);
                    entry.singleton = true;
                    _components.insertMulti(entry.typeName, entry);
                } else {
                    reportError(lineNumber, 0, QStringLiteral("invalid version %1, expected <major>.<minor>").arg(sections[2]));
                }
            }
        } else if (sections[0] == QLatin1String("typeinfo")) {
            if (sectionCount != 2) {
                reportError(lineNumber, 0,
                            QStringLiteral("typeinfo requires 1 argument, but %1 were provided").arg(sectionCount - 1));
                continue;
            }
#ifdef QT_CREATOR
            TypeInfo typeInfo(sections[1]);
            _typeInfos.append(typeInfo);
#endif

        } else if (sections[0] == QLatin1String("designersupported")) {
            if (sectionCount != 1)
                reportError(lineNumber, 0, QStringLiteral("designersupported does not expect any argument"));
            else
                _designerSupported = true;
        } else if (sections[0] == QLatin1String("depends")) {
            if (sectionCount != 3) {
                reportError(lineNumber, 0,
                            QStringLiteral("depends requires 2 arguments, but %1 were provided").arg(sectionCount - 1));
                continue;
            }

            int major, minor;
            if (parseVersion(sections[2], &major, &minor)) {
                Component entry(sections[1], QString(), major, minor);
                entry.internal = true;
                _dependencies.insert(entry.typeName, entry);
            } else {
                reportError(lineNumber, 0, QStringLiteral("invalid version %1, expected <major>.<minor>").arg(sections[2]));
            }
        } else if (sections[0] == QLatin1String("import")) {
            if (sectionCount != 2) {
                reportError(lineNumber, 0,
                            QStringLiteral("import requires 2 arguments, but %1 were provided").arg(sectionCount - 1));
                continue;
            }
            _imports << sections[1];
        } else if (sectionCount == 2) {
            // No version specified (should only be used for relative qmldir files)
            const Component entry(sections[0], sections[1], -1, -1);
            _components.insertMulti(entry.typeName, entry);
        } else if (sectionCount == 3) {
            int major, minor;
            if (parseVersion(sections[1], &major, &minor)) {
                const QString &fileName = sections[2];

                if (fileName.endsWith(QLatin1String(".js")) || fileName.endsWith(QLatin1String(".mjs"))) {
                    // A 'js' extension indicates a namespaced script import
                    const Script entry(sections[0], fileName, major, minor);
                    _scripts.append(entry);
                } else {
                    const Component entry(sections[0], fileName, major, minor);
                    _components.insertMulti(entry.typeName, entry);
                }
            } else {
                reportError(lineNumber, 0, QStringLiteral("invalid version %1, expected <major>.<minor>").arg(sections[1]));
            }
        } else {
            reportError(lineNumber, 0,
                        QStringLiteral("a component declaration requires two or three arguments, but %1 were provided").arg(sectionCount));
        }

        firstLine = false;
    }

    return hasError();
}

void QQmlDirParser::reportError(quint16 line, quint16 column, const QString &description)
{
    QQmlJS::DiagnosticMessage error;
    error.line = line;
    error.column = column;
    error.message = description;
    _errors.append(error);
}

bool QQmlDirParser::hasError() const
{
    if (! _errors.isEmpty())
        return true;

    return false;
}

void QQmlDirParser::setError(const QQmlJS::DiagnosticMessage &e)
{
    _errors.clear();
    reportError(e.line, e.column, e.message);
}

QList<QQmlJS::DiagnosticMessage> QQmlDirParser::errors(const QString &uri) const
{
    QList<QQmlJS::DiagnosticMessage> errors;
    const int numErrors = _errors.size();
    errors.reserve(numErrors);
    for (int i = 0; i < numErrors; ++i) {
        QQmlJS::DiagnosticMessage e = _errors.at(i);
        e.message.replace(QLatin1String("$$URI$$"), uri);
        errors << e;
    }
    return errors;
}

QString QQmlDirParser::typeNamespace() const
{
    return _typeNamespace;
}

void QQmlDirParser::setTypeNamespace(const QString &s)
{
    _typeNamespace = s;
}

QList<QQmlDirParser::Plugin> QQmlDirParser::plugins() const
{
    return _plugins;
}

QHash<QString, QQmlDirParser::Component> QQmlDirParser::components() const
{
    return _components;
}

QHash<QString, QQmlDirParser::Component> QQmlDirParser::dependencies() const
{
    return _dependencies;
}

QStringList QQmlDirParser::imports() const
{
    return _imports;
}

QList<QQmlDirParser::Script> QQmlDirParser::scripts() const
{
    return _scripts;
}

QList<QQmlDirParser::TypeInfo> QQmlDirParser::typeInfos() const
{
    return _typeInfos;
}

bool QQmlDirParser::designerSupported() const
{
    return _designerSupported;
}

QString QQmlDirParser::className() const
{
    return _className;
}

QDebug &operator<< (QDebug &debug, const QQmlDirParser::Component &component)
{
    const QString output = QStringLiteral("{%1 %2.%3}").
        arg(component.typeName).arg(component.majorVersion).arg(component.minorVersion);
    return debug << qPrintable(output);
}

QDebug &operator<< (QDebug &debug, const QQmlDirParser::Script &script)
{
    const QString output = QStringLiteral("{%1 %2.%3}").
        arg(script.nameSpace).arg(script.majorVersion).arg(script.minorVersion);
    return debug << qPrintable(output);
}

QT_END_NAMESPACE
