#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 <dbus/dbus.h>
// #include <dbus/dbus-glib-lowlevel.h> /* for glib main loop */
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib-lowlevel.h>
void restore(char *path, char *type,char* path_type)
{
    char command[255] = {};
    snprintf(command, sizeof(command), "%s %s %s %s", "/usr/sbin/coredata_restore.sh",type,path_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) {
            printf("Path: %s\n", (char *)xmlNodeGetContent(cur_node));
             if (strstr((char *)xmlNodeGetContent(cur_node),"/etc/")!=NULL){
                printf("Path: %s\n", (char *)xmlNodeGetContent(cur_node));
                 restore((char *)xmlNodeGetContent(cur_node), "etc","install");
            }else{
                printf("Path: %s\n",(char *)xmlNodeGetContent(cur_node));
                 restore((char *)xmlNodeGetContent(cur_node), "var","install");
            }
           
        }
        print_keep_path_elements(cur_node->children);
    }
}

void print_path_elements_restore(xmlNode *node, char *type,char * path_type)
{
    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)
        {
            printf("Path: %s\n", (char *)xmlNodeGetContent(cur_node));
            if (strcmp(path_type, "install") == 0)
            restore((char *)xmlNodeGetContent(cur_node), type, "install");
            else
            restore((char *)xmlNodeGetContent(cur_node), type, "sys");
        }
    }
    print_path_elements_restore(cur_node->children,type,path_type);
}

void read_coredata_xml(){
    xmlDoc *doc = NULL;
    xmlDoc *keep_doc = NULL;
    xmlNode *root_element = NULL;
    xmlNode *keep_root_element = NULL;
    xmlNode *restore_sys = NULL;
    xmlNode *restore_install = NULL;
    xmlNode *install_node = NULL;
    xmlNode *sys_node = NULL;
    LIBXML_TEST_VERSION
    const char *filename = "/etc/ostree/ost-ex.d/ostree_keepdata.xml"; // 替换为你要检查的文件名

    if (access(filename, F_OK) != -1)
    {
        syslog(LOG_INFO, "文件 %s 存在\n", filename);
        keep_doc = xmlReadFile("/etc/ostree/ost-ex.d/ostree_keepdata.xml", NULL, 0);
        if (keep_doc == NULL)
        {
            syslog(LOG_INFO,"Error: restore ostree_keepdata 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("/etc/ostree/ost-ex.d/ostree_coredata.xml", NULL, 0);

    if (doc == NULL)
    {
        printf("Error: could not parse file");
        return 1;
    }
    root_element = xmlDocGetRootElement(doc);
    restore_sys = root_element->children;
    // restore_install = restore_sys->next;
    // sys_node=restore_sys->children;
    // install_node=restore_install->children;

    while (restore_sys != NULL)
    {
        if (strcmp((const char *)restore_sys->name, "restore_sys") == 0)
        {
            for (sys_node = restore_sys->children; sys_node; sys_node = sys_node->next)
            {

                if (sys_node->type == XML_ELEMENT_NODE && strcmp((const char *)sys_node->name, "etc") == 0)
                {
                    print_path_elements_restore(sys_node->children, "etc","restore_sys");
                }
                else if (strcmp((const char *)sys_node->name, "var") == 0)
                {
                    print_path_elements_restore(sys_node->children,"var","restore_sys");
                }
            }
            break;
        }
        restore_sys = restore_sys->next;
    }
    restore_install = restore_sys->next;
    while (restore_install != NULL)
    {
        if (strcmp((const char *)restore_install->name, "restore_install") == 0)
        {
            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_restore(install_node->children, "etc","install");
                }
                else if (strcmp((const char *)install_node->name, "var") == 0)
                {
                    print_path_elements_restore(install_node->children, "var","install");
                }
            }
            break;
        }
        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;
    }

    // 发送消息并获得reply的handle
    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);
        syslog(LOG_INFO,"Method call response returned string \"%s\".\n", value);
       //判断其是否在是什么模式
       if (strcmp (value,"normal")==0){
           //用户模式
            syslog(LOG_INFO,"current mode is normal");
            read_coredata_xml();
           
       }else{
            syslog(LOG_INFO,"current mode is maintainer");
       }
    }
    else
    {
        // 返回类型不正确
        g_error("Error: unexpected return type from method call.");
    }
    dbus_message_unref(msg);
    return;
}
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);
    const char *filename = "/ostree/pkgs/ostree-ovl.conf"; // 替换为你要检查的文件名
    const char *mode_file = "/etc/ostree/ost-ex.d/mode-change"; // 替换为你要检查的文件名
    syslog(LOG_INFO, "--245文件 %s %s存在\n", filename,mode_file);
    if (access(filename, F_OK) != -1 && access(mode_file, F_OK) != -1) {
        syslog(LOG_INFO, "文件 %s 存在\n", filename);

        FILE *file = fopen(filename, "r");
        FILE *mode_fp = fopen(mode_file, "r");
        if (file == NULL || mode_fp == NULL) {
            printf("无法打开文件！");
            exit(1);
        }
        syslog(LOG_INFO,"-----255");
        char line[256];
        char mode_line[256];
        int in_maintenance_mode = 0;

        while (fgets(mode_line, sizeof(mode_line), mode_fp)) {
            syslog(LOG_INFO,"-----mode_line=%s",mode_line);
            if (strncmp(mode_line, "tomaintian", 10) == 0) {
                in_maintenance_mode = 1;
                syslog(LOG_INFO,"-----263");
                break;
            }
        }
        
        if (in_maintenance_mode) {
            while (fgets(line, sizeof(line), file)) {
                syslog(LOG_INFO,"-----line=%s",line);
                if (strncmp(line, "mode=maintian", 13) == 0) {
                    syslog(LOG_INFO,"-----271line=%s",line);
                    read_coredata_xml();
                    break;
                }
            }
        }

        fclose(file);
        fclose(mode_fp);
    } else {
        syslog(LOG_ERR, "文件 %s 或 %s 不存在\n", filename, mode_file);
    }

    return 0;
}
