/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL3$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
** Software Foundation and appearing in the file LICENSE.GPL included in
** the packaging of this file. Please review the following information to
** ensure the GNU General Public License version 2.0 requirements will be
** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qquickstyle.h"
#include "qquickstyle_p.h"

#include <QtCore/qdir.h>
#include <QtCore/qfile.h>
#include <QtCore/qdebug.h>
#include <QtCore/qsettings.h>
#include <QtCore/qfileselector.h>
#include <QtCore/qlibraryinfo.h>
#include <QtCore/qmetaobject.h>
#include <QtGui/qcolor.h>
#include <QtGui/qfont.h>
#include <QtGui/qpalette.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/qpa/qplatformtheme.h>
#include <QtQml/private/qqmlmetatype_p.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlfile.h>

#include <functional>

QT_BEGIN_NAMESPACE

/*!
    \class QQuickStyle
    \brief The QQuickStyle class allows configuring the application style.
    \inmodule QtQuickControls2
    \since 5.7

    QQuickStyle provides API for querying and configuring the application
    \l {Styling Qt Quick Controls}{styles} of Qt Quick Controls.

    \code
    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQuickStyle>

    int main(int argc, char *argv[])
    {
        QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
        QGuiApplication app(argc, argv);

        QQuickStyle::setStyle("Material");

        QQmlApplicationEngine engine;
        engine.load(QUrl("qrc:/main.qml"));

        return app.exec();
    }
    \endcode

    \note The style must be configured \b before loading QML that imports
    Qt Quick Controls. It is not possible to change the style after the QML
    types have been registered.

    The style can also be specified as a path to a custom style, such as
    \c ":/mystyle". See \l {Creating a Custom Style} for more details about
    building custom styles. Custom styles do not need to implement all controls.
    By default, the styling system uses the \l {Default style} as a fallback
    for controls that a custom style does not provide. It is possible to
    specify a different fallback style to customize or extend one of the
    built-in styles.

    \code
    QQuickStyle::setStyle(":/mystyle");
    QQuickStyle::setFallbackStyle("Material");
    \endcode

    \sa {Styling Qt Quick Controls}
*/

static QStringList envPathList(const QByteArray &var)
{
    QStringList paths;
    if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty(var))) {
        const QByteArray value = qgetenv(var);
        paths += QString::fromLocal8Bit(value).split(QDir::listSeparator(), Qt::SkipEmptyParts);
    }
    return paths;
}

static QStringList defaultImportPathList()
{
    QStringList importPaths;
    importPaths.reserve(3);
#ifdef Q_OS_ANDROID
    // androiddeployqt puts the QML files inside a resource file and they are not
    // showing up in the Qml2ImportsPath as a result
    importPaths += QStringLiteral(":/android_rcc_bundle/qml");
#else
# ifndef QT_STATIC
    importPaths += QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath);
# endif
#endif
    importPaths += envPathList("QML2_IMPORT_PATH");
    importPaths += QStringLiteral(":/qt-project.org/imports");
    importPaths += QCoreApplication::applicationDirPath();
    return importPaths;
}

struct QQuickStyleSpec
{
    QQuickStyleSpec() : custom(false), resolved(false) { }

    QString name()
    {
        if (!resolved)
            resolve();
        return style.mid(style.lastIndexOf(QLatin1Char('/')) + 1);
    }

    QString path()
    {
        if (!resolved)
            resolve();
        QString s = style;
        if (QQmlFile::isLocalFile(s))
            s = QQmlFile::urlToLocalFileOrQrc(s);
        return s.left(s.lastIndexOf(QLatin1Char('/')) + 1);
    }

    void setStyle(const QString &s)
    {
        style = s;
        resolved = false;
        resolve();
    }

    void setFallbackStyle(const QString &fallback, const QByteArray &method)
    {
        fallbackStyle = fallback;
        fallbackMethod = method;
    }

    static QString findStyle(const QString &path, const QString &name)
    {
        QDir dir(path);
        if (!dir.exists())
            return QString();

        if (name.isEmpty())
            return dir.absolutePath() + QLatin1Char('/');

        const QStringList entries = dir.entryList(QStringList(), QDir::Dirs | QDir::NoDotAndDotDot);
        for (const QString &entry : entries) {
            if (entry.compare(name, Qt::CaseInsensitive) == 0)
                return dir.absoluteFilePath(entry);
        }

        return QString();
    }

