/*
 * @Author: yushuoqi yushuoqi@kylinos.cn
 * @Date: 2024-04-11 20:24:44
 * @LastEditors: yushuoqi yushuoqi@kylinos.cn
 * @LastEditTime: 2024-04-18 21:28:14
 * @FilePath: /kaiming/app/dbus/KMSystemServerAdaptor.cpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
/**
 * @brief main.cpp
 */

#include "autogenserveradaptor.h"

#include <stdlib.h>
#include <syslog.h>
#include <unistd.h>

#include <functional>
#include <iostream>
#include <list>
#include <memory>
#include <string>
#include <thread>

#include "app/info/KMInfoCommand.h"
#include "app/install/KMInstall.h"
#include "app/uninstall/KMUninstall.h"
#include "app/update/KMUpdate.h"
#include "common/KMLogger.h"
#include "common/KMError.h"
#include "common/KMPackageManager.h"

using namespace org::kylin::kaiming;
using namespace std;

#define KAIMING_DBUS_SERVICE "org.kylin.kaiming"
#define KAIMING_DBUS_PATH "/org/kylin/kaiming"
#define KAIMING_DBUS_INTERFACE "org.kylin.kaiming.interface"

static std::map<int, std::string> errorCodes = {
    { KM_ERROR_NO, "没有错误，操作成功" },
    { KM_ERROR_CHECK_ENV_FAILED, "检测系统环境失败" },
    { KM_ERROR_GET_SUMMARY_COMMIT_FAILED, "得到摘要commit失败" },
    { KM_ERROR_INVALID_ARGS, "非法传入参数" },
    { KM_ERROR_NEED_NEW_VERSION, "软件包或运行时需要更新的版本" },
    { KM_ERROR_ALREADY_INSTALLED, "系统已安装该软件包" },
    { KM_ERROR_NOT_INSTALLED, "系统未安装软件包" },
    { KM_ERROR_INSTALL_ONLY_PULLED, "软件包或运行时只拉取到本地仓库，但不安装" },
    { KM_ERROR_DIFFERENT_REMOTE, "软件包或运行时已安装，但是来自于不同的远程仓库源" },
    { KM_ERROR_INSTALL_SKIPPED, "软件包运行或软件或运行时因为更早的错误跳过安装" },
    { KM_ERROR_REMOTE_NOT_FOUND, "未找到具体的远程仓库源" },
    { KM_ERROR_RUNTIME_NOT_FOUND, "未找到运行时" },
    { KM_ERROR_REF_NOT_FOUND, "未找到完整的ref引用" },
    { KM_ERROR_REF_COMMIT_NOT_FOUND, "未找到ref对应的commit信息" },
    { KM_ERROR_DOWNGRADE, "拉取的commit是一个更新包，但更新包不被允许安装" },
    { KM_ERROR_INVALID_REF, "非法的ref引用" },
    { KM_ERROR_INVALID_DATA, "非法的数据" },
    { KM_ERROR_SETUP_FAILED, "沙箱建立失败" },
    { KM_ERROR_EXPORT_FAILED, "导出数据失败" },
    { KM_ERROR_REMOTE_USED, "远程仓库不允许卸载" },
    { KM_ERROR_RUNTIME_USED, "运行时不允许被卸载" },
    { KM_ERROR_INVALID_NAME, "非法的软件包、运行时或仓库源名称" },
    { KM_ERROR_OUT_OF_SPACE, "磁盘用尽，需要更多磁盘空间" },
    { KM_ERROR_WRONG_USER, "错误用户试图操作，比如非root用户试图执行root权限操作" },
    { KM_ERROR_NOT_CACHED, "得到摘要失败" },
    { KM_ERROR_PERMISSION_DENIED, "由于系统策略，该操作不被允许" },
    { KM_ERROR_DECOMPRESSION_FAILED, "文件解压失败" },
    { KM_ERROR_CURL_DOWNLOAD_FAILED, "curl下载文件失败" },
    { KM_ERROR_LOAD_FILE_FAILED, "加载文件失败" },
    { KM_ERROR_GET_SUBSUMMARY_GVARIANT_FAILED, "解析摘要信息失败" },
    { KM_ERROR_GET_REF_INFO_FAILED, "获取ref信息失败" },
    { KM_ERROR_NO_COLLECTIONID, "没有collection id" },
    { KM_ERROR_NOTHING_TO_DO, "无事可做" },
    { KM_ERROR_GET_COMMIT_DATA_FAILED, "获取commit数据失败" },
    { KM_ERROR_DEPLOY_DATA_FAILED, "部署数据到系统失败" },
    { KM_ERROR_FOUND_REMOTE_REF_FAILED, "未找到远程仓库对应的ref" },
    { KM_ERROR_DELETE_EXPORT_FILES_FAILED, "删除exports文件失败" },
    { KM_ERROR_DELETE_DIRECTORY_FAILED, "删除目录失败" },
    { KM_ERROR_DELETE_DEPLOY_TAG_FAILED, "删除deploy tag失败" },
    { KM_ERROR_DELETE_REF_TAG_FAILED, "删除ref tag失败" },
    { KM_ERROR_PRUNE_REPO_FAILED, "精简仓库失败" },
    { KM_ERROR_NOT_NEED_UPDATE, "不需要更新" },
    { KM_ERROR_LOAD_METADATA_FILE_FAILED, "加载 metadata 文件失败" },
    { KM_ERROR_UNINSTALL_FAILED, "卸载应用失败" },
};

