#include <syslog.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <systemd/sd-bus.h>
#include <unistd.h>
#include <fcntl.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib-lowlevel.h> /* for glib main loop */
void add_element(xmlNode *node, const char *name, const char *content) {
    xmlNode *new_node = xmlNewTextChild(node, NULL, BAD_CAST name, BAD_CAST content);
    if (new_node == NULL) {
        printf("Failed to add element %s with content %s", name, content);
    }
}

void delete_element(xmlNode *node, const char *name) {
    xmlNode *cur_node = NULL;
    for (cur_node = node; cur_node; cur_node = cur_node->next) {
        if (cur_node->type == XML_ELEMENT_NODE && strcmp((char *)cur_node->name, name) == 0) {
            xmlUnlinkNode(cur_node);
            xmlFreeNode(cur_node);
            break;
        }
    }
}

void update_element(xmlNode *root, const char *name, const char *new_content) {
    xmlNode *cur_node = NULL;
    for (cur_node = root->children; cur_node; cur_node = cur_node->next) {
        if (cur_node->type == XML_ELEMENT_NODE && strcmp((char *)cur_node->name, name) == 0) {
            xmlNodeSetContent(cur_node, BAD_CAST new_content);
            break;
        }
    }
}
bool search_element(xmlNode *root, const char *name) {
    xmlNode *cur_node = NULL;
    for (cur_node = root->children; cur_node; cur_node = cur_node->next) {
        if (cur_node->type == XML_ELEMENT_NODE && strcmp((char *)cur_node->name, name) == 0) {
            syslog(LOG_INFO,"Element %s found with content: %s", name, (char *)xmlNodeGetContent(cur_node));
            return true;
        }
    }
}
int update_xml(char*path) {
    char * filename="/usr/ost-ex.d/ostree_keep.xml";
    xmlDoc *doc = NULL;
    xmlNode *root_element = NULL;
    xmlNode *restore_sys_etc = NULL;
    xmlNode *restore_install_etc = NULL;
    xmlNode *restore_sys_var = NULL;
    xmlNode *restore_install_var = NULL;
    LIBXML_TEST_VERSION
    if (access(filename, F_OK) != -1)
    {
        syslog(LOG_INFO, "文件 %s 存在\n", filename);
        doc = xmlReadFile(filename, NULL, 0);

        if (doc == NULL)
        {
            // printf("Error: could not parse file %s", argv[1]);
            return 1;
        }
        root_element = xmlDocGetRootElement(doc);
    }
    else
    {

        // 创建一个新的XML文档
        doc = xmlNewDoc(BAD_CAST "1.0");
        root_element = xmlNewNode(NULL, BAD_CAST "root");
        xmlDocSetRootElement(doc, root_element);
    }

    // xmlDoc *doc = NULL;
    // xmlNode *root_element = NULL;

    
    // restore_sys_etc = root_element->children;
    // restore_install_etc = restore_sys_etc->next;
    // restore_sys_var = restore_install_etc->next;
    // restore_install_var = restore_sys_var->next;
    char str[] = "/etc/locale.conf;/var/lib/lightdm";
    //strcpy(str, path);
    char *token;
    char delim[] = ";";
    char *saveptr;

    // 使用strtok_r函数分割字符串
    // token = strtok_r(str, delim, &saveptr);
    token = strtok(str, delim);

    while (token != NULL)
    {
        syslog(LOG_INFO,"处理路径： %s", token);
        // 在这里添加对路径的处理代码
        if (!search_element(root_element,token)){
            add_element("path",token);
        }
        // 获取下一个子串
        // token = strtok_r(NULL, delim, &saveptr);
        token = strtok(NULL, delim);
    }

        // 添加元素
    // add_element(root_element, "element1", "content1");
    // add_element(root_element, "element2", "content2");

    // // 删除元素
    // delete_element(root_element, "element1");

    // // 更新元素内容
    // update_element(root_element, "element2", "updated_content2");
    // 保存XML文档到文件
   // xmlSaveFormatFileEnc("output.xml", doc, "UTF-8", 1);
     xmlSaveFormatFileEnc(filename, doc, "UTF-8", 1);
    // 释放内存
    xmlFreeDoc(doc);
    xmlCleanupParser();

    return 0;
}
void send_a_method_call(DBusConnection *connection, char *param)
{
    DBusError err;
    DBusMessage *msg;
    DBusMessageIter arg;
    DBusPendingCall *pending;
    const char *value;
    dbus_error_init(&err);

    // 针对目的地地址，请参考图，创建一个method call消息。 Constructs a new message to invoke a method on a remote object.
    msg = dbus_message_new_method_call("com.kylin.MaintainMode.interface",           // target for the method call
                                        "/com/kylin/MaintainMode/Object",   // object to call on
                                        "com.kylin.MaintainMode.interface", // interface to call on
                                        "GetFile");                     // method name
    if (msg == NULL)
    {
        g_printerr("Message NULL");
        return;
    }
    syslog(LOG_ERR, "WD--file=[%s]--fun=[%s]--line=[%d]", __FILE__, __FUNCTION__, __LINE__);
    //为消息添加参数。Append arguments
    dbus_message_iter_init_append(msg, &arg);
    if (!dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING, &param))
    {
        g_printerr("Out of Memory!");
        exit(1);
    }

    // 发送消息并获得reply的handle 。Queues a message to send, as with dbus_connection_send() , but also returns a DBusPendingCall used to receive a reply to the message.
    if (!dbus_connection_send_with_reply(connection, msg, &pending, -1))
    {
        g_printerr("Out of Memory!");
        exit(1);
    }

    if (pending == NULL)
    {
        g_printerr("Pending Call NULL: connection is disconnected ");
        dbus_message_unref(msg);
        return;
    }

    dbus_connection_flush(connection);
    dbus_message_unref(msg);

    // waiting a reply，在发送的时候，已经获取了method reply的handle，类型为DBusPendingCall。
    //  block until we recieve a reply， Block until the pending call is completed.
    dbus_pending_call_block(pending);
    // get the reply message，Gets the reply, or returns NULL if none has been received yet.
    msg = dbus_pending_call_steal_reply(pending);
    if (msg == NULL)
    {
        fprintf(stderr, "Reply Null/n");
        exit(1);
    }
    // free the pending message handle
    dbus_pending_call_unref(pending);
    // read the parameters
    if (!dbus_message_iter_init(msg, &arg))
        fprintf(stderr, "Message has no arguments!/n");
    
    if (dbus_message_iter_get_arg_type(&arg) == DBUS_TYPE_STRING)
    {
        
        dbus_message_iter_get_basic(&arg, &value);
        printf("Method call response returned string \"%s\".\n", value);
       //获取文件在哪里并更新到配置文件中ostree_keep
        update_xml(value);
    }
    else
    {
        // 返回类型不正确
        g_error("Error: unexpected return type from method call.");
    }
    dbus_message_unref(msg);
    return;
}
int dbus_monitor(void)
{
   
    DBusConnection *connection;
    DBusError error;
    dbus_error_init(&error);
    // Connect to session bus
    connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
    if (dbus_error_is_set(&error))
    {
        syslog(LOG_ERR, "Connection Error (%s)\n", error.message);
        dbus_error_free(&error);
        return 1;
    }

    // Add a rule for incoming signals
    dbus_bus_add_match(connection, "type='signal',interface='com.kylin.MaintainMode.interface'", &error);
    dbus_connection_flush(connection);

    if (dbus_error_is_set(&error))
    {
        syslog(LOG_ERR,"Error adding D-Bus match rule (%s)\n", error.message);
        dbus_error_free(&error);
        return 1;
    }

    // Main event loop
    while (1)
    {
        DBusMessage *message;
        DBusMessageIter args;
        guint16 sigvalue;
        DBusDispatchStatus status = dbus_connection_read_write(connection, 1000); // 设置阻塞时间
        // Blocking call to receive a message
        message = dbus_connection_pop_message(connection);
        if (message != NULL)
        {
            if (dbus_message_is_signal(message, "com.kylin.MaintainMode.interface", "BootModeChanged"))
            {
                // 读取参数
                if (!dbus_message_iter_init(message, &args))
                   syslog(LOG_ERR, "消息没有参数!");
                else if (DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type(&args))
                     syslog(LOG_ERR, "参数格式错误！");
                else
                {
                    dbus_message_iter_get_basic(&args, &sigvalue);
                    syslog(LOG_ERR, "WD--file=[%s]--fun=[%s]--line=[%d]-获取信号的值:[%d]", __FILE__, __FUNCTION__, __LINE__, sigvalue);
                     char command[255] = {};
                    if (sigvalue == 1) // 是进入运维模式
                    {
                        //获取到信号，do what you do.....
                        syslog(LOG_INFO, "------进入运维模式-----");
                        snprintf(command, sizeof(command), "%s %s", "/usr/ost-ex.d/boot_handle.sh","in");
                        if (system(command) == 0)
                        {
                            syslog(LOG_INFO, "copy success");
                        }
                        syslog(LOG_INFO, "------进入运维模式boot备份end-----");
                    }else if(sigvalue == 3){
                        syslog(LOG_INFO, "------退出且保留运维模式-----");
                        //新增配置文件，保留下的数据，在ostree_restore 存在ostree_keep的配置文件中
                        // DBusConnection *connection;
                        // DBusError error;
                        // dbus_error_init(&error);
                        // // Connect to session bus
                        // connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
                        // if (dbus_error_is_set(&error))
                        // {
                        //     syslog(LOG_ERR, "Connection Error (%s)\n", error.message);
                        //     dbus_error_free(&error);
                        //     return 1;
                        // }
                        // send_a_method_call(connection, NULL);
                    }else if(sigvalue==5){
                         syslog(LOG_INFO, "------退出且不保留运维模式-----");
                        snprintf(command, sizeof(command), "%s %s", "/usr/ost-ex.d/boot_handle.sh","out");
                        if (system(command) == 0)
                        {
                            syslog(LOG_INFO, "copy success");
                        }
                        syslog(LOG_INFO, "------进入运维模式boot备份end-----");

                    }
                }
            }
            // Free the received message
            dbus_message_unref(message);
        }
    }
    // Close the connection
    dbus_connection_unref(connection);
    return 0;
}
int main(int argc, char **argv) {
    dbus_monitor();
}