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

#include <tools/stringconstants.h>
#include <tools/qttools.h>

#include <QtCore/qregularexpression.h>

namespace qbs {

QString toJSLiteral(const bool b)
{
    return b ? Internal::StringConstants::trueValue() : Internal::StringConstants::falseValue();
}

QString toJSLiteral(long long l)
{
    return QString::number(l);
}

QString toJSLiteral(unsigned long long l)
{
    return QString::number(l);
}

QString toJSLiteral(const QString &str)
{
    QString js = str;
    js.replace(QRegularExpression(QLatin1String("([\\\\\"])")), QLatin1String("\\\\1"));
    js.prepend(QLatin1Char('"'));
    js.append(QLatin1Char('"'));
    return js;
}

QString toJSLiteral(const QStringList &strs)
{
    QString js = QStringLiteral("[");
    for (int i = 0; i < strs.size(); ++i) {
        if (i != 0)
            js.append(QLatin1String(", "));
        js.append(toJSLiteral(strs.at(i)));
    }
    js.append(QLatin1Char(']'));
    return js;
}

QString toJSLiteral(const QVariant &val)
{
    if (!val.isValid())
        return Internal::StringConstants::undefinedValue();
    switch (val.userType()) {
    case QMetaType::QVariantList:
    case QMetaType::QStringList: {
        QString res;
        const auto list = val.toList();
        for (const QVariant &child : list) {
            if (res.length()) res.append(QLatin1String(", "));
            res.append(toJSLiteral(child));
        }
        res.prepend(QLatin1Char('['));
        res.append(QLatin1Char(']'));
        return res;
    }
    case QMetaType::QVariantMap: {
        const QVariantMap &vm = val.toMap();
        QString str = QStringLiteral("{");
        for (QVariantMap::const_iterator it = vm.begin(); it != vm.end(); ++it) {
            if (it != vm.begin())
                str += QLatin1Char(',');
            str += toJSLiteral(it.key()) + QLatin1Char(':') + toJSLiteral(it.value());
        }
        str += QLatin1Char('}');
        return str;
    }
    case QMetaType::Bool:
        return toJSLiteral(val.toBool());
    case QMetaType::Char:
    case QMetaType::Int:
    case QMetaType::Long:
    case QMetaType::LongLong:
        return toJSLiteral(val.toLongLong());
    case QMetaType::UChar:
    case QMetaType::UInt:
    case QMetaType::ULong:
    case QMetaType::ULongLong:
        return toJSLiteral(val.toULongLong());
    case QMetaType::QVariantHash: {
        const QVariantHash h = val.toHash();
        if (h.size() == 1 && h.constBegin().key().isEmpty())
            return toJSLiteral(*h.constBegin());
        break;
    }
    default:
        break;
    }

    if (qVariantCanConvert(val, QMetaType::QString))
        return toJSLiteral(val.toString());
    return QStringLiteral("Unconvertible type %1").arg(QLatin1String(val.typeName()));
}

} // namespace qbs
