/*
 * Copyright (C) by Hannah von Reth <hannah.vonreth@owncloud.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
 * for more details.
 */

#include "gui/qmlutils.h"

#include "gui/fonticonmessagebox.h"
#include "resources/resources.h"

#include <QMessageBox>
#include <QQmlContext>
#include <QQuickItem>
#include <QQuickWidget>

using namespace Qt::Literals::StringLiterals;

void OCC::QmlUtils::OCQuickWidget::setOCContext(const QUrl &src, QWidget *parentFocusWidget, QObject *ocContext, QJSEngine::ObjectOwnership ownership)
{
    if (ownership == QJSEngine::CppOwnership) {
        // Destroying the `ocContext` will result in property changed signals, causing the re-evaluation
        // of the bindings in the QML file, which in turn results in warnings about accessing a property
        // of a `null` object.
        // To prevent this, reset the source to an empty URL.
        connect(
            ocContext, &QObject::destroyed, this, [this] { setSource(QUrl()); }, Qt::DirectConnection);
    }
    rootContext()->setContextProperty(QStringLiteral("ocQuickWidget"), this);
    rootContext()->setContextProperty(QStringLiteral("ocContext"), ocContext);
    engine()->setObjectOwnership(ocContext, ownership);
    engine()->addImageProvider(QStringLiteral("QSfera"), new OCC::Resources::CoreImageProvider());
    setResizeMode(QQuickWidget::SizeRootObjectToView);

    // Ensure the parent widget used OC_DECLARE_WIDGET_FOCUS
    if (parentFocusWidget) {
        Q_ASSERT(parentFocusWidget->metaObject()->indexOfMethod("focusNext()") != -1);
        Q_ASSERT(parentFocusWidget->metaObject()->indexOfMethod("focusPrevious()") != -1);
        _parentFocusWidget = parentFocusWidget;
    }

    setSource(src);
    if (!errors().isEmpty()) {
        auto box = new FontIconMessageBox({Resources::FontIcon::DefaultGlyphes::Warning}, QStringLiteral("QML Error"), QDebug::toString(errors()));
        box->setAttribute(Qt::WA_DeleteOnClose);
        box->exec();
        qFatal("A qml error occurred %s", qPrintable(QDebug::toString(errors())));
    }
}

void OCC::QmlUtils::OCQuickWidget::setOCContext(const QUrl &src, QWidget *ocContext)
{
    setOCContext(src, ocContext, ocContext, QJSEngine::ObjectOwnership::CppOwnership);
}

void OCC::QmlUtils::OCQuickWidget::focusInEvent(QFocusEvent *event)
{
    switch (event->reason()) {
    case Qt::TabFocusReason:
        Q_EMIT focusFirst();
        break;
    case Qt::BacktabFocusReason:
        Q_EMIT focusLast();
        break;
    default:
        break;
    }
    QQuickWidget::focusInEvent(event);
}

bool OCC::QmlUtils::OCQuickWidget::event(QEvent *event)
{
    if (event->type() == QEvent::EnabledChange) {
        QTimer::singleShot(0, this, &OCQuickWidget::enabledChanged);
    }
    return QQuickWidget::event(event);
}

QString OCC::QmlUtils::OCUtils::qVersion() const
{
    return QString::fromUtf8(::qVersion());
}

QUrl OCC::QmlUtils::OCUtils::resourcePath(const QString &theme, const QString &icon, bool enabled, int size, const QColor &color)
{
    return resourcePath2(u"qsfera"_s, theme, icon, enabled, size, color);
}

QUrl OCC::QmlUtils::OCUtils::resourcePath2(const QString &provider, const QString &theme, const QString &icon, bool enabled, int size, const QColor &color)
{
    auto url = QUrl(u"image://%1"_s.arg(provider));
    url.setQuery({{u"theme"_s, theme}, {u"icon"_s, QString::fromUtf8(QUrl::toPercentEncoding(icon))}, {u"enabled"_s, enabled ? u"true"_s : u"false"_s},
        {u"size"_s, QString::number(size)}, {u"color"_s, color.isValid() ? color.name(QColor::HexRgb) : QString()}});
    return url;
}

QUrl OCC::QmlUtils::OCUtils::avatarPath(const QString &accountID, bool enabled, int size)
{
    return resourcePath2(u"avatar"_s, {}, accountID, enabled, size, {});
}

int OCC::QmlUtils::OCUtils::compareQVersion(int major, int minor, int patch) const
{
    return QVersionNumber::compare(QVersionNumber(QT_VERSION_MAJOR, QT_VERSION_MINOR, QT_VERSION_PATCH), QVersionNumber(major, minor, patch));
}
