/* Copyright (c) KylinSoft  Co., Ltd. [2023].All rights reserved.
    [ostree-maintain-daemon] licensed under the [Your LICENSE].
    Author: [ZhangTingting]
    Create: [2024]
*/

#include "mm-manager.h"
#include "mm-public.h"
#include <string.h>

/***************************************进入维护模式*********************************************************/

/*进入维护模式*/
gboolean mm_enter_maintain_mode()
{
    gboolean ret;
    gchar *boot_mode;

    // boot_mode = mm_get_config_value (MM_CONFIG_FILE_PATH, BOOT_SECTION, BOOT_MODE);//判断当前模式
    boot_mode = mm_get_config_value(MM_CONFIG_FILE_PATH, BOOT_SECTION, BOOT_NEXT_MODE); // 判断下次要进入的模式，如果已经设置为维护模式，无需重复设置
    if (strcmp(boot_mode, "maintain") == 0) {
        mm_emit_mode_changed_signal(MM_MODE_STATUS);
        g_info("mm: Next time  will in maintenance mode, cannot enter again.");
        return FALSE;
    }

    ret = mm_set_config_value(MM_CONFIG_FILE_PATH, BOOT_SECTION, BOOT_NEXT_MODE, BOOT_MODE_MAINTAIN); // 设置下次启动的模式
    if (!ret) {
        mm_emit_mode_changed_signal(ENTER_MM_MODE_FAILED);
        g_warning("mm: enter maintain mode config failed.");
        return FALSE;
    }

    // //锁文件
    // ret = lock_file_acquire(LOCK_FILE_PATH);
    // if (!ret)
    // {
    //     mm_emit_mode_changed_signal (ENTER_MM_MODE_FAILED);
    //     g_info("mm: enter maintain mode lock file failed.");
    //     return FALSE;
    // }

    // 通知
    mm_emit_mode_changed_signal(ENTER_MM_MODE_SUCCESS);
    mm_shutdown_action = FALSE;
    g_info("mm: enter maintain mode success.");

    // 记录进入mm的时间
    /*GDateTime *date_time = g_date_time_new_now_local();
    gchar *date_time_str = g_date_time_format (date_time, "%Y-%m-%dT%H:%M:%SZ");
    ret = mm_set_config_value (MM_CONFIG_FILE_PATH, TIME_SECTION, TIME_START,date_time_str);*/

    return TRUE;
}

/*******************************************退出维护模式***********************************************************/
/*
// 获取维护模式期间安装包列表
static void mm_get_pkgs_name_period()
{
    return; // 暂时
}

// 获取单个安装包数据
static void mm_get_pkg_data()
{
    // 暂时
}
*/

