From c1490cd62703975c5478aea1156d0bbefcc37bc8 Mon Sep 17 00:00:00 2001
From: Trial97 <alexandru.tripon97@gmail.com>
Date: Thu, 20 Apr 2023 00:57:09 +0300
Subject: Refator task to work with multiple providers

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
---
 .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 201 +++++++++++++--------
 .../minecraft/mod/tasks/GetModDependenciesTask.h   |  62 ++++---
 .../minecraft/mod/tasks/LocalModGetAllTask.cpp     |  52 ------
 launcher/minecraft/mod/tasks/LocalModGetAllTask.h  |  45 -----
 4 files changed, 161 insertions(+), 199 deletions(-)
 delete mode 100644 launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp
 delete mode 100644 launcher/minecraft/mod/tasks/LocalModGetAllTask.h

(limited to 'launcher/minecraft/mod/tasks')

diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
index 7f184765..966eea19 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp
@@ -20,90 +20,74 @@
 #include "GetModDependenciesTask.h"
 
 #include <QDebug>
+#include <algorithm>
+#include <memory>
+#include "Json.h"
 #include "QObjectPtr.h"
 #include "minecraft/mod/MetadataHandler.h"
-#include "minecraft/mod/tasks/LocalModGetAllTask.h"
 #include "modplatform/ModIndex.h"
+#include "modplatform/flame/FlameAPI.h"
+#include "modplatform/modrinth/ModrinthAPI.h"
 #include "tasks/ConcurrentTask.h"
 #include "tasks/SequentialTask.h"
+#include "ui/pages/modplatform/ModModel.h"
+#include "ui/pages/modplatform/flame/FlameResourceModels.h"
+#include "ui/pages/modplatform/modrinth/ModrinthResourceModels.h"
 
-GetModDependenciesTask::GetModDependenciesTask(QDir index_dir, QList<ModPlatform::IndexedVersion> selected, NewDependecyVersionAPITask api)
-    : m_selected(selected), m_getDependenciesVersionAPI(api)
+static Version mcVersions(BaseInstance* inst)
 {
-    m_getAllMods = makeShared<LocalModGetAllTask>(index_dir);
-    m_getNetworkDep = makeShared<SequentialTask>(this, "GetDepInfo");
-    connect(m_getNetworkDep.get(), &Task::finished, &loop, &QEventLoop::quit);
-    QObject::connect(m_getAllMods.get(), &LocalModGetAllTask::getAllMods, [this](QList<Metadata::ModStruct> mods) {
-        m_mods = mods;
-        prepareDependecies();
-    });
+    return static_cast<MinecraftInstance*>(inst)->getPackProfile()->getComponent("net.minecraft")->getVersion();
 }
 
-void GetModDependenciesTask::executeTask()
+static ResourceAPI::ModLoaderTypes mcLoaders(BaseInstance* inst)
 {
-    setStatus(tr("Geting all mods"));
-    m_getAllMods->start();
-    loop.exec();
-    emitSucceeded();
+    return static_cast<MinecraftInstance*>(inst)->getPackProfile()->getModLoaders().value();
 }
 
-auto GetModDependenciesTask::abort() -> bool
+GetModDependenciesTask::GetModDependenciesTask(QObject* parent,
+                                               BaseInstance* instance,
+                                               ModFolderModel* folder,
+                                               QList<std::shared_ptr<PackDependecny>> selected)
+    : SequentialTask(parent, "Get dependencies"), m_selected(selected), m_version(mcVersions(instance)), m_loaderType(mcLoaders(instance))
 {
-    emitAborted();
-    return true;
-}
+    m_providers.append(Provider{ ModPlatform::ResourceProvider::FLAME, std::make_shared<ResourceDownload::FlameModModel>(*instance),
+                                 std::make_shared<FlameAPI>() });
+    m_providers.append(Provider{ ModPlatform::ResourceProvider::MODRINTH, std::make_shared<ResourceDownload::ModrinthModModel>(*instance),
+                                 std::make_shared<ModrinthAPI>() });
+    for (auto mod : folder->allMods())
+        m_mods.append(mod->metadata());
+    prepare();
+};
 
