#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 */
// int dbus_monitor1(void)
// {
   
//     DBusConnection *connection;
//     DBusError error;
//     dbus_error_init(&error);
//     syslog(LOG_ERR,"WD--file=[%s]--fun=[%s]--line=[%d]-Connection Error:[%s]",__FILE__,__FUNCTION__,__LINE__,error.message);
//     // Connect to session bus
//     connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
//     if (dbus_error_is_set(&error))
//     {
//         fprintf(stderr, "Connection Error (%s)\n", error.message);
//         syslog(LOG_ERR,"WD--file=[%s]--fun=[%s]--line=[%d]-Connection Error:[%s]",__FILE__,__FUNCTION__,__LINE__,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'", &error);
//     dbus_connection_flush(connection);

//     if (dbus_error_is_set(&error))
//     {
//         fprintf(stderr, "Error adding D-Bus match rule (%s)\n", error.message);
//         syslog(LOG_ERR,"WD--file=[%s]--fun=[%s]--line=[%d]-Connection Error:[%s]",__FILE__,__FUNCTION__,__LINE__,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", "BootModeChanged"))
//             {
//                 // 读取参数
//                 if (!dbus_message_iter_init(message, &args))
//                     fprintf(stderr, "消息没有参数！\n");
//                 else if (DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type(&args))
//                     fprintf(stderr, "参数格式错误！\n");
//                 else
//                 {
//                     dbus_message_iter_get_basic(&args, &sigvalue);
//                     printf("获取信号的值： %d\n", 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, "------进入运维模式-----");
//                         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;
// }
void copy(char *path, char *type)
{
    char command[255] = {};
    snprintf(command, sizeof(command), "%s %s %s", "/usr/ost-ex.d/copy.sh",type,path);
    if (system(command) == 0)
    {
        syslog(LOG_INFO, "copy success");
    }
}

void print_keep_path_elements(xmlNode *node) {
    xmlNode *cur_node = NULL;
    for (cur_node = node; cur_node; cur_node = cur_node->next) {
        if (cur_node->type == XML_ELEMENT_NODE && strcmp((const char *)cur_node->name, "path") == 0) {
            if (strstr(xmlNodeGetContent(cur_node),"/etc/")!=NULL){
                printf("Path: %s\n", xmlNodeGetContent(cur_node));
                copy(xmlNodeGetContent(cur_node), "etc");
            }else{
                printf("Path: %s\n", xmlNodeGetContent(cur_node));
                copy(xmlNodeGetContent(cur_node), "var");
            }
            
        }
        print_keep_path_elements(cur_node->children);
    }
}
void print_path_elements(xmlNode *node, char *type)
{
    xmlNode *cur_node = NULL;
    for (cur_node = node; cur_node; cur_node = cur_node->next)
    {
        syslog(LOG_ERR, "WD--file=[%s]--fun=[%s]--line=[%d]", __FILE__, __FUNCTION__, __LINE__);
        if (cur_node->type == XML_ELEMENT_NODE && strcmp((const char *)cur_node->name, "path") == 0)
        {
            syslog(LOG_ERR,"Path: %s\n", xmlNodeGetContent(cur_node));
            copy(xmlNodeGetContent(cur_node), type);
            syslog(LOG_ERR, "WD--file=[%s]--fun=[%s]--line=[%d]", __FILE__, __FUNCTION__, __LINE__);
        }
        print_path_elements(cur_node->children, type);
    }
}
// void print_origin_path_elements(xmlNode *keep_node, xmlNode *node, char *type)
// {
//     xmlNode *cur_node = NULL;
//     xmlNode *cur_orig_node = NULL;
//     for (cur_orig_node = node; cur_orig_node; cur_orig_node = cur_orig_node->next)
//     {
//         if (cur_orig_node->type == XML_ELEMENT_NODE && strcmp((const char *)cur_orig_node->name, "path") == 0)
//         {
//             syslog(LOG_INFO,"Path: %s\n", xmlNodeGetContent(cur_orig_node));
//             for (cur_node = keep_node; cur_node; cur_node = cur_node->next)
//             {
//                 if (cur_node->type == XML_ELEMENT_NODE && strcmp((const char *)cur_node->name, "path") == 0)
//                 {
//                     syslog(LOG_INFO,"keep path: %s\n", xmlNodeGetContent(cur_node));
//                     if (stcmp(xmlNodeGetContent(cur_node),xmlNodeGetContent(cur_orig_node))！=0)
//                     {
//                         copy(xmlNodeGetContent(cur_orig_node), type);
//                     }
                    