gboolean mm_delete_tmp_layer_data()
{
    gchar copy_command[2048];
    gchar *ovl_etc_tmp_upper;
    gchar *ovl_usr_tmp_upper;
    gchar *ovl_var_tmp_upper;

    // 获取ovl目录路径
    gchar *ovl_dir_path_tmp = mm_get_ovl_dir_path();
    if (ovl_dir_path_tmp == NULL) {
        g_warning("mm: get ovl dir path failed.");
        return FALSE;
    }
    g_info("mm: Successfully obtained the ovl dir path.");
    gchar *ovl_dir_path = g_strstrip(ovl_dir_path_tmp);
    gint16 ret;
    g_info("mm: Beginning deletion of etc pkgs data...");
    ovl_etc_tmp_upper = g_strconcat(ovl_dir_path, ETC_LAYER_TMP_UPPER, "*", NULL);
    snprintf(copy_command, sizeof(copy_command), "rm -rf %s ", ovl_etc_tmp_upper);
    ret = system(copy_command);

    if (ret == -1) {
        g_info("mm: delete etc pkgs data failed.");
        // 发通知
        // 清除ovl tmp层数据
        // 设置启动模式 normal
        // 发通知
        mm_emit_mode_changed_signal(ENTER_NORMAL_MODE_FAILED);
        g_info("mm: Send a failure notification signal.");
        // 清除ovl tmp层数据
        mm_delete_tmp_layer_data();
        g_info("mm: Clear ovl tmp layer data.");
        // 设置为标准模式 normal
        // gboolean ret;
        // ret = mm_set_config_value (MM_CONFIG_FILE_PATH, BOOT_SECTION, BOOT_MODE,BOOT_MODE_NORMAL);
        // if(!ret)
        // {
        //     g_info("mm: Failed to set to normal mode.");
        //     return FALSE;
        // }
        // g_info("mm: Successfully set to normal mode.");
        // lock_file_release(LOCK_FILE_PATH);

        return FALSE;
    }

    ovl_usr_tmp_upper = g_strconcat(ovl_dir_path, USR_LAYER_TMP_UPPER, "*", NULL);
    snprintf(copy_command, sizeof(copy_command), "rm -rf %s ", ovl_usr_tmp_upper);
    ret = system(copy_command);
    g_info("mm: Beginning deletion of usr pkgs data...");
    if (ret == -1) {
        g_info("mm: delete usr pkgs data failed.");
        // 发通知
        // 清除ovl tmp层数据
        // 设置启动模式 normal
        // 发通知
        mm_emit_mode_changed_signal(ENTER_NORMAL_MODE_FAILED);
        g_info("mm: Send a failure notification signal.");
        // 清除ovl tmp层数据
        mm_delete_tmp_layer_data();
        g_info("mm: Clear ovl tmp layer data.");
        // 设置为标准模式 normal
        // gboolean ret;

        // ret = mm_set_config_value (MM_CONFIG_FILE_PATH, BOOT_SECTION, BOOT_MODE,BOOT_MODE_NORMAL);
        // if(!ret)
        // {
        //     g_info("mm: Failed to set to normal mode.");
        //     return FALSE;
        // }
        // g_info("mm: Successfully set to normal mode.");
        // lock_file_release(LOCK_FILE_PATH);

        return FALSE;
    }

    ovl_var_tmp_upper = g_strconcat(ovl_dir_path, VAR_LAYER_TMP_UPPER, "*", NULL);
    snprintf(copy_command, sizeof(copy_command), "rm -rf %s ", ovl_var_tmp_upper);
    ret = system(copy_command);
    g_info("mm: Beginning deletion of var pkgs data...");
    if (ret == -1) {
        g_info("mm: delete var pkgs data failed.");
        // 发通知
        // 清除ovl tmp层数据
        // 设置启动模式 normal
        // 发通知
        mm_emit_mode_changed_signal(ENTER_NORMAL_MODE_FAILED);
        g_info("mm: Send a failure notification signal.");
        // 清除ovl tmp层数据
        mm_delete_tmp_layer_data();
        g_info("mm: Clear ovl tmp layer data.");
        // 设置为标准模式 normal
        // gboolean ret;
        // ret = mm_set_config_value (MM_CONFIG_FILE_PATH, BOOT_SECTION, BOOT_MODE,BOOT_MODE_NORMAL);
        // if(!ret)
        // {
        //     g_info("mm: Failed to set to normal mode.");
        //     return FALSE;
        // }
        // g_info("mm: Successfully set to normal mode.");
        // lock_file_release(LOCK_FILE_PATH);

        return FALSE;
    }

    return TRUE;
}

// 解决数据迁移过程中的目录冲突，dir为待解决冲突的目录（etc、var等）
static gboolean mm_fix_conflicts(char *dir)
{
    // 获取ovl目录路径
    gchar *ovl_dir_path_tmp = mm_get_ovl_dir_path();
    if (ovl_dir_path_tmp == NULL) {
        g_warning("mm: get ovl dir path failed.");
        return FALSE;
    }
    // g_info("mm: Successfully obtained the ovl dir path.");
    gchar *ovl_dir_path = g_strstrip(ovl_dir_path_tmp);
    gint16 ret;
    // 增加tmpupper与upper文件冲突检测与处理
    gchar fix_etc_conflict_cmd[1024];
    gchar fix_var_conflict_cmd[1024];
    snprintf(fix_etc_conflict_cmd, sizeof(fix_etc_conflict_cmd), "bash /usr/bin/fix-conflicts.sh %s %s", ovl_dir_path, dir);
    ret = system(fix_etc_conflict_cmd);
    // g_info ("mm: Detection and Handling of Conflicts Between tmpupper and upper Files...");
    if (ret == -1)
        return FALSE;

    return TRUE;
}

