/*
 * Copyright (c) KylinSoft  Co., Ltd. 2024. All rights reserved.
 *
 * kaiming is licensed under the GPL v2.0+.
 * 
 * See the LICENSE file for more details.
 */

#include "KMDbusClient.h"
#include "common/KMLogger.h"
#include <nlohmann/json.hpp>

KMDbusClient::KMDbusClient()
{
    //连接服务
    GError* error = nullptr;
    connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error);
    if (!connection)
    {
        KMError(std::string("Failed to connect to system bus: ")+  error->message);
        g_error_free(error);
        exit(EXIT_FAILURE);
    }

    //获取远程对象
    proxy = g_dbus_proxy_new_sync(
        connection,
        G_DBUS_PROXY_FLAGS_NONE,
        nullptr,
        "org.kylin.kaiming",  //服务名
        "/org/kylin/kaiming", //对象路径
        "org.kylin.kaiming.interface", //接口名
        nullptr,
        &error
    );
    if (!proxy)
    {
        KMError(std::string("Failed to creat proxy: ")+  error->message);
        g_error_free(error);
        exit(EXIT_FAILURE);
    }

    // 监听 progresschangesignal 信号
    g_signal_connect(proxy, "g-signal", G_CALLBACK(on_progress_change), this);
}

KMDbusClient::~KMDbusClient()
{
    if (proxy) g_object_unref(proxy);
    if (connection) g_object_unref(connection);
}

void KMDbusClient::on_progress_change(GDBusProxy* proxy, const gchar* sender_name,
                                      const gchar* signal_name, GVariant* parameters,
                                      gpointer user_data)
{
    static int lastProgress = -1;
    if (g_strcmp0(signal_name, "progresschangesignal") == 0) {
        const gchar* progressJson;
        g_variant_get(parameters, "(&s)", &progressJson);

        // 解析 JSON 并检查是否包含 "progress" 字段
        nlohmann::json progressData = nlohmann::json::parse(progressJson);
        int progress = progressData["progress"].get<int>();

        if (progress != lastProgress)
        {
            // 打印进度条
            const int barWidth = 50; // 进度条宽度
            int pos = barWidth * progress / 100;  // 根据进度计算位置

            std::cout << "[";
            for (int i = 0; i < barWidth; ++i) {
                if (i < pos) {
                    std::cout << "=";  // 已完成的部分
                } else if (i == pos) {
                    std::cout << ">";  // 当前进度的位置
                } else {
                    std::cout << " ";  // 未完成的部分
                }
            }
            std::cout << "] " << progress << " %\r";  // 用 "\r" 覆盖当前行
            std::cout.flush();  // 刷新输出

            // 如果进度为100%，则换行
            if (progress == 100) 
            {
                std::cout << std::endl;
            }
            lastProgress = progress;
        }           
    }
}

bool KMDbusClient::install(const std::string& name, const std::string& branch)
{
    GError* error = nullptr;
    GVariant* result = g_dbus_proxy_call_sync(
        proxy,
        "install",  //方法名
        g_variant_new("(ss)", name.c_str(), branch.c_str()), //参数
        G_DBUS_CALL_FLAGS_NONE,
        -1,
        nullptr,
        &error
    );

    if (!result) 
    {
        KMError(std::string("Failed to call Install method ") + error->message);
        g_error_free(error);
        return false;
    }
    
    gboolean success;
    g_variant_get(result, "(b)", &success);  //获取返回值
    g_variant_unref(result);
    return success;
}

// 运行 DBus 事件循环，确保可以接收信号
void KMDbusClient::run()
{
    loop = g_main_loop_new(nullptr, FALSE);
    running = true;
    g_main_loop_run(loop);
}

//停止事件循环
void  KMDbusClient::stop()
{
    if (loop && running)
    {
        running = false;
        g_main_loop_quit(loop);
    }
}