/*
    SPDX-FileCopyrightText: 2015 Aleix Pol Gonzalez <aleixpol@blue-systems.com>

    SPDX-License-Identifier: LGPL-2.1-or-later
*/

#include "menu.h"
#include <KLocalizedQmlContext>
#include <QDebug>
#include <QPointer>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <purpose/alternativesmodel.h>
#include <purpose/configuration.h>
#include <qqml.h>

using namespace Purpose;

class Purpose::MenuPrivate : public QObject
{
    Q_OBJECT
public:
    MenuPrivate(Menu *qq)
        : QObject(qq)
        , m_model(new AlternativesModel(qq))
        , q(qq)
    {
    }

    ~MenuPrivate() override
    {
        if (m_engine) {
            m_engine->deleteLater();
        }
    }

    void trigger(int row)
    {
        if (!m_engine) {
            m_engine = new QQmlApplicationEngine;
            m_engine->rootContext()->setContextObject(new KLocalizedQmlContext(this));
            m_engine->loadFromModule("org.kde.purpose.private.widgets", "JobDialog");
        }

        Q_ASSERT(!m_engine->rootObjects().isEmpty());
        QObject *o = m_engine->rootObjects().at(0);

        if (!o) {
            qWarning() << Q_FUNC_INFO << "object is NULL at m_engine" << m_engine << "rootObjects=" << m_engine->rootObjects();
            return;
        }

        o->setProperty("model", QVariant::fromValue(m_model.data()));
        o->setProperty("index", row);
        o->setProperty("visible", true);
        o->setProperty("menu", QVariant::fromValue<QObject *>(q));
        o->setParent(q);

        QMetaObject::invokeMethod(o, "start");
    }

public:
    QQmlApplicationEngine *m_engine = nullptr;
    QPointer<AlternativesModel> m_model;
    Purpose::Menu *q;
};

Menu::Menu(QWidget *parent)
    : QMenu(parent)
    , d_ptr(new MenuPrivate(this))
{
    connect(d_ptr->m_model.data(), &AlternativesModel::inputDataChanged, this, &Menu::reload);
    connect(this, &QMenu::triggered, this, [this](QAction *action) {
        Q_D(Menu);
        const int row = action->property("row").toInt();
        Q_EMIT aboutToShare();
        d->trigger(row);
    });
}

void Menu::reload()
{
    Q_D(Menu);
    clear();

    const auto getSortedModelIndices = [d] {
        QList<QModelIndex> indices;
        for (int i = 0, c = d->m_model->rowCount(); i != c; ++i) {
            indices << d->m_model->index(i);
        }
        std::sort(indices.begin(), indices.end(), [](const QModelIndex &left, const QModelIndex &right) {
            return left.data(AlternativesModel::ActionDisplayRole).toString() < right.data(AlternativesModel::ActionDisplayRole).toString();
        });

        return indices;
    };

    const QList<QModelIndex> sortedIndices = getSortedModelIndices();

    for (const QModelIndex &idx : sortedIndices) {
        QAction *a = addAction(idx.data(AlternativesModel::ActionDisplayRole).toString());
        a->setToolTip(idx.data(Qt::ToolTipRole).toString());
        a->setIcon(idx.data(Qt::DecorationRole).value<QIcon>());
        a->setProperty("pluginId", idx.data(AlternativesModel::PluginIdRole));
        a->setProperty("row", idx.row());
    }

    setEnabled(!isEmpty());
}

AlternativesModel *Menu::model() const
{
    Q_D(const Menu);
    return d->m_model.data();
}

#include "menu.moc"
#include "moc_menu.cpp"