// 移动安装包数据到指定目录
gboolean mm_move_pkgs_data_to_layer()
{
    gchar copy_command[1024];

    gchar *ovl_etc_tmp_upper;
    gchar *ovl_etc_upper;

    gchar *ovl_usr_tmp_upper;
    gchar *ovl_usr_upper;

    gchar *ovl_var_tmp_upper;
    // gchar *ovl_var_lower;
    gchar *ovl_var_upper;

    // 获取ovl目录路径
    gchar *ovl_dir_path_tmp = mm_get_ovl_dir_path();
    if (ovl_dir_path_tmp == NULL) {
        g_warning("mm: get ovl dir path failed.");
        return FALSE;
    }
    g_info("mm: Successfully obtained the ovl dir path.");

    gchar *ovl_dir_path = g_strstrip(ovl_dir_path_tmp);
    gint16 ret;

    g_info("mm: The etc installation package data will soon be moved to the specified directory...");
    ovl_etc_tmp_upper = g_strconcat(ovl_dir_path, ETC_LAYER_TMP_UPPER, NULL);
    ovl_etc_upper = g_strconcat(ovl_dir_path, ETC_LAYER_UPPER, NULL);

    ovl_usr_tmp_upper = g_strconcat(ovl_dir_path, USR_LAYER_TMP_UPPER, NULL);
    ovl_usr_upper = g_strconcat(ovl_dir_path, USR_LAYER_UPPER, NULL);

    ovl_var_tmp_upper = g_strconcat(ovl_dir_path, VAR_LAYER_TMP_UPPER, NULL);
    ovl_var_upper = g_strconcat(ovl_dir_path, VAR_LAYER_UPPER, NULL);

    // 增加冲突目录处理逻辑
    if (!mm_fix_conflicts("etc")) {
        g_info("mm: Failed to fix directory conflicts between [tmpupper] and [upper].");
        // 发通知
        mm_emit_mode_changed_signal(ENTER_NORMAL_MODE_FAILED);
        return FALSE;
    }

    char *etc_space_size = print_human_readable_size(etc_size);
    printf("Retaining etc data, with a data volume of approximately:%s (%ld)\n", etc_space_size, etc_size);
    g_info("Retaining etc data, with a data volume of approximately:%s (%ld)", etc_space_size, etc_size);
    free(etc_space_size);

    snprintf(copy_command, sizeof(copy_command), "rsync -aAXc  --inplace --force -H  --numeric-ids --ignore-times --atimes --links --log-file=/var/log/ostree.log --log-file-format=\"ostree-maintain: %%o %%f \"  %s %s  ", ovl_etc_tmp_upper, ovl_etc_upper);
    ret = system(copy_command);
    if (ret == -1) {
        g_info("mm: mv etc pkgs data failed.");
        // 发通知
        mm_emit_mode_changed_signal(ENTER_NORMAL_MODE_FAILED);
        g_info("mm: Send a failure notification signal.");
        // 清除ovl tmp层数据
        mm_delete_tmp_layer_data();
        g_info("mm: Clear ovl tmp layer data.");
        // 设置为标准模式 normal
        // gboolean ret;
        // ret = mm_set_config_value (MM_CONFIG_FILE_PATH, BOOT_SECTION, BOOT_MODE,BOOT_MODE_NORMAL);
        // if(!ret)
        // {
        //     g_info("mm: Failed to set to normal mode.");
        //     return FALSE;
        // }
        // g_info("mm: Succeed to set to normal mode.");
        // lock_file_release(LOCK_FILE_PATH);
        return FALSE;
    }

    char *usr_space_size = print_human_readable_size(usr_size);
    printf("Retaining usr data, with a data volume of approximately:%s (%ld)\n", usr_space_size, usr_size);
    g_info("Retaining usr data, with a data volume of approximately:%s (%ld)", usr_space_size, usr_size);
    free(usr_space_size);
    snprintf(copy_command, sizeof(copy_command), "rsync -aAXc  --inplace --force -H  --numeric-ids --ignore-times --atimes --links --log-file=/var/log/ostree.log --log-file-format=\"ostree-maintain: %%o %%f \"  %s %s  ", ovl_usr_tmp_upper, ovl_usr_upper);
    ret = system(copy_command);
    if (ret == -1) {
        g_info("mm: mv etc pkgs data failed.");
        // 发通知
        mm_emit_mode_changed_signal(ENTER_NORMAL_MODE_FAILED);
        g_info("mm: Send a failure notification signal.");
        // 清除ovl tmp层数据
        mm_delete_tmp_layer_data();
        g_info("mm: Clear ovl tmp layer data.");
        // 设置为标准模式 normal

        // gboolean ret;
        // ret = mm_set_config_value (MM_CONFIG_FILE_PATH, BOOT_SECTION, BOOT_MODE,BOOT_MODE_NORMAL);
        // if(!ret)
        // {
        //     g_info("mm: Failed to set to normal mode.");
        //     return FALSE;
        // }
        // lock_file_release(LOCK_FILE_PATH);
        return FALSE;
    }

    char *var_space_size = print_human_readable_size(var_size);
    printf("Retaining var data, with a data volume of approximately:%s (%ld)\n", var_space_size, var_size);
    g_info("Retaining var data, with a data volume of approximately:%s (%ld)", var_space_size, var_size);
    free(var_space_size);
    snprintf(copy_command, sizeof(copy_command), "rsync -aAXc  --inplace --force -H  --numeric-ids --ignore-times --atimes --links --log-file=/var/log/ostree.log --log-file-format=\"ostree-maintain: %%o %%f \"  %s %s  ", ovl_var_tmp_upper, ovl_var_upper);
    ret = system(copy_command);
    if (ret == -1) {
        g_info("mm: mv etc pkgs data failed.");
        // 发通知
        mm_emit_mode_changed_signal(ENTER_NORMAL_MODE_FAILED);
        g_info("mm: Send a failure notification signal.");
        // 清除ovl tmp层数据
        mm_delete_tmp_layer_data();
        g_info("mm: Clear ovl tmp layer data.");
        // 设置为标准模式 normal

        // gboolean ret;
        // ret = mm_set_config_value (MM_CONFIG_FILE_PATH, BOOT_SECTION, BOOT_MODE,BOOT_MODE_NORMAL);
        // if(!ret)
        // {
        //     g_info("mm: Failed to set to normal mode.");
        //     return FALSE;
        // }
        // lock_file_release(LOCK_FILE_PATH);

        return FALSE;
    }

    // single handle copy status file to var upper
    // g_info("mm: single handle copy status file to var upper...");
    // ovl_var_tmp_upper = g_strconcat(ovl_dir_path, VAR_LAYER_TMP_UPPER, "dpkg/status", NULL);
    // ovl_var_upper = g_strconcat(ovl_dir_path, VAR_LAYER_UPPER, "dpkg/", NULL);
    // snprintf(copy_command, sizeof(copy_command), "rsync -aAXc  --inplace --force -H  --numeric-ids --ignore-times --atimes --links --log-file=/var/log/ostree.log --log-file-format=\"ostree-maintain: %%o %%f \"  %s %s  ", ovl_var_tmp_upper, ovl_var_upper);
    // ret = system(copy_command);
    // if (ret == -1) {
    //     g_info("mm: mv dpkg file data failed.");
    //     // 发通知
    //     mm_emit_mode_changed_signal(ENTER_NORMAL_MODE_FAILED);
    //     g_info("mm: Send a failure notification signal.");
    //     // 清除ovl tmp层数据
    //     mm_delete_tmp_layer_data();
    //     g_info("mm: Clear ovl tmp layer data.");
    //     // 设置为标准模式 normal
    //     // gboolean ret;
    //     // ret = mm_set_config_value (MM_CONFIG_FILE_PATH, BOOT_SECTION, BOOT_MODE,BOOT_MODE_NORMAL);
    //     // if(!ret)
    //     // {
    //     //     g_info("mm: Failed to set to normal mode.");
    //     //     return FALSE;
    //     // }
    //     // lock_file_release(LOCK_FILE_PATH);

    //     return FALSE;
    // }

    return TRUE;
}