    void resolve(const QUrl &baseUrl = QUrl())
    {
        if (style.isEmpty())
            style = QGuiApplicationPrivate::styleOverride;
        if (style.isEmpty())
            style = QString::fromLocal8Bit(qgetenv("QT_QUICK_CONTROLS_STYLE"));
        if (fallbackStyle.isEmpty())
            setFallbackStyle(QString::fromLocal8Bit(qgetenv("QT_QUICK_CONTROLS_FALLBACK_STYLE")), "QT_QUICK_CONTROLS_FALLBACK_STYLE");
#if QT_CONFIG(settings)
        if (style.isEmpty() || fallbackStyle.isEmpty()) {
            QSharedPointer<QSettings> settings = QQuickStylePrivate::settings(QStringLiteral("Controls"));
            if (settings) {
                if (style.isEmpty())
                    style = settings->value(QStringLiteral("Style")).toString();
                if (fallbackStyle.isEmpty())
                    setFallbackStyle(settings->value(QStringLiteral("FallbackStyle")).toString(), ":/qtquickcontrols2.conf");
            }
        }
#endif

        // resolve a path relative to the config
        QString configPath = QFileInfo(resolveConfigFilePath()).path();
        QString stylePath = findStyle(configPath, style);
        if (!stylePath.isEmpty()) {
            style = stylePath;
            resolved = true;
        }

        custom = style.contains(QLatin1Char('/'));

        if (baseUrl.isValid()) {
            QString path = QQmlFile::urlToLocalFileOrQrc(baseUrl);
            QString stylePath = findStyle(path, style);
            if (!stylePath.isEmpty()) {
                style = stylePath;
                resolved = true;
            }
        }

        if (QGuiApplication::instance()) {
            if (!custom) {
                const QStringList stylePaths = QQuickStylePrivate::stylePaths();
                for (const QString &path : stylePaths) {
                    QString stylePath = findStyle(path, style);
                    if (!stylePath.isEmpty()) {
                        custom = !stylePath.startsWith(QQmlFile::urlToLocalFileOrQrc(baseUrl));
                        style = stylePath;
                        resolved = true;
                        break;
                    }
                }
            }
            resolved = true;
        }
    }

    void reset()
    {
        custom = false;
        resolved = false;
        style.clear();
        fallbackStyle.clear();
        fallbackMethod.clear();
        configFilePath.clear();
    }

    QString resolveConfigFilePath()
    {
        if (configFilePath.isEmpty()) {
            configFilePath = QFile::decodeName(qgetenv("QT_QUICK_CONTROLS_CONF"));
            if (configFilePath.isEmpty() || !QFile::exists(configFilePath)) {
                if (!configFilePath.isEmpty())
                    qWarning("QT_QUICK_CONTROLS_CONF=%s: No such file", qPrintable(configFilePath));

                configFilePath = QStringLiteral(":/qtquickcontrols2.conf");
            }
        }
        return configFilePath;
    }

    bool custom;
    bool resolved;
    QString style;
    QString fallbackStyle;
    QByteArray fallbackMethod;
    QString configFilePath;
    QStringList customStylePaths;
};

Q_GLOBAL_STATIC(QQuickStyleSpec, styleSpec)

static QStringList parseStylePathsWithColon(const QString &var)
{
    QStringList paths;
    const QChar colon = QLatin1Char(':');
    int currentIndex = 0;

    do {
        int nextColonIndex = -1;
        QString path;

        if (var.at(currentIndex) == colon) {
            // This is either a list separator, or a qrc path.
            if (var.at(currentIndex + 1) == colon) {
                // It's a double colon (list separator followed by qrc path);
                // find the end of the path.
                nextColonIndex = var.indexOf(colon, currentIndex + 2);
                path = var.mid(currentIndex + 1,
                    nextColonIndex == -1 ? -1 : nextColonIndex - currentIndex - 1);
            } else {
                // It's a single colon.
                nextColonIndex = var.indexOf(colon, currentIndex + 1);
                if (currentIndex == 0) {
                    // If we're at the start of the string, then it's a qrc path.
                    path = var.mid(currentIndex,
                        nextColonIndex == -1 ? -1 : nextColonIndex - currentIndex);
                } else {
                    // Otherwise, it's a separator.
                    path = var.mid(currentIndex + 1,
                        nextColonIndex == -1 ? -1 : nextColonIndex - currentIndex - 1);
                }
            }
        } else {
            // It's a file path.
            nextColonIndex = var.indexOf(colon, currentIndex);
            path = var.mid(currentIndex,
                nextColonIndex == -1 ? -1 : nextColonIndex - currentIndex);
        }

        paths += path;
        currentIndex = nextColonIndex;

        // Keep going until we can't find any more colons,
        // or we're at the last character.
    } while (currentIndex != -1 && currentIndex < var.size() - 1);

    return paths;
}

