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

#ifndef _KMHOSTAPPDEPLOY_H
#define _KMHOSTAPPDEPLOY_H

#include <filesystem>
#include <iostream>
#include <set>
#include <sstream>
#include <fstream>
#include <stdexcept>
#include <memory>
#include <vector>

#include "common/KMCommonTypePrivate.h"
#include "common/KMInfoJson.h"

namespace fs = std::filesystem;

class KMPackageManager;

class KMHostAppDeploy
{
public:
    explicit KMHostAppDeploy(const std::string &infoPath);
    virtual ~KMHostAppDeploy();

    friend class KMPackageManager;

public:
    /**
     * @brief 加载 info.json 以确定是否是 HostApp
     */
    bool loadHostAppInfo();

    /**
     * @brief 设置版本路径,refID
     */
    void setHostAppConfig(const fs::path &versionPath, const std::string &refID);

    /**
     * @brief 遍历解压目录，收集同步文件
     */
    void collectSynchronizedFiles();

    /**
     * @brief: 获取同步文件列表
     * @return 返回同步文件列表
     */
    std::set<std::string> getSynchronizedFiles();

    /**
     * @brief 检查文件是否已经存在，避免覆盖
     */
    bool checkFileConflicts();

    /**
     * @brief 执行 rsync 同步文件
     */
    void synchronizeFiles(bool append);

    /**
     * @brief 卸载方法
     */
    void uninstall(TaskType type = TaskType::TASK_TYPE_UNINSTALL);

    /**
     * @brief 处理记录的desktop文件，供KMPackageManager调用
     * @param packageManager KMPackageManager实例的引用
     */
    void processRecordedDesktopFiles(KMPackageManager &packageManager);

private:
    /**
     * @brief 写入已同步文件列表
     */
    void writeSynchronizedFileList(bool append);

    /**
     * @brief 读取已安装文件列表
     */
    std::set<std::string> readSynchronizedFileList(const fs::path &listPath);

    /**
     * @brief: 跳过特定文件
     * @param {string} &file 待检测的文件
     * @param {set<std::string>} &excludedDirs 需排除的目录
     * @return {*}
     */
    bool shouldSkipFile(const std::string &file, const std::set<std::string> &excludedDirs);

    /**
     * @brief: 清理空目录
     * @param {set<std::string>} &files 待清理所在目录文件
     * @return {*}
     */
    void removeEmptyDirs(const std::set<std::string> &files);

    /**
     * @brief: 编译 GSettings schema 文件
     * @return {*}
     */
    void handleSchemaCompilation();

    /**
     * @brief: 启动非容器应用相关服务
     * @return {*}
     */
    void startServices();

    /**
     * @description: handle autostart files
     * @return {*}
     */
    void handleAutoStart();

    /**
     * @description: handle desktop files
     * @return {*}
     */
    void handleDesktopFiles();

    /**
     * @description: handle chmod files
     * @return {*}
     */
    void handleChmods();

    void chmodRecursive(const std::string &path, mode_t mode);

    /**
     * @description: 安装时结束进程
     * @return {*}
     */
    void handleInstallKills();

    /**
     * @description: 卸载时结束进程
     * @return {*}
     */
    void handleUninstallKills();

    void processKillList(const std::vector<std::string> &processes);
    /**
     * @description: 卸载时停止服务
     * @return {*}
     */
    void handleStopServices();

    /**
     * @description: 删除指定目录
     * @return {*}
     */
    void handleRmdir();

    /**
     * @brief 处理kare driver
     */
    void handleKareDriver();

    /**
     * @brief 导出desktop文件，开始菜单卸载等使用
     */
    void exportDesktopFile();

    /**
     * @brief 执行钩子脚本
     * 
     * @param scriptPath 脚本路径
     * @param arg 执行动作
     */
    void executeScript(const std::string &scriptPath, const std::string &arg);

    /**
     * @brief  卸载 kare 驱动
     *
     */
    void handleKareUninstall(const std::set<std::string>& installedFiles);

private:
    class Private;
    std::unique_ptr<Private> d;
};

#endif //_KMHOSTAPPDEPLOY_H