//                 }
//             }
//         }
//         print_origin_path_elements(cur_orig_node->children, type);
//     }
// }
void read_copy_xml(){
    xmlDoc *doc = NULL;
    xmlDoc *keep_doc = NULL;
    xmlNode *root_element = NULL;
    xmlNode *keep_root_element = NULL;
    xmlNode *restore_install = NULL;
    xmlNode *install_node=NULL;

    LIBXML_TEST_VERSION
    const char *filename = "/usr/ost-ex.d/ostree_keep.xml"; // 替换为你要检查的文件名

    if (access(filename, F_OK) != -1)
    {
        syslog(LOG_INFO, "文件 %s 存在\n", filename);
        keep_doc = xmlReadFile("/usr/ost-ex.d/ostree_keep.xml", NULL, 0);
        if (keep_doc == NULL)
        {
            syslog(LOG_ERR,"Error: could not parse file");
        }else{
            keep_root_element =xmlDocGetRootElement(keep_doc);
            if (keep_root_element != NULL)
            {
                print_keep_path_elements(keep_root_element);
            }
        }
    }
    else
    {
        syslog(LOG_INFO, "文件 %s 不存在\n", filename);
    }
    doc = xmlReadFile("/usr/ost-ex.d/restore.xml", NULL, 0);

    if (doc == NULL)
    {
       syslog(LOG_ERR, "WD--file=[%s]--fun=[%s]--line=[%d] Error: could not parse file", __FILE__, __FUNCTION__, __LINE__);
        return 1;
    }
    root_element = xmlDocGetRootElement(doc);
    restore_install = root_element->children;
    
    syslog(LOG_ERR, "WD--file=[%s]--fun=[%s]--line=[%d]", __FILE__, __FUNCTION__, __LINE__);
    while (restore_install != NULL)
    {
        if (strcmp((const char *)restore_install->name, "restore_install") == 0)
        {
            syslog(LOG_ERR, "WD--file=[%s]--fun=[%s]--line=[%d] (const char *)restore_install->name=%s", __FILE__, __FUNCTION__, __LINE__, (const char *)restore_install->name);
            for (install_node = restore_install->children; install_node; install_node = install_node->next)
            {
                if (install_node->type == XML_ELEMENT_NODE && strcmp((const char *)install_node->name, "etc") == 0)
                {
                    print_path_elements(install_node->children, "etc");
                }else if (strcmp((const char *)install_node->name, "var") == 0)
                {
                    print_path_elements(install_node->children, "var");
                }
            }

            break;
        }
        syslog(LOG_ERR, "WD--file=[%s]--fun=[%s]--line=[%d]", __FILE__, __FUNCTION__, __LINE__);
        restore_install = restore_install->next;
    }

    xmlFreeDoc(doc);
    xmlFreeDoc(keep_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",           // target for the method call
                                        "/com/kylin/MaintainMode/Object",   // object to call on
                                        "com.kylin.MaintainMode.interface", // interface to call on
                                        "GetBootMode");                     // 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);
       //判断其是否在是什么模式
       if (strcmp (value,"normal")==0){
           //用户模式
            FILE *file = fopen("/etc/ostree/ostree_mode", "w");
            if (file == NULL)
            {
                printf("无法打开文件！");
                exit(1);
            }
            fprintf(file, "mode=normal");
            fclose(file);
            read_copy_xml();
           
       }else{
           FILE *file = fopen("/etc/ostree/ostree_mode", "w");
            if (file == NULL)
            {
                printf("无法打开文件！");
                exit(1);
            }
            fprintf(file, "mode=maintainer");
            fclose(file);
       }
    }
    else
    {
        // 返回类型不正确
        g_error("Error: unexpected return type from method call.");
    }
    dbus_message_unref(msg);
    return;
}
pthread_t boot_tid;
int main(int argc, char **argv) {
    //获取模式
    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);
    

    return 0;
}