/****************************************************************************
**
** 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: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 <QtCore/QDir>
#include <QtCore/QtDebug>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QStringList>
#include <QtCore/QTextCodec>
#include <QtCore/QTextStream>
#include <QtCore/QUrl>
#include <QtCore/QVariant>
#include <QtCore/QVector>
#include <QtCore/QCoreApplication>

#include <QtXmlPatterns/QXmlFormatter>
#include <QtXmlPatterns/QXmlItem>
#include <QtXmlPatterns/QXmlQuery>
#include <QtXmlPatterns/QXmlSerializer>

#include "private/qautoptr_p.h"
#include "qapplicationargument_p.h"
#include "qapplicationargumentparser_p.h"

#if defined(Q_OS_WIN) && (!defined(_WIN32_WCE) || _WIN32_WCE >= 0x800)
/* Needed for opening stdout with _fdopen & friends. io.h seems to not be
 * needed on MinGW though. */
#include <io.h>
#include <fcntl.h>
#endif

#include "main.h"

QT_USE_NAMESPACE

/* The two Q_DECLARE_METATYPE macros must appear before the code
 * on a couple of HPUX platforms. */

/*!
 \internal
 \since 4.4
 Represents the name and value found in "-param name=value".
 */
typedef QPair<QString, QString> Parameter;
Q_DECLARE_METATYPE(Parameter)

/*!
 \internal
 \since 4.4
 For the -output switch.
 */
Q_DECLARE_METATYPE(QIODevice *)

/*!
 \class PatternistApplicationParser
 \brief Subclass to handle -param name=value
 \internal
 \since 4.4
 \reentrant
 */
class PatternistApplicationParser : public QApplicationArgumentParser
{
public:
    inline PatternistApplicationParser(int argc, char **argv,
                                       const QXmlNamePool &np) : QApplicationArgumentParser(argc, argv)
                                                               , m_namePool(np)
#ifdef Q_OS_WIN
                                                               , m_stdout(0)
#endif
    {
    }

#ifdef Q_OS_WIN
    virtual ~PatternistApplicationParser()
    {
        /* QFile::~QFile() nor QFile::close() frees the handle when
         * we use QFile::open() so we have to do it manually.
         *
         * "If stream is NULL, the invalid parameter handler is invoked," so
         * lets try to avoid that. */
        if(m_stdout)
            fclose(m_stdout);
    }
#endif

protected:
    virtual QVariant convertToValue(const QApplicationArgument &arg,
                                    const QString &input) const
    {
        if(arg.name() == QLatin1String("param"))
        {
            const int assign = input.indexOf(QLatin1Char('='));

            if(assign == -1)
            {
                message(QXmlPatternistCLI::tr("Each binding must contain an equal sign."));
                return QVariant();
            }

            const QString name(input.left(assign));
            const QString value(input.mid(assign + 1));

            if(!QXmlName::isNCName(name))
            {
                message(QXmlPatternistCLI::tr("The variable name must be a valid NCName, which %1 isn't.").arg(name));
                return QVariant();
            }

            /* The value.isNull() check ensures we can bind variables whose value is an empty string. */
            return QVariant::fromValue(Parameter(name, value.isNull() ? QString(QLatin1String("")) : value ));
        }
        else if(arg.name() == QLatin1String("output"))
        {
            QFile *const f = new QFile(input);

            if(f->open(QIODevice::WriteOnly))
                return QVariant::fromValue(static_cast<QIODevice *>(f));
            else
            {
                message(QXmlPatternistCLI::tr("Failed to open file %1 for writing: %2").arg(f->fileName(), f->errorString()));
                return QVariant();
            }
        }
        else if(arg.name() == QLatin1String("initial-template"))
        {
            const QXmlName name(QXmlName::fromClarkName(input, m_namePool));
            if(name.isNull())
            {
                message(QXmlPatternistCLI::tr("%1 is an invalid Clark Name").arg(input));
                return QVariant();
            }
            else
                return QVariant::fromValue(name);
        }
        else
            return QApplicationArgumentParser::convertToValue(arg, input);
    }