-void GetModDependenciesTask::prepareDependecies()
+void GetModDependenciesTask::prepare()
 {
-    auto c_dependencies = getDependenciesForVersions(m_selected);
-    if (c_dependencies.length() == 0) {
-        m_getNetworkDep->start();
-        return;
-    }
-    for (auto dep : c_dependencies) {
-        auto task =
-            m_getDependenciesVersionAPI(dep, [this](const ModPlatform::IndexedVersion& new_version) { addDependecies(new_version, 20); });
-        m_getNetworkDep->addTask(task);
+    for (auto sel : m_selected) {
+        for (auto dep : getDependenciesForVersion(sel->version, sel->pack.provider)) {
+            addTask(prepareDependencyTask(dep, sel->pack.provider, 20));
+        }
     }
-    m_getNetworkDep->start();
 }
 
-void GetModDependenciesTask::addDependecies(const ModPlatform::IndexedVersion& new_version, int level)
-{
-    // some mutex?
-    m_dependencies.append(new_version);
-    auto c_dependencies = getDependenciesForVersion(new_version);
-    if (c_dependencies.length() == 0) {
-        return;
-    }
-    if (level == 0) {
-        qWarning() << "Dependency cycle exeeded";
-        return;
-    }
-    for (auto dep : c_dependencies) {
-        auto task = m_getDependenciesVersionAPI(
-            dep, [this, level](const ModPlatform::IndexedVersion& new_versions) { addDependecies(new_versions, level - 1); });
-        m_getNetworkDep->addTask(task);
-    }
-};
-
-QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersions(const QList<ModPlatform::IndexedVersion>& selected)
+QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion(const ModPlatform::IndexedVersion& version,
+                                                                                 const ModPlatform::ResourceProvider providerName)
 {
     auto c_dependencies = QList<ModPlatform::Dependency>();
-    for (auto version : selected) {
-        for (auto ver_dep : version.dependencies) {
-            if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) {
-                if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(),
-                                            [&ver_dep](const auto& i) { return i.addonId == ver_dep.addonId; });
-                    dep == c_dependencies.end()) {  // check the current dependency list
-                    if (auto dep = std::find_if(selected.begin(), selected.end(),
-                                                [&ver_dep](const auto& i) { return i.addonId == ver_dep.addonId; });
-                        dep == selected.end()) {  // check the selected versions
-                        if (auto dep = std::find_if(m_mods.begin(), m_mods.end(),
-                                                    [&ver_dep](const auto& i) { return i.project_id == ver_dep.addonId; });
-                            dep == m_mods.end()) {  // check the existing mods
-                            c_dependencies.append(ver_dep);
-                        }
+    for (auto ver_dep : version.dependencies) {
+        if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) {
+            if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(),
+                                        [&ver_dep](const ModPlatform::Dependency& i) { return i.addonId == ver_dep.addonId; });
+                dep == c_dependencies.end()) {  // check the current dependency list
+                if (auto dep = std::find_if(m_selected.begin(), m_selected.end(),
+                                            [&ver_dep, providerName](std::shared_ptr<PackDependecny> i) {
+                                                return i->pack.addonId == ver_dep.addonId && i->pack.provider == providerName;
+                                            });
+                    dep == m_selected.end()) {  // check the selected versions
+                    if (auto dep = std::find_if(m_mods.begin(), m_mods.end(),
+                                                [&ver_dep, providerName](std::shared_ptr<Metadata::ModStruct> i) {
+                                                    return i->project_id == ver_dep.addonId && i->provider == providerName;
+                                                });
+                        dep == m_mods.end()) {  // check the existing mods
+                        c_dependencies.append(ver_dep);
                     }
                 }
             }
@@ -112,21 +96,80 @@ QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion
     return c_dependencies;
 };
 
-QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion(const ModPlatform::IndexedVersion& version)
+Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Dependency& dep,
+                                                        const ModPlatform::ResourceProvider providerName,
+                                                        int level)
 {
-    auto c_dependencies = QList<ModPlatform::Dependency>();
-    for (auto ver_dep : version.dependencies) {
-        if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) {
-            if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(),
-                                        [&ver_dep](const auto& i) { return i.addonId == ver_dep.addonId; });
-                dep == c_dependencies.end()) {  // check the current dependency list
-                if (auto dep =
-                        std::find_if(m_mods.begin(), m_mods.end(), [&ver_dep](const auto& i) { return i.project_id == ver_dep.addonId; });
-                    dep == m_mods.end()) {  // check the existing mods
-                    c_dependencies.append(ver_dep);
-                }
+    auto pDep = std::make_shared<PackDependecny>();
+    pDep->dependency = dep;
+    pDep->pack = { dep.addonId, providerName };
+    m_pack_dependencies.append(pDep);
+    auto provider =
+        std::find_if(m_providers.begin(), m_providers.end(), [providerName](const Provider& p) { return p.name == providerName; });
+    // if (provider == m_providers.end()) {
+    //     qWarning() << "Unsuported provider for dependency check";
+    //     return nullptr;
+    // }
+
+    auto tasks = makeShared<SequentialTask>(this, QString("DependencyInfo: %1").arg(dep.addonId.toString()));
+
+    auto responseInfo = new QByteArray();
+    auto info = provider->api->getProject(dep.addonId.toString(), responseInfo);
+    QObject::connect(info.get(), &NetJob::succeeded, [responseInfo, provider, pDep] {
+        QJsonParseError parse_error{};
+        QJsonDocument doc = QJsonDocument::fromJson(*responseInfo, &parse_error);
+        if (parse_error.error != QJsonParseError::NoError) {
+            qWarning() << "Error while parsing JSON response for mod info at " << parse_error.offset
+                       << " reason: " << parse_error.errorString();
+            qWarning() << *responseInfo;
+            return;
+        }
+        try {
+            auto obj = provider->name == ModPlatform::ResourceProvider::FLAME ? Json::requireObject(Json::requireObject(doc), "data")
+                                                                              : Json::requireObject(doc);
+            provider->mod->loadIndexedPack(pDep->pack, obj);
+        } catch (const JSONValidationError& e) {
+            qDebug() << doc;
+            qWarning() << "Error while reading mod info: " << e.cause();
+        }
+    });
+    tasks->addTask(info);
+
+    ResourceAPI::DependencySearchArgs args = { dep, m_version, m_loaderType };
+    ResourceAPI::DependencySearchCallbacks callbacks;
+
+    callbacks.on_succeed = [dep, provider, pDep, level, this](auto& doc, auto& pack) {
+        try {
+            QJsonArray arr;
+            if (dep.version.length() != 0 && doc.isObject()) {
+                arr.append(doc.object());
+            } else {
+                arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array();
+            }
+            pDep->version = provider->mod->loadDependencyVersions(dep, arr);
+            if (!pDep->version.addonId.isValid()) {
+                qWarning() << "Error while reading mod version empty ";
+                qDebug() << doc;
+                return;
             }
+            pDep->version.is_currently_selected = true;
+            pDep->pack.versions = { pDep->version };
+            pDep->pack.versionsLoaded = true;
+        } catch (const JSONValidationError& e) {
+            qDebug() << doc;
+            qWarning() << "Error while reading mod version: " << e.cause();
+            return;
         }
-    }
-    return c_dependencies;
-};
\ No newline at end of file
+        if (level == 0) {
+            qWarning() << "Dependency cycle exeeded";
+            return;
+        }
+        for (auto dep : getDependenciesForVersion(pDep->version, provider->name)) {
+            addTask(prepareDependencyTask(dep, provider->name, level - 1));
+        }
+    };
+
+    auto version = provider->api->getDependencyVersion(std::move(args), std::move(callbacks));
+    tasks->addTask(version);
+    return tasks;
+};
diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
index 7f7e1fb1..d83d6e27 100644
--- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
+++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h
@@ -18,48 +18,64 @@
 
 #pragma once
 
