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

#include <gio/gio.h>
#include <stdlib.h>
#include <string.h>

#include "common/KMLogger.h"
#include "dbus/kmsessioninterface.h"

// D-Bus 名称和路径定义
#define KAIMING_DBUS_SERVICE "org.kylin.kaiming"
#define KAIMING_DBUS_PATH "/org/kylin/kaiming"
#define KAIMING_DBUS_INTERFACE "org.kylin.kaiming.session"

class KMSessionServerAdaptor
{
private:
public:
    KMSessionServerAdaptor(){};
    ~KMSessionServerAdaptor(){};

    static void on_handle_xdg_open(KaimingSession *object,
                                   GDBusMethodInvocation *invocation,
                                   const gchar *arg_name, gpointer user_data)
    {
        g_autofree gchar *local_path = NULL;

        // 检查是否是 file:// 开头的路径
        if (g_str_has_prefix(arg_name, "file://"))
        {
            // 转换 file:// URI 为本地路径
            local_path = g_filename_from_uri(arg_name, NULL, NULL);
            if (local_path == NULL)
            {
                g_dbus_method_invocation_return_dbus_error(
                    invocation, "org.kylin.kaiming.Error.Failed",
                    "Invalid file:// URI.");
                KMError("Invalid file:// URI");
                return;
            }
        }
        else
        {
            // 如果不是 file://，直接使用原路径
            local_path = g_strdup(arg_name);
        }

        // 定义错误变量
        GError *error = NULL;

        // 情况 1：处理网页 URL（http:// 或 https:// 开头）
        if (g_str_has_prefix(local_path, "http://") || g_str_has_prefix(local_path, "https://"))
        {
            g_autofree gchar *command = g_strdup_printf("xdg-open \"%s\"", local_path);
            if (!g_spawn_command_line_async(command, &error))
            {
                gchar *error_message = g_strdup_printf(
                    "Failed to open URL using xdg-open: %s",
                    error->message ? error->message : "Unknown error");
                g_dbus_method_invocation_return_dbus_error(
                    invocation, "org.kylin.kaiming.Error.Failed", error_message);
                KMError(error_message);
                g_free(error_message);
                g_error_free(error);
                return;
            }

            // 成功完成方法调用
            kaiming_session_complete_xdg_open(object, invocation);
            kmlogger.info("Opened URL via xdg-open: %s", local_path);
            return;
        }

        // 情况 2：处理本地路径或文件（检查路径是否存在）
        if (g_file_test(local_path, G_FILE_TEST_EXISTS))
        {
            g_autofree gchar *command = g_strdup_printf("xdg-open \"%s\"", local_path);
            if (!g_spawn_command_line_async(command, &error))
            {
                gchar *error_message = g_strdup_printf(
                    "Failed to open file/path using xdg-open: %s",
                    error->message ? error->message : "Unknown error");
                g_dbus_method_invocation_return_dbus_error(
                    invocation, "org.kylin.kaiming.Error.Failed", error_message);
                KMError(error_message);
                g_free(error_message);
                g_error_free(error);
                return;
            }

            // 成功完成方法调用
            kaiming_session_complete_xdg_open(object, invocation);
            kmlogger.info("Opened file/path via xdg-open: %s", local_path);
            return;
        }

        // 情况 3：路径不存在，返回错误
        g_dbus_method_invocation_return_dbus_error(
            invocation, "org.kylin.kaiming.Error.Failed",
            "Invalid path or file does not exist.");
        KMError("Invalid path or file does not exist");
    }
};

// 当总线获取成功时的回调
static void on_bus_acquired(GDBusConnection *connection, const gchar *name,
                            gpointer user_data)
{
    GError *error = NULL;
    // 获取 KMSessionServerAdaptor 实例
    KMSessionServerAdaptor *handler =
        static_cast<KMSessionServerAdaptor *>(user_data);
    // 创建一个新的 Service 对象  需与xml自动生成的.c中的一致
    KaimingSession *service = kaiming_session_skeleton_new();
    // 将 Service 对象的方法调用与 KMSessionServerAdaptor 的方法连接起来
    // "on_handle_xdg-open"需与xml自动生成的.c中的一致
    g_signal_connect(service, "handle-xdg-open",
                     G_CALLBACK(KMSessionServerAdaptor::on_handle_xdg_open),
                     handler);

    // 将 Service 对象导出到 D-Bus 连接上
    g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(service),
                                     connection, KAIMING_DBUS_PATH, &error);
    if (error)
    {
        KMError("Failed to export xdg-open interface.");
        g_clear_error(&error);
    }
}

int main(int argc, char **argv)
{
    GMainLoop *loop;
    guint owner_id;

    // 创建 KMSessionServerAdaptor 实例
    KMSessionServerAdaptor handler;

    // 将 handler 作为 user_data 传递
    owner_id = g_bus_own_name(G_BUS_TYPE_SESSION, KAIMING_DBUS_SERVICE,
                              G_BUS_NAME_OWNER_FLAGS_NONE, on_bus_acquired, NULL,
                              NULL, &handler, NULL);

    kmlogger.info("test gdbus");

    // 创建主循环
    loop = g_main_loop_new(NULL, FALSE);
    // 进入循环
    g_main_loop_run(loop);

    // 取消 D-Bus 名称的所有权 释放资源
    g_bus_unown_name(owner_id);
    // 释放 GMainLoop 对象
    g_main_loop_unref(loop);

    return 0;
}