static std::string getErrorMessage(int errorCode)
{
    if (errorCodes.find(errorCode) != errorCodes.end())
    {
        return errorCodes[errorCode];
    }
    else
    {
        return "未知错误";
    }
}

typedef struct _PackageInfo
{
    std::string name;
    std::string branch;
    std::string version;
    size_t packageSize;
} packageInfo;

typedef struct _AdaptorProgressStatus
{
    std::string refId;
    int progress;
    std::string speed;
    int timeout;
} AdaptorProgressStatus;

typedef enum
{
    KM_INSTALL_OPERATION = 0, // 安装操作
    KM_UPDATE_OPERATION,      // 升级操作
    KM_UNINSTALL_OPERATION,   // 卸载操作
} KMOperationType;

typedef std::function<void(AdaptorProgressStatus progressStatus)> progressCallBack;

class KMSystemServerAdaptor;

class KMSystemServerAdaptor : public interface_adaptor, public DBus::ObjectAdaptor, public DBus::IntrospectableAdaptor
{
public:
    KMSystemServerAdaptor(DBus::Connection &connection, const std::string &path)
        : interface_adaptor()
        , DBus::ObjectAdaptor(connection, path)
        , IntrospectableAdaptor() // public DBus::IntrospectableAdaptor 必须，否则 d-feet 会显示不出内容，查看接口信息也是空的
    {
        m_install = shared_ptr<KMPackageManager>(new KMPackageManager());
        m_update = shared_ptr<KMUpdate>(new KMUpdate());
        uninstaller = shared_ptr<KMUninstall>(new KMUninstall());
        m_update = shared_ptr<KMUpdate>(new KMUpdate());
        m_kmLocalInfo = shared_ptr<KMInfoCommand>(new KMInfoCommand());
        m_kmRemoteInfo = shared_ptr<KMInfoCommand>(new KMInfoCommand());
        m_kmPackageManager = shared_ptr<KMPackageManager>(new KMPackageManager());
    }

    ~KMSystemServerAdaptor() { }

    bool install(const std::string &name, const std::string &branch) override
    {
        kmlogger.info("begin call install api, m_installRunningFlag=%d", m_installRunningFlag);
        if (m_installRunningFlag)
        {
            return false;
        }

        m_installRunningFlag = true;

        // 创建回调函数，负责发送信号
        std::function<void(const std::string &)> callback = [this](const std::string &progressJson)
        {
            // 发送信号，这里使用模拟的数据
            AdaptorProgressStatus ps;

            kmlogger.info("receive jsonData: %s", progressJson.c_str());
            // KMJsonHelper::unpackFromJson(progressJson, ps.refId, ps.progress, ps.speed, ps.timeout); // 反序列有问题，先传json字符串信号
            // kmlogger.info("refId:%s progress:%d speed:%s timeout:%d", ps.refId.c_str(), ps.progress, ps.speed.c_str(), ps.timeout);

            progresschangesignal(progressJson);
        };

        kmlogger.info("begin install");

        // 创建一个 std::thread 对象，并将 lambda 表达式作为其构造函数的参数传递给它，包括this指针
        std::thread ti(
          [=]()
          {
              int installErrorNumber;
              // lambda 表达式中的代码将在新线程中执行
              std::cout << "Install thread!" << std::endl;
              // 调用真实安装函数，并传递回调函数,不阻塞主线程，在子线程中异步处理
              int ret = m_install->installSoftwareCenter(name, branch, installErrorNumber, callback);
              kmlogger.info("before emit install signal");
              finishsignal(name, KM_INSTALL_OPERATION, ret, getErrorMessage(ret));
              this->m_installRunningFlag = false;
              kmlogger.info("end emit install signal, m_installRunningFlag = %d", this->m_installRunningFlag);
              this->m_installThread.detach();
          });

        m_installThread = std::move(ti);

        kmlogger.info("begin emit installsignal");

        return true;
    }