    virtual QString typeToName(const QApplicationArgument &argument) const
    {
        if(argument.name() == QLatin1String("param"))
            return QLatin1String("name=value");
        else if(argument.name() == QLatin1String("output"))
            return QLatin1String("local file");
        else
            return QApplicationArgumentParser::typeToName(argument);
    }

    virtual QVariant defaultValue(const QApplicationArgument &argument) const
    {
        if(argument.name() == QLatin1String("output"))
        {
            QFile *const out = new QFile();

#ifdef Q_OS_WIN
            /* If we don't open stdout in "binary" mode on Windows, it will translate
             * 0xA into 0xD 0xA. */
            _setmode(_fileno(stdout), _O_BINARY);
            m_stdout = _wfdopen(_fileno(stdout), L"wb");
            out->open(m_stdout, QIODevice::WriteOnly);
#else
            out->open(stdout, QIODevice::WriteOnly);
#endif

            return QVariant::fromValue(static_cast<QIODevice *>(out));
        }
        else
            return QApplicationArgumentParser::defaultValue(argument);
    }

private:
    QXmlNamePool    m_namePool;
#ifdef Q_OS_WIN
    mutable FILE *  m_stdout;
#endif
};

static inline QUrl finalizeURI(const QApplicationArgumentParser &parser,
                               const QApplicationArgument &isURI,
                               const QApplicationArgument &arg)
{
    QUrl userURI;
    {
        const QString stringURI(parser.value(arg).toString());

        if (parser.has(isURI) || QDir::isRelativePath(stringURI))
            userURI = QUrl(stringURI);
        else
            userURI = QUrl::fromLocalFile(stringURI);
    }

    return QUrl::fromLocalFile(QDir::current().absolutePath() + QLatin1Char('/')).resolved(userURI);
}