QStringList QQuickStylePrivate::stylePaths(bool resolve)
{
    // user-requested style path
    QStringList paths;
    if (resolve) {
        QString path = styleSpec()->path();
        if (path.endsWith(QLatin1Char('/')))
            path.chop(1);
        if (!path.isEmpty())
            paths += path;
    }

    if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("QT_QUICK_CONTROLS_STYLE_PATH"))) {
        const QString value = QString::fromLocal8Bit(qgetenv("QT_QUICK_CONTROLS_STYLE_PATH"));
        const QChar listSeparator = QDir::listSeparator();
        if (listSeparator == QLatin1Char(':')) {
            // Split manually to avoid breaking paths on systems where : is the list separator,
            // since it's also used for qrc paths.
            paths += parseStylePathsWithColon(value);
        } else {
            // Fast/simpler path for systems where something other than : is used as
            // the list separator (such as ';').
            const QStringList customPaths = value.split(listSeparator, Qt::SkipEmptyParts);
            paths += customPaths;
        }
    }

    // system/custom style paths
    paths += styleSpec()->customStylePaths;
    paths += envPathList("QT_QUICK_CONTROLS_STYLE_PATH");

    // built-in import paths
    const QString targetPath = QStringLiteral("QtQuick/Controls.2");
    const QStringList importPaths = defaultImportPathList();
    for (const QString &importPath : importPaths) {
        QDir dir(importPath);
        if (dir.cd(targetPath))
            paths += dir.absolutePath();
    }

    paths.removeDuplicates();
    return paths;
}

QString QQuickStylePrivate::fallbackStyle()
{
    return styleSpec()->fallbackStyle;
}

bool QQuickStylePrivate::isCustomStyle()
{
    return styleSpec()->custom;
}

void QQuickStylePrivate::init(const QUrl &baseUrl)
{
    QQuickStyleSpec *spec = styleSpec();
    spec->resolve(baseUrl);

    if (!spec->fallbackStyle.isEmpty()) {
        QString fallbackStyle;
        const QStringList stylePaths = QQuickStylePrivate::stylePaths();
        for (const QString &path : stylePaths) {
            fallbackStyle = spec->findStyle(path, spec->fallbackStyle);
            if (!fallbackStyle.isEmpty())
                break;
        }
        if (fallbackStyle.isEmpty()) {
            if (spec->fallbackStyle.compare(QStringLiteral("Default")) != 0) {
                qWarning() << "ERROR: unable to locate fallback style" << spec->fallbackStyle;
                qInfo().nospace().noquote() << spec->fallbackMethod << ": the fallback style must be the name of one of the built-in Qt Quick Controls 2 styles.";
            }
            spec->fallbackStyle.clear();
        }
    }
}

void QQuickStylePrivate::reset()
{
    if (styleSpec())
        styleSpec()->reset();
}

QString QQuickStylePrivate::configFilePath()
{
    return styleSpec()->resolveConfigFilePath();
}

QSharedPointer<QSettings> QQuickStylePrivate::settings(const QString &group)
{
#ifndef QT_NO_SETTINGS
    const QString filePath = QQuickStylePrivate::configFilePath();
    if (QFile::exists(filePath)) {
        QFileSelector selector;
        QSettings *settings = new QSettings(selector.select(filePath), QSettings::IniFormat);
        if (!group.isEmpty())
            settings->beginGroup(group);
        return QSharedPointer<QSettings>(settings);
    }
#endif // QT_NO_SETTINGS
    return QSharedPointer<QSettings>();
}

#if QT_CONFIG(settings)
static void readValue(const QSharedPointer<QSettings> &settings, const QString &name, std::function<void(const QVariant &)> setValue)
{
    const QVariant var = settings->value(name);
    if (var.isValid())
        setValue(var);
}