    bool update(const std::string &name, const std::string &branch) override
    {
        kmlogger.info("begin call update api, m_updateRunningFlag=%d", m_updateRunningFlag);
        if (m_updateRunningFlag)
        {
            return false;
        }

        m_updateRunningFlag = true;

        // 创建回调函数，负责发送信号
        std::function<void(const std::string &)> updatecallback = [this](const std::string &progressJson)
        {
            // 发送信号，这里使用模拟的数据
            AdaptorProgressStatus ps;

            kmlogger.info("receive jsonData: %s", progressJson.c_str());
            // KMJsonHelper::unpackFromJson(progressJson, ps.refId, ps.progress, ps.speed, ps.timeout); // 反序列有问题，先传json字符串信号
            // kmlogger.info("refId:%s progress:%d speed:%s timeout:%d", ps.refId.c_str(), ps.progress, ps.speed.c_str(), ps.timeout);

            progresschangesignal(progressJson);
        };

        kmlogger.info("begin update");

        // 创建一个 std::thread 对象，并将 lambda 表达式作为其构造函数的参数传递给它，包括this指针
        std::thread tupdate(
          [=]()
          {
              int updateErrorNumber;
              // lambda 表达式中的代码将在新线程中执行
              std::cout << "update thread!" << std::endl;
              // 调用真实安装函数，并传递回调函数,不阻塞主线程，在子线程中异步处理
              int ret = m_update->update(name, branch, updateErrorNumber, updatecallback);
              kmlogger.info("before emit update signal");
              finishsignal(name, KM_UPDATE_OPERATION, ret, getErrorMessage(ret));
              this->m_updateRunningFlag = false;
              kmlogger.info("end emit update signal, m_updateRunningFlag = %d", this->m_updateRunningFlag);
              this->m_updateThread.detach();
          });

        m_updateThread = std::move(tupdate);

        kmlogger.info("begin emit updatesignal");

        return true;
    }

    bool uninstall(const std::string &name, const std::string &branch)
    {
        kmlogger.info("begin call uninstall api, m_installRunningFlag=%d", m_installRunningFlag);
        if (m_uninstallRunningFlag)
        {
            return false;
        }

        m_uninstallRunningFlag = true;

        std::thread tu(
          [=]()
          {
              int ret = uninstaller->process(vector<string>{ name });
              kmlogger.info("before emit uninstall signal");
              finishsignal(name, KM_UNINSTALL_OPERATION, ret, getErrorMessage(ret));
              kmlogger.info("end emit uninstall signal");

              this->m_uninstallRunningFlag = false;
              kmlogger.info("end emit uninstall signal, m_uninstallRunningFlag = %d", this->m_uninstallRunningFlag);
              this->m_uninstallThread.detach();
          });

        m_uninstallThread = std::move(tu);

        return true;
    }

    string getLocalInfo(const string &name)
    {
        kmlogger.info("begin call getLocalInfo api");

        // std::thread tlocalinfo([=]()
        //                {
        int errorCode;

        string localInfoJson = m_kmLocalInfo->getLocalInfo(name, errorCode);

        kmlogger.info("before emit getLocalInfo signal");
        getlocalinfosignal(name, localInfoJson, errorCode, getErrorMessage(errorCode));
        kmlogger.info("end emit getLocalInfo signal");

        //                    this->m_localInfoThread.detach();
        //                });

        // m_localInfoThread = std::move(tlocalinfo);

        return localInfoJson;
    }