int main(int argc, char **argv)
{
    enum ExitCode
    {
        /**
         * We start from 2, because QApplicationArgumentParser
         * uses 1.
         */
        QueryFailure = 2,
        StdOutFailure
    };

    const QCoreApplication app(argc, argv);
    QCoreApplication::setApplicationName(QLatin1String("xmlpatterns"));

    QXmlNamePool namePool;
    PatternistApplicationParser parser(argc, argv, namePool);
    parser.setApplicationDescription(QLatin1String("A tool for running XQuery queries."));
    parser.setApplicationVersion(QLatin1String("0.1"));

    QApplicationArgument param(QLatin1String("param"),
                               QXmlPatternistCLI::tr("Binds an external variable. The value is directly available using the variable reference: $name."),
                               qMetaTypeId<Parameter>());
    param.setMaximumOccurrence(-1);
    parser.addArgument(param);

    const QApplicationArgument noformat(QLatin1String("no-format"),
                                        QXmlPatternistCLI::tr("By default output is formatted for readability. When specified, strict serialization is performed."));
    parser.addArgument(noformat);

    const QApplicationArgument isURI(QLatin1String("is-uri"),
                                     QXmlPatternistCLI::tr("If specified, all filenames on the command line are interpreted as URIs instead of a local filenames."));
    parser.addArgument(isURI);

    const QApplicationArgument initialTemplateName(QLatin1String("initial-template"),
                                                   QXmlPatternistCLI::tr("The name of the initial template to call as a Clark Name."),
                                                   QVariant::String);
    parser.addArgument(initialTemplateName);

    /* The temporary object is required to compile with g++ 3.3. */
    QApplicationArgument queryURI = QApplicationArgument(QLatin1String("query/stylesheet"),
                                                         QXmlPatternistCLI::tr("A local filename pointing to the query to run. If the name ends with .xsl it's assumed "
                                                                               "to be an XSL-T stylesheet. If it ends with .xq, it's assumed to be an XQuery query. (In "
                                                                               "other cases it's also assumed to be an XQuery query, but that interpretation may "
                                                                               "change in a future release of Qt.)"),
                                                         QVariant::String);
    queryURI.setMinimumOccurrence(1);
    queryURI.setNameless(true);
    parser.addArgument(queryURI);

    QApplicationArgument focus = QApplicationArgument(QLatin1String("focus"),
                                                      QXmlPatternistCLI::tr("The document to use as focus. Mandatory "
                                                                            "in case a stylesheet is used. This option is "
                                                                            "also affected by the is-uris option."),
                                                      QVariant::String);
    focus.setMinimumOccurrence(0);
    focus.setNameless(true);
    parser.addArgument(focus);

    QApplicationArgument output(QLatin1String("output"),
                                QXmlPatternistCLI::tr("A local file to which the output should be written. "
                                                      "The file is overwritten, or if not exist, created. "
                                                      "If absent, stdout is used."),
                                qMetaTypeId<QIODevice *>());
    parser.addArgument(output);

    if(!parser.parse())
        return parser.exitCode();

    /* Get the query URI. */
    const QUrl effectiveURI(finalizeURI(parser, isURI, queryURI));

    QXmlQuery::QueryLanguage lang;

    if(effectiveURI.toString().endsWith(QLatin1String(".xsl")))
         lang = QXmlQuery::XSLT20;
    else
         lang = QXmlQuery::XQuery10;

    if(lang == QXmlQuery::XQuery10 && parser.has(initialTemplateName))
    {
        parser.message(QXmlPatternistCLI::tr("An initial template name cannot be specified when running an XQuery."));
        return QApplicationArgumentParser::ParseError;
    }

    QXmlQuery query(lang, namePool);

    query.setInitialTemplateName(qvariant_cast<QXmlName>(parser.value(initialTemplateName)));

    /* Bind external variables. */
    {
        const QVariantList parameters(parser.values(param));
        const int len = parameters.count();

        /* For tracking duplicates. */
        QSet<QString> usedParameters;

        for(int i = 0; i < len; ++i)
        {
            const Parameter p(qvariant_cast<Parameter>(parameters.at(i)));

            if(usedParameters.contains(p.first))
            {
                parser.message(QXmlPatternistCLI::tr("Each parameter must be unique, %1 is specified at least twice.").arg(p.first));
                return QApplicationArgumentParser::ParseError;
            }
            else
            {
                usedParameters.insert(p.first);
                query.bindVariable(p.first, QXmlItem(p.second));
            }
        }
    }

    if(parser.has(focus))
    {
        if(!query.setFocus(finalizeURI(parser, isURI, focus)))
            return QueryFailure;
    }
    else if(lang == QXmlQuery::XSLT20 && !parser.has(initialTemplateName))
    {
        parser.message(QXmlPatternistCLI::tr("When a stylesheet is used, a "
                                             "document must be specified as a focus, or an "
                                             "initial template name must be specified, or both."));
        return QApplicationArgumentParser::ParseError;
    }

    query.setQuery(effectiveURI);

    const QPatternist::AutoPtr<QIODevice> outDevice(qvariant_cast<QIODevice *>(parser.value(output)));
    Q_ASSERT(outDevice);
    Q_ASSERT(outDevice->isWritable());

    if(query.isValid())
    {
        typedef QPatternist::AutoPtr<QAbstractXmlReceiver> RecPtr;
        RecPtr receiver;

        if(parser.has(noformat))
            receiver = RecPtr(new QXmlSerializer(query, outDevice.data()));
        else
            receiver = RecPtr(new QXmlFormatter(query, outDevice.data()));

        const bool success = query.evaluateTo(receiver.data());

        if(success)
            return parser.exitCode();
        else
            return QueryFailure;
    }
    else
        return QueryFailure;
}

