#ifndef LEGACYPATCH_H
#define LEGACYPATCH_H

#include <QObject>

#include "models/downloader.h"
#include "models/filesystem.h"
#include "models/lotrodatmanager.h"
#include "models/settings.h"

class Patch : public QObject
{
    Q_OBJECT

public:
    enum class CurrentProcess {
        E_AWAITING_INSTALL,
        E_INSTALL,
        E_AWAITING_APPLY,
        E_APPLY,
        E_FINISHED
    };

    struct InstallationStatus {
        CurrentProcess process = CurrentProcess::E_FINISHED;
        int current_part = 0; // Ex. "installation (current_part/total_parts) percent%"
        int total_parts = 0;
        double percent = 0;
        QString debug_msg = "";
    };

    friend InstallationStatus operator+(const InstallationStatus &a, const InstallationStatus &b) {
        InstallationStatus result = {
            CurrentProcess::E_INSTALL,
            a.current_part + b.current_part,
            a.total_parts + b.total_parts,
            (100.0 * double(a.current_part - 1 + b.current_part - 1) + a.percent + b.percent) / double(a.total_parts + b.total_parts),
            QString()
        };

        return result;
    }

public:
    explicit Patch(QString patch_name, LotroDatManager* mgr, QObject *parent);

    QString getPatchName();

public slots: // WARNING: THESE CAN BE NON-BLOCKING OPERATIONS! Use them in chain only via operationFinished signal handlers.

    virtual void checkForUpdates() = 0; // Checks for updates. Updates patches info in Settings.
    virtual void download() = 0; // Downloads patch contents, prepared for installation.
    virtual void install() = 0; // Installs patch into game resources (need to be enabled after install to be activated)
    virtual void activate() = 0; // Activates (or deactivates) patch components based on user preferences (patch needs to be installed)

signals: // each signal brings with it pointer to this class

    void operationStarted(QString operation_name, Patch* patch);
    void errorOccured(QString operation_name, Patch* patch, QString msg);
    void operationFinished(QString operation_name, Patch* patch, bool result);

    void downloadStatusChanged(Patch* patch, Downloader::Status status);
    void installStatusChanged(Patch* patch, InstallationStatus status);

protected:
    bool needDownloadDatabase(QString db_name);

    static bool isDatabaseDownloadEnabled(QString db_name); // Checks if this database needs to be downloaded (comparing with user parameters)

protected:
    LotroDatManager* lotro_mgr_;
    QString patch_name_;
    QSet<Downloader*> downloaders_;
    InstallationStatus status_;
};

#endif // LEGACYPATCH_H