template <typename Enum>
static Enum toEnumValue(const QVariant &var)
{
    // ### TODO: expose QFont enums to the meta object system using Q_ENUM
    //QMetaEnum enumeration = QMetaEnum::fromType<Enum>();
    //bool ok = false;
    //int value = enumeration.keyToValue(var.toByteArray(), &ok);
    //if (!ok)
    //    value = var.toInt();
    //return static_cast<Enum>(value);

    return static_cast<Enum>(var.toInt());
}

const QFont *QQuickStylePrivate::readFont(const QSharedPointer<QSettings> &settings)
{
    const QVariant var = settings->value(QStringLiteral("Font"));
    if (var.isValid())
        return new QFont(var.value<QFont>());

    QFont f;
    settings->beginGroup(QStringLiteral("Font"));
    readValue(settings, QStringLiteral("Family"), [&f](const QVariant &var) { f.setFamily(var.toString()); });
    readValue(settings, QStringLiteral("PointSize"), [&f](const QVariant &var) { f.setPointSizeF(var.toReal()); });
    readValue(settings, QStringLiteral("PixelSize"), [&f](const QVariant &var) { f.setPixelSize(var.toInt()); });
    readValue(settings, QStringLiteral("StyleHint"), [&f](const QVariant &var) { f.setStyleHint(toEnumValue<QFont::StyleHint>(var.toInt())); });
    readValue(settings, QStringLiteral("Weight"), [&f](const QVariant &var) { f.setWeight(toEnumValue<QFont::Weight>(var)); });
    readValue(settings, QStringLiteral("Style"), [&f](const QVariant &var) { f.setStyle(toEnumValue<QFont::Style>(var.toInt())); });
    settings->endGroup();
    return new QFont(f);
}

static void readColorGroup(const QSharedPointer<QSettings> &settings, QPalette::ColorGroup group, QPalette *palette)
{
    const QStringList keys = settings->childKeys();
    if (keys.isEmpty())
        return;

    static const int index = QPalette::staticMetaObject.indexOfEnumerator("ColorRole");
    Q_ASSERT(index != -1);
    QMetaEnum metaEnum = QPalette::staticMetaObject.enumerator(index);

    for (const QString &key : keys) {
        bool ok = false;
        int role = metaEnum.keyToValue(key.toUtf8(), &ok);
        if (ok)
            palette->setColor(group, static_cast<QPalette::ColorRole>(role), settings->value(key).value<QColor>());
    }
}

const QPalette *QQuickStylePrivate::readPalette(const QSharedPointer<QSettings> &settings)
{
    QPalette p;
    settings->beginGroup(QStringLiteral("Palette"));
    readColorGroup(settings, QPalette::All, &p);

    settings->beginGroup(QStringLiteral("Normal"));
    readColorGroup(settings, QPalette::Normal, &p);
    settings->endGroup();

    settings->beginGroup(QStringLiteral("Disabled"));
    readColorGroup(settings, QPalette::Disabled, &p);
    settings->endGroup();
    return new QPalette(p);
}
#endif // QT_CONFIG(settings)

static bool qt_is_dark_system_theme()
{
    if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
        if (const QPalette *systemPalette = theme->palette(QPlatformTheme::SystemPalette)) {
            const QColor &textColor = systemPalette->color(QPalette::WindowText);
            return textColor.red() > 128 && textColor.blue() > 128 && textColor.green() > 128;
        }
    }
    return false;
}

bool QQuickStylePrivate::isDarkSystemTheme()
{
    static bool dark = qt_is_dark_system_theme();
    return dark;
}

/*!
    Returns the name of the application style.

    \note The application style can be specified by passing a \c -style command
          line argument. Therefore \c name() may not return a fully resolved
          value if called before constructing a QGuiApplication.
*/
QString QQuickStyle::name()
{
    return styleSpec()->name();
}

/*!
    Returns the path of an overridden application style, or an empty
    string if the style is one of the built-in Qt Quick Controls 2 styles.

    \note The application style can be specified by passing a \c -style command
          line argument. Therefore \c path() may not return a fully resolved
          value if called before constructing a QGuiApplication.
*/
QString QQuickStyle::path()
{
    return styleSpec()->path();
}

