#pragma once

#include "SystemRecovery.h"
#include "UserDataRecovery.h"
#include "DimFileRecovery.h"
#include "UImgRecovery.h"
#include "utils/Device.h"
#include "BRContext.h"
#include <QObject>
#include <QString>
#include <QDBusContext>

class OSTreeWorkerThread;
class WorkerThread;

class RecoveryService : public QObject, public QDBusContext
{
    Q_OBJECT
    Q_CLASSINFO("D-Bus Interface", "com.deepin.daemon.uosrecovery")
public:
    explicit RecoveryService(QObject* parent  = nullptr);
    virtual ~RecoveryService();

    //是否运行于live系统
    Q_SCRIPTABLE bool IsInLive();

    Q_SCRIPTABLE QString ListPartition(bool removable = false);

    Q_SCRIPTABLE QString GetPartition(const QString & uuid);

    //获取待备份系统的根分区UUID
    Q_SCRIPTABLE QString GetRootUUID();

    bool IsRootfs(const QString &rootUUID);

    //获取存储备份文件的设备uuid
    Q_SCRIPTABLE QString GetBackupDeviceUUID(const QString &rootUUID);

    // 设置备份文件存储位置的设备UUID，并校验可用磁盘空间
    Q_SCRIPTABLE int SetBackupDeviceUUID(const QString &deviceUUID);

    Q_SCRIPTABLE int AutoInitSystemRecoveryType(const QString &rootUUID);

    //备份系统
    //Q_SCRIPTABLE int SystemBackup(const QString &request);

    Q_SCRIPTABLE int BackupV20(const V20BackupReq &request);
    Q_SCRIPTABLE int SystemRestoreV20(const V20RestoreReq &request);
    Q_SCRIPTABLE int CancelBackupOrRestore20(const V20BackupReq &request);
    Q_SCRIPTABLE int Remove(const V20BackupReq &request);
    Q_SCRIPTABLE int SystemBackup(const SystemBackupRequest &request);
    Q_SCRIPTABLE int SystemRestore(const SystemRestoreRequest &request);

    //数据备份
    Q_SCRIPTABLE int UserDataBackup(const UserDataBackupRequest &request);
    // 数据备份空间校验
    Q_SCRIPTABLE int CheckUserDataBackupSpace(const UserDataBackupRequest &request);

    //查询磁盘上的备份文件
    Q_SCRIPTABLE QString ListSystemBackup();

    Q_SCRIPTABLE QString CheckBackupDiskSpace(const QString &rootUUID, const QString &backupDeviceUUID);

    // 校验ghost备份空间
    Q_SCRIPTABLE int CheckGhostBackupDiskSpace(const QString &selectDir);

    // 系统全量备份空间校验
    Q_SCRIPTABLE int CheckFullSystemBackupDiskSpace(const QString &rootUUID, const QString &backupDeviceUUID);

    // 系统增量备份空间校验
    Q_SCRIPTABLE int CheckIncSystemBackupSpace(const QString &backupDeviceUUID);
    Q_SCRIPTABLE int CheckIncSystemBackupSpace(const SystemBackupRequest &request);

    //Q_SCRIPTABLE int SystemRestore(const QString &request);

    Q_SCRIPTABLE int UserDataRestore(const UserDataRestoreRequest &request);
    Q_SCRIPTABLE void Reboot();
    Q_SCRIPTABLE QString ListUserDataBackup(const QString &username);
    Q_SCRIPTABLE int RemoveBackupInfo(const UserDataRestoreRequest &request);
    Q_SCRIPTABLE int CreateUImg(const SystemCloneRequest &request);
    Q_SCRIPTABLE QString QueryUImgBackup(const GhostLogQuery &request);
    Q_SCRIPTABLE int GetSystemSyncType();
    Q_SCRIPTABLE int GetUserDataSyncType();
    Q_SCRIPTABLE QString ListOperateLogs(const OperateLogQuery &request);
    Q_SCRIPTABLE bool IsRunning();
    Q_SCRIPTABLE int GetContext(QString &operateID, QString &userName, int &opType, int &progress);
    Q_SCRIPTABLE int OStreeFactoryRestore(const SystemRestoreRequest &request);
    Q_SCRIPTABLE void ClearRollbackAutoNotify();
    Q_SCRIPTABLE bool HasInitBackDimFile();
    Q_SCRIPTABLE int DimFileToLoopDeviceFile(const QString &dimFilePath, const QString &imgFilePath);
    Q_SCRIPTABLE int ClearDimFileRestoreCfg(const QString &imgFilePath);
    Q_SCRIPTABLE int CheckDimFileSpace(const QString &dimFilesPath);

Q_SIGNALS:
    void ReportProgress(const QString &progress);
    void ReportSpace(const QString &space);
    void Error(const QString &errMsg);
    void Success(const QString &msg);
    void ReportCheckSpace(const QString &space);
private:
    int SystemBackup(const QString &request);
    int SystemRestore(const QString &request);
    void onReportProgress(const QString &progress);
    void onReportSpace(const QString &space);
    void onError(const QString &errMsg);
    void onSuccess(const QString &msg);
    void onReportCheckSpace(const QString &space);
    //ErrorCode CreateUserDataRecovery();
    //运行于live系统时,挂载真实系统根分区
    //bool MountRoot(const QString &rootUUID);
    //运行于live系统时,根据fstab挂载其他分区
    bool MountByFstab(const QString &rootPath);
    void FillErrMsg(ErrorCode errCode, quint64 backupSizeBytes, int liveFlag,
                    const QString &errMsg, QString &jsonContent);
    bool GetSystemBackupDirSizeBytes(const QString &rootUUID, const QString &backupDeviceUUID, const QString &dirPath,
                                     const QStringList &excludeDir, quint64 &totalBytes, QString &errMsg);
    ErrorCode GetMountPointByUUID(const QString & srcUUID, QString &mountPoint);
    ErrorCode InitSystemBackupType();
    ErrorCode InitUserDataBackupType();
    //QString ErrorString(ErrorCode errorCode);
    void partition2DiskArray(const QMap<QString, DeviceList> &partitionMap, QJsonArray &diskArray,
                             bool removable, bool isLvm);
    bool checkCaller();
    bool checkUuidInFstab(const QString &uuid, const QString &rootmnt = "/");
private:
    SystemRecoveryPtr m_pSystemRecovery;
    UserDataRecoveryPtr m_pUserDataRecovery;
    DimFileRecoveryPtr m_pDimFileRecovery;
    UImgRecoveryPtr m_pUImgRecovery;
    DeviceInfoList m_allDevice;
    FSTabInfoList m_fsTabInfoList;
    QString m_rootUUID;
    QString m_recoveryConf;
    QMap<QString, pid_t> m_registeredProcNameMap;
    int m_systemSyncType = -1;
    int m_userDataSyncType = -1;
    QMap<QString, int> m_opIDProgress;
    OSTreeWorkerThread *m_ostreeWorker = nullptr;
    WorkerThread *m_recoveryThread = nullptr;
    bool m_isImmutableSys = false;
};