    /*
     * 软件商店通过直接返回字符串中branch是否为空判断查询结果是否正确，而不是通过发出的信号
     *
     * branch为空： 返回信息失败
     * branch不为空： 返回信息正确后，另外商店也能获取到发布平台发布的应用信息，商店就可以正确显示该应用
     */
    string getRemoteInfo(const string &name)
    {
        kmlogger.info("begin call getRemoteInfo api");

        // std::thread tremoteinfo([=]()
        //                {
        int errorCode;

        string remoteInfoJson = m_kmRemoteInfo->getRemoteInfo(name, errorCode);

        kmlogger.info("before emit getRemoteInfo signal");
        getremoteinfosignal(name, remoteInfoJson, errorCode, getErrorMessage(errorCode));
        kmlogger.info("end emit getRemoteInfo signal");

        //    this->m_remoteInfoThread.detach();
        //                });

        // m_remoteInfoThread = std::move(tremoteinfo);

        return remoteInfoJson;
    }

    bool isInstalled(const string &name)
    {
        kmlogger.info("begin call isInstalled api");

        // std::thread tisinstalled([=]()
        //                {
        int errorCode;
        bool isInstall = false;

        errorCode = m_kmPackageManager->isInstalled(name);
        if (errorCode == KM_ERROR_NO)
        {
            isInstall = true;
        }

        kmlogger.info("before emit isInstalled signal");
        isinstalledsignal(name, isInstall, errorCode, getErrorMessage(errorCode));
        kmlogger.info("end emit isInstalled signal");

        //    this->m_isInstalledThread.detach();
        //                });

        // m_isInstalledThread = std::move(tisinstalled);

        return isInstall;
    }

    bool isUpgradable(const string &name)
    {
        kmlogger.info("begin call isUpgradable api");

        // std::thread tisupgradable([=]()
        //                {
        int errorCode;
        bool isUpgradabled = false;

        errorCode = m_update->isUpgradabled(name);
        if (errorCode == KM_ERROR_NO)
        {
            isUpgradabled = true;
        }

        kmlogger.info("before emit isUpgradable signal");
        isupgradablesignal(name, isUpgradabled, errorCode, getErrorMessage(errorCode));
        kmlogger.info("end emit isUpgradable signal");

        //                    this->m_isUpgradableThread.detach();
        //                });

        // m_isUpgradableThread = std::move(tisupgradable);

        return isUpgradabled;
    }

private:
    shared_ptr<KMPackageManager> m_install;     // 安装
    shared_ptr<KMUninstall> uninstaller;      // 卸载
    shared_ptr<KMUpdate> m_update;            // 更新
    shared_ptr<KMInfoCommand> m_kmLocalInfo;  // 获取本地信息
    shared_ptr<KMInfoCommand> m_kmRemoteInfo; // 获取远程信息
    shared_ptr<KMPackageManager> m_kmPackageManager; // 开明包管理

    std::thread m_installThread;
    bool m_installRunningFlag = false;

    std::thread m_updateThread;
    bool m_updateRunningFlag = false;

    std::thread m_uninstallThread;
    bool m_uninstallRunningFlag = false;

    std::thread m_localInfoThread;
    std::thread m_remoteInfoThread;
    std::thread m_isInstalledThread;
    std::thread m_isUpgradableThread;
};

int main()
{
    DBus::BusDispatcher dispatcher;
    DBus::default_dispatcher = &dispatcher;

    DBus::Connection connection = DBus::Connection::SystemBus();
    if (!connection.register_bus())
    {
        std::cerr << "fialed to register_bus";
        return 0;
    }

    std::cerr << "连接状态: " << connection.connected() << std::endl;

    connection.request_name(KAIMING_DBUS_SERVICE); // .service 服务文件名 :  /usr/share/dbus-1/system-services/com.kylin.UpgradeStrategies.service
    std::cerr << "连接名: " << KAIMING_DBUS_SERVICE << std::endl;

    // 创建服务对象并注册到总线上
    KMSystemServerAdaptor adaptor(connection, KAIMING_DBUS_PATH);

    kmlogger.info("befor enter dispatcher.");

    // 设置超时时间为10秒
    // connection.set_timeout(10000);

    // 运行事件循环
    while (true)
    {
        dispatcher.enter();
        dispatcher.leave();
    }

    kmlogger.info("before exit 0");

    return 0;
}