/*!
    Sets the application style to \a style.

    \note The style must be configured \b before loading QML that imports Qt Quick Controls.
          It is not possible to change the style after the QML types have been registered.

    \sa setFallbackStyle(), {Using Styles in Qt Quick Controls}
*/
void QQuickStyle::setStyle(const QString &style)
{
    if (QQmlMetaType::isModule(QStringLiteral("QtQuick.Controls"), 2, 0)) {
        qWarning() << "ERROR: QQuickStyle::setStyle() must be called before loading QML that imports Qt Quick Controls 2.";
        return;
    }

    styleSpec()->setStyle(style);
}

/*!
    \since 5.8
    Sets the application fallback style to \a style.

    \note The fallback style must be the name of one of the built-in Qt Quick Controls styles, e.g. "Material".

    \note The style must be configured \b before loading QML that imports Qt Quick Controls.
          It is not possible to change the style after the QML types have been registered.

    The fallback style can be also specified by setting the \c QT_QUICK_CONTROLS_FALLBACK_STYLE
    \l {Supported Environment Variables in Qt Quick Controls}{environment variable}.

    \sa setStyle(), {Using Styles in Qt Quick Controls}
*/
void QQuickStyle::setFallbackStyle(const QString &style)
{
    if (QQmlMetaType::isModule(QStringLiteral("QtQuick.Controls"), 2, 0)) {
        qWarning() << "ERROR: QQuickStyle::setFallbackStyle() must be called before loading QML that imports Qt Quick Controls 2.";
        return;
    }

    styleSpec()->setFallbackStyle(style, "QQuickStyle::setFallbackStyle()");
}

/*!
    \since 5.9
    Returns the names of the available styles.

    \note The method must be called \b after creating an instance of QGuiApplication.

    \sa stylePathList(), addStylePath()
*/
QStringList QQuickStyle::availableStyles()
{
    QStringList styles;
    if (!QGuiApplication::instance()) {
        qWarning() << "ERROR: QQuickStyle::availableStyles() must be called after creating an instance of QGuiApplication.";
        return styles;
    }

    const QStringList stylePaths = QQuickStylePrivate::stylePaths();
    for (const QString &path : stylePaths) {
        const QList<QFileInfo> entries = QDir(path).entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
        for (const QFileInfo &entry : entries) {
            const QString name = entry.fileName();
            if (!name.endsWith(QLatin1String(".dSYM")) && name != QLatin1String("designer"))
                styles += name;
        }
    }
    styles.prepend(QStringLiteral("Default"));
    styles.removeDuplicates();
    return styles;
}

/*!
    \since 5.12

    Returns the list of directories where Qt Quick Controls 2 searches for available styles.

    By default, the list contains paths specified in the \c QT_QUICK_CONTROLS_STYLE_PATH
    environment variable, and any existing \c QtQuick/Controls.2 sub-directories in
    \l QQmlEngine::importPathList().

    \sa addStylePath(), availableStyles()
*/
QStringList QQuickStyle::stylePathList()
{
    return QQuickStylePrivate::stylePaths();
}

/*!
    \since 5.12

    Adds \a path as a directory where Qt Quick Controls 2 searches for available styles.

    The \a path may be any local filesystem directory or \l {The Qt Resource System}{Qt Resource} directory.
    For example, the following paths are all valid:

    \list
        \li \c {/path/to/styles/}
        \li \c {file:///path/to/styles/}
        \li \c {:/path/to/styles/}
        \li \c {qrc:/path/to/styles/})
    \endlist

    The \a path will be converted into \l {QDir::canonicalPath}{canonical form} before it is added to
    the style path list.

    The newly added \a path will be first in the stylePathList().

    \sa stylePathList(), availableStyles()
*/
void QQuickStyle::addStylePath(const QString &path)
{
    if (path.isEmpty())
        return;

    const QUrl url = QUrl(path);
    if (url.isRelative() || url.scheme() == QLatin1String("file")
            || (url.scheme().length() == 1 && QFile::exists(path)) ) {  // windows path
        styleSpec()->customStylePaths.prepend(QDir(path).canonicalPath());
    } else if (url.scheme() == QLatin1String("qrc")) {
        styleSpec()->customStylePaths.prepend(QLatin1Char(':') + url.path());
    } else {
        styleSpec()->customStylePaths.prepend(path);
    }
}

QT_END_NAMESPACE