+#include <qlist.h>
+#include <qvariant.h>
 #include <QDir>
 #include <QEventLoop>
+#include <QList>
 #include <functional>
+#include <memory>
 
 #include "minecraft/mod/MetadataHandler.h"
-#include "minecraft/mod/tasks/LocalModGetAllTask.h"
+#include "minecraft/mod/ModFolderModel.h"
 #include "modplatform/ModIndex.h"
+#include "modplatform/ResourceAPI.h"
 #include "tasks/SequentialTask.h"
 #include "tasks/Task.h"
+#include "ui/pages/modplatform/ModModel.h"
 
-class GetModDependenciesTask : public Task {
+class GetModDependenciesTask : public SequentialTask {
     Q_OBJECT
    public:
     using Ptr = shared_qobject_ptr<GetModDependenciesTask>;
-    using LocalModGetAllTaskPtr = shared_qobject_ptr<LocalModGetAllTask>;
 
-    using NewDependecyVersionAPITask =
-        std::function<Task::Ptr(const ModPlatform::Dependency&, std::function<void(const ModPlatform::IndexedVersion&)>)>;
+    struct PackDependecny {
+        ModPlatform::Dependency dependency;
+        ModPlatform::IndexedPack pack;
+        ModPlatform::IndexedVersion version;
+        PackDependecny(){};
+        PackDependecny(const ModPlatform::IndexedPack& p, const ModPlatform::IndexedVersion& v)
+        {
+            pack = p;
+            version = v;
+        }
+    };
 
-    explicit GetModDependenciesTask(QDir index_dir, QList<ModPlatform::IndexedVersion> selected, NewDependecyVersionAPITask api);
+    struct Provider {
+        ModPlatform::ResourceProvider name;
+        std::shared_ptr<ResourceDownload::ModModel> mod;
+        std::shared_ptr<ResourceAPI> api;
+    };
 
-    auto canAbort() const -> bool override { return true; }
-    auto abort() -> bool override;
+    explicit GetModDependenciesTask(QObject* parent,
+                                    BaseInstance* instance,
+                                    ModFolderModel* folder,
+                                    QList<std::shared_ptr<PackDependecny>> selected);
 
-    auto getDependecies() const -> QList<ModPlatform::IndexedVersion> { return m_dependencies; }
+    auto getDependecies() const -> QList<std::shared_ptr<PackDependecny>> { return m_pack_dependencies; }
 
    protected slots:
-    //! Entry point for tasks.
-    void executeTask() override;
-
-    void prepareDependecies();
-    void addDependecies(const ModPlatform::IndexedVersion&, int);
-    QList<ModPlatform::Dependency> getDependenciesForVersions(const QList<ModPlatform::IndexedVersion>&);
-    QList<ModPlatform::Dependency> getDependenciesForVersion(const ModPlatform::IndexedVersion&);
+    Task::Ptr prepareDependencyTask(const ModPlatform::Dependency&, const ModPlatform::ResourceProvider, int);
+    QList<ModPlatform::Dependency> getDependenciesForVersion(const ModPlatform::IndexedVersion&,
+                                                             const ModPlatform::ResourceProvider providerName);
+    void prepare();
 
    private:
-    QList<ModPlatform::IndexedVersion> m_selected;
-    QList<ModPlatform::IndexedVersion> m_dependencies;
-    QList<Metadata::ModStruct> m_mods;
+    QList<std::shared_ptr<PackDependecny>> m_pack_dependencies;
+    QList<std::shared_ptr<Metadata::ModStruct>> m_mods;
+    QList<std::shared_ptr<PackDependecny>> m_selected;
+    QList<Provider> m_providers;
 
-    LocalModGetAllTaskPtr m_getAllMods = nullptr;
-    NewDependecyVersionAPITask m_getDependenciesVersionAPI;
-    SequentialTask::Ptr m_getNetworkDep;
-    QEventLoop loop;
+    Version m_version;
+    ResourceAPI::ModLoaderTypes m_loaderType;
 };
diff --git a/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp b/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp
deleted file mode 100644
index 67058807..00000000
--- a/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-// SPDX-License-Identifier: GPL-3.0-only
-/*
- *  PolyMC - Minecraft Launcher
- *  Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
- *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
- *
- *  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, version 3.
- *
- *  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.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-#include "LocalModGetAllTask.h"
-
-#include "FileSystem.h"
-#include "minecraft/mod/MetadataHandler.h"
-
-#ifdef Q_OS_WIN32
-#include <windows.h>
-#endif
-
-LocalModGetAllTask::LocalModGetAllTask(QDir index_dir) : m_index_dir(index_dir)
-{
-    // Ensure a '.index' folder exists in the mods folder, and create it if it does not
-    if (!FS::ensureFolderPathExists(index_dir.path())) {
-        emitFailed(QString("Unable to create index for all mods!"));
-    }
-
-#ifdef Q_OS_WIN32
-    SetFileAttributesW(index_dir.path().toStdWString().c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED);
-#endif
-}
-
-void LocalModGetAllTask::executeTask()
-{
-    setStatus(tr("Geting all mods"));
-    emit getAllMods(Metadata::getAll(m_index_dir));
-    emitSucceeded();
-}
-
-auto LocalModGetAllTask::abort() -> bool
-{
-    emitAborted();
-    return true;
-}
diff --git a/launcher/minecraft/mod/tasks/LocalModGetAllTask.h b/launcher/minecraft/mod/tasks/LocalModGetAllTask.h
deleted file mode 100644
index bf4b78b7..00000000
--- a/launcher/minecraft/mod/tasks/LocalModGetAllTask.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// SPDX-License-Identifier: GPL-3.0-only
-/*
- *  PolyMC - Minecraft Launcher
- *  Copyright (c) 2022 flowln <flowlnlnln@gmail.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, version 3.
- *
- *  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.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include <QDir>
-
-#include "minecraft/mod/MetadataHandler.h"
-#include "tasks/Task.h"
-
-class LocalModGetAllTask : public Task {
-    Q_OBJECT
-   public:
-    using Ptr = shared_qobject_ptr<LocalModGetAllTask>;
-
-    explicit LocalModGetAllTask(QDir index_dir);
-
-    auto canAbort() const -> bool override { return true; }
-    auto abort() -> bool override;
-
-   protected slots:
-    //! Entry point for tasks.
-    void executeTask() override;
-
-   signals:
-    void getAllMods(QList<Metadata::ModStruct>);
-
-   private:
-    QDir m_index_dir;
-};
-- 
cgit