// 判断临时维护层 是否与etc upper层数据文件，删除
static void mm_delete_confilct_data()
{
}
// 删除临时维护层数据

// 判断安装包数据是否已在数据修改层，如果在指定层则在拷贝后删除

/*退出维护模式*/
gboolean mm_exit_maintain_mode(char *SaveDataMode)
{
    gboolean ret;
    gboolean match_result = FALSE;
    gchar *boot_mode;
    boot_mode = mm_get_config_value(MM_CONFIG_FILE_PATH, BOOT_SECTION, BOOT_MODE);
    if (strcmp(boot_mode, "normal") == 0) {
        g_info("mm: Already in user mode, cannot exit again.");
        mm_emit_mode_changed_signal(NM_MODE_STATUS);
        mm_set_config_value(MM_CONFIG_FILE_PATH, BOOT_SECTION, BOOT_NEXT_MODE, BOOT_MODE_NORMAL);
        return FALSE;
    }

    g_info("exit mm: Starting to exit maintenance mode...\n");
    // 维护保留数据：none 不保留；all保留全部；part保留部分(暂无)
    g_info("exit mm: data savemode =%s\n", SaveDataMode);
    if (strcmp(SaveDataMode, SAVE_DATA_MODE_NONE) == 0) {
        match_result = TRUE;
        g_info("exit mm: Save data NONE.");
    } else if (strcmp(SaveDataMode, SAVE_DATA_MODE_ALL) == 0) {
        ret = mm_move_pkgs_data_to_layer();
        if (!ret) {
            g_info("exit mm: move layer data failed.");
            return FALSE;
        } else {
            g_info("exit mm: Save data ALL.");
        }
        match_result = TRUE;
        mm_shutdown_sync = TRUE;
    } else if (strcmp(SaveDataMode, SAVE_DATA_MODE_PART) == 0) { // 用户选择部分保存安装包数据 （暂时）
        g_info("exit mm: Save data parts .");
        match_result = TRUE;
    }

    if (!match_result) {
        g_warning("exit mm: please check parameter.");
        return FALSE;
    }

    /*设置启动模式配置文件*/
    g_print("exit mm: set normal mode ostree-ovl.conf file.\n");
    ret = mm_set_config_value(MM_CONFIG_FILE_PATH, BOOT_SECTION, BOOT_NEXT_MODE, BOOT_MODE_NORMAL);
    if (!ret) {
        // 桌面通知，进入维护模式失败
        mm_emit_mode_changed_signal(ENTER_NORMAL_MODE_FAILED);
        g_warning("exit mm: set normal mode failed.");
        return FALSE;
    }
    g_info("exit mm: set normal mode successfully.");
    // 通知用户退出维护模式
    g_print("exit mm: send notification exit mm success.\n");

    if (strcmp(SaveDataMode, SAVE_DATA_MODE_ALL) == 0) {
        mm_emit_mode_changed_signal(ENTER_NORMAL_MODE_SUCCESS_SAVE);
    } else {
        mm_emit_mode_changed_signal(ENTER_NORMAL_MODE_SUCCESS_CLEAR);
    }

    mm_shutdown_action = TRUE; // 关机前执行动作
    g_info("exit mm: exit mm over.\n");
    return TRUE;
}

/***************************获取当前维护状态********************************/
gchar *mm_get_boot_mode()
{
    gchar *boot_mode;
    boot_mode = mm_get_config_value(MM_CONFIG_FILE_PATH, BOOT_SECTION, BOOT_MODE);
    if (boot_mode == NULL) {
        g_info("mm_get_boot_mode: The current operation and maintenance status failed to be obtained.");
        return NULL;
    }
    g_info("mm: The current system status: %s\n", boot_mode);
    // g_info("mm_get_boot_mode: The current operation and maintenance status succeed to be obtained.");
    return boot_mode;
}
