#include "KMBuilderFinish.h"

KMBuilderFinish::KMBuilderFinish(shared_ptr<KMBuilderCache> cache)
{
    m_pConfigData = builderContext.getBuilderConfig()->getConfigData();
    m_pKMBuilderCache = cache;
    m_builderCache = m_pKMBuilderCache->getBuilderCache();
}

KMBuilderFinish::~KMBuilderFinish()
{
}

bool KMBuilderFinish::builderContextFinish()
{
    //用于获取全局数据
    KMBuilderGlobal global;

    string configFile = "";
    string debuginfoDir = "";
    string sourcesDir = "";
    string localeParentDir = "";
    string json = "";
    vector<string> args;

    //更新checksum
    builderConfigChecksumForFinish();
    //命中缓存就跳过
    if (!m_pKMBuilderCache->find("finish"))
    {
        vector<string> subIds;
        string ref = "";

        string appDir = m_builderCache.appDir; //appdir不存在与context结构体中，需要确认

        //获取ref
        bool buildRuntime = std::any_cast<bool>(m_pConfigData->attributeMap["build-runtime"]);
        bool buildExtension = std::any_cast<bool>(m_pConfigData->attributeMap["build-extension"]);
        string id = std::any_cast<string>(m_pConfigData->attributeMap["id"]);
        string branch = std::any_cast<string>(m_pConfigData->attributeMap["branch"]);
        ref = global.kaimingComposeRef(!buildRuntime && !buildExtension, id, branch, builderContext.getArch());

        string configMetadata = std::any_cast<string>(m_pConfigData->attributeMap["metadata"]);
        //元数据备份
        if (!configMetadata.empty())
        {
            string baseDir = builderContext.getBaseDir();
            string destMetadata = KMBuilderUtils::getChildDir(appDir, "metadata");
            string srcMetadata = KMBuilderUtils::getChildDir(baseDir, configMetadata);
            string contents = "";

            contents = KMBuilderUtils::fileGetContents(srcMetadata);
            bool setRet = KMBuilderUtils::fileSetContents(destMetadata, contents);
            if (!setRet)
            {
                km_logger.info("Write %s is faild!", destMetadata.c_str());
                return false;
            }
        }

        vector<string> inheritExtensions = m_pConfigData->inheritExtensions;
        vector<string> inheritSdkExtensions = m_pConfigData->inheritSdkExtensions;
        if (!inheritExtensions.empty() || !inheritSdkExtensions.empty())
        {
            string metadata = KMBuilderUtils::getChildDir(appDir, "metadata");
            string archOption = "";
            string parentId = "";
            string parentVersion = "";
            string baseMetadata = "";

            archOption = KMBuilderUtils::argSplice("--arch=", KMBuilderUtils::getArch());

            string configBase = std::any_cast<string>(m_pConfigData->attributeMap["base"]);
            string configSdk = std::any_cast<string>(m_pConfigData->attributeMap["sdk"]);
            if (!configBase.empty())
            {
                parentId = configBase;
                string configBranch = global.configGetBranch();
                string configBaseVersion = std::any_cast<string>(m_pConfigData->attributeMap["base-version"]);
                if (configBaseVersion.empty())
                {
                    parentVersion = configBranch;
                }
                else
                {
                    parentVersion = configBaseVersion;
                }
            }
            else
            {
                parentId = configSdk;
                string configRuntimeVersion = std::any_cast<string>(m_pConfigData->attributeMap["runtime-version"]);
                if (configRuntimeVersion.empty())
                {
                    parentVersion = DEFAULT_BRANCH;
                }
                else
                {
                    parentVersion = configRuntimeVersion;
                }
            }

            baseMetadata = KMBuilderUtils::kaiming(1, "info", archOption, "--show-metadata", parentId, parentVersion);
            if (baseMetadata.empty())
            {
                km_logger.error("Inherit extensions specified, but could not get metadata for parent %s version %s", parentId.c_str(), parentVersion.c_str());
            }

            //处理INI参数
            pt::ptree ptBaseKeyFile, ptKeyFile;
            if (!KMBuilderUtils::loadIniData(baseMetadata, ptBaseKeyFile))
            {
                km_logger.error("Can't load metadata file:%s", baseMetadata.c_str());
                return false;
            }
            if (!KMBuilderUtils::loadIniFile(metadata, ptKeyFile))
            {
                km_logger.error("Can't load metadata file:%s", metadata.c_str());
                return false;
            }

            inheritExtensions.clear();

            for (auto inheritExtension : inheritExtensions)
            {
                string group = ("Extension ", inheritExtension);
                vector<string> keys;
                int j;

                if (!KMBuilderUtils::hasGroup(ptBaseKeyFile, group))
                {
                    km_logger.info("Can't find inherited extension point %s", inheritExtension.c_str());
                }

                keys = KMBuilderUtils::getKeys(ptBaseKeyFile, group);
                if (keys.empty())
                {
                    return false;
                }

                for (auto key : keys)
                {
                    string value = KMBuilderUtils::getValue(ptBaseKeyFile, group, key);
                    if (!value.empty())
                    {
                        return false;
                    }
                    KMBuilderUtils::setValue(ptKeyFile, group, key, value);
                }

                if (!KMBuilderUtils::groupHasKey(ptKeyFile, group, "version") && !KMBuilderUtils::groupHasKey(ptKeyFile, group, "versions"))
                {
                    KMBuilderUtils::setValue(ptKeyFile, group, "version", parentVersion);
                }
            }

            if (!KMBuilderUtils::saveToIniFile(ptKeyFile, metadata))
            {
                km_logger.error("Can't save metadata.platform:");
                return false;
            }
        }

        //查找和确认commond所对应的执行文件是否存在
        string command = std::any_cast<string>(m_pConfigData->attributeMap["command"]);
        if (!command.empty())
        {
            string filesDir = appDir + "/" + "files";
            string commandFile = "";

            fs::path fCommond(command);

            string tempApp = "/app/";

            if (!fCommond.is_absolute())
            {
                string binDir = filesDir + "/" + "bin";
                string tempDir = binDir + "/" + command;
                fs::path fTempDir(tempDir);
                if (fs::exists(tempDir))
                {
                    commandFile = binDir + "/" + command;
                }
            }
            else if (command.compare(0, tempApp.size(), tempApp))
            {
                string deleteAppDir = command.substr(strlen("/app/"));
                commandFile = filesDir + "/" + deleteAppDir;
            }

            if (!commandFile.empty() && !fs::exists(commandFile))
            {
                string help = "";
                km_logger.info("commandFile %s is not exists!", commandFile.c_str());
                return false;
            }
        }

        //命令行拼接--------------------------------------------->START
        args.push_back("kaiming");
        args.push_back("build-finish");

        if (!command.empty())
        {
            string argsCommond = "--command=" + command;
            args.push_back(argsCommond);
        }

        vector<string> finishArgs = m_pConfigData->finishArgs;
        if (!finishArgs.empty())
        {
            for (string finishArgs : finishArgs)
                args.push_back(finishArgs);
        }

        map<string, shared_ptr<BuilderExtension>> addBuildExtensions = m_pConfigData->addBuildExtensions;
        for (const auto &pair : addBuildExtensions)
        {
            if (pair.second->removeAfterBuild)
            {
                string argsCommond = "--remove-extension=" + pair.second->name;
                args.push_back(argsCommond);
            }
        }

        map<string, shared_ptr<BuilderExtension>> addExtensions = m_pConfigData->addExtensions;
        for (const auto &pair : addExtensions)
        {
            if (pair.second->directory.empty())
            {
                km_logger.info("No directory specified for extension '%s'", pair.second->name.c_str());
            }
            else
            {
                addArg(pair.second, args, KEY_DIRECTORY, pair.second->directory);
                addArgb(pair.second, args, KEY_AUTODELETE, pair.second->autodelete);
                addArgb(pair.second, args, KEY_NO_AUTODOWNLOAD, pair.second->noAutoDownload);
                addArgb(pair.second, args, KEY_LOCALE_SUBSET, pair.second->localeSubset);
                addArgb(pair.second, args, KEY_SUBDIRECTORIES, pair.second->subdirectories);
                addArg(pair.second, args, KEY_ADD_LD_PATH, pair.second->addLdPath);
                addArg(pair.second, args, KEY_DOWNLOAD_IF, pair.second->downloadIf);
                addArg(pair.second, args, KEY_ENABLE_IF, pair.second->enableIf);
                addArgl(pair.second, args, KEY_MERGE_DIRS, pair.second->mergeDirs);
                addArg(pair.second, args, KEY_SUBDIRECTORY_SUFFIX, pair.second->subdirectorySuffix);
                addArg(pair.second, args, KEY_VERSION, pair.second->version);
                addArgl(pair.second, args, KEY_VERSIONS, pair.second->versions);
            }
        }

        args.push_back(appDir);

        //启动进程，去执行build-finish命令行
        if (!KMBuilderUtils::spawn("", 0, args))
        {
            return false;
        }
        //命令行拼接--------------------------------------------->END

        //序列化ConfigData
        json = builderConfigSerialize(m_pConfigData);

        //确认configFile路径
        bool build_runtime = std::any_cast<bool>(m_pConfigData->attributeMap["build-runtime"]);
        if (build_runtime)
        {
            configFile = appDir + "/" + "usr/manifest.json";
        }
        else
        {
            configFile = appDir + "/" + "files/manifest.json";
        }

        //生成最新备份版本号，对旧manifest.json配置文件做备份
        if (fs::exists(configFile))
        {
            // 获取父目录
            fs::path fConfigFile = configFile;
            fs::path parentDir = fConfigFile.parent_path();
            int ver = 0;
            std::string basename;
            fs::path oldConfig;

            // 生成并查找唯一的旧文件名
            do
            {
                basename = "manifest-base-" + std::to_string(++ver) + ".json";
                oldConfig = parentDir / basename;
            } while (fs::exists(oldConfig));

            // 移动原始文件
            try
            {
                fs::rename(configFile, oldConfig);
            }
            catch (const fs::filesystem_error &e)
            {
                std::cerr << "Error moving manifest file: " << e.what() << '\n';
                return false;
            }
        }

        // 将JSON字符串写入文件
        std::ofstream ofs(configFile);
        if (ofs.is_open())
        {
            ofs << json;
            ofs.close();
        }
        else
        {
            std::cerr << "Unable to open file for writing." << std::endl;
            return false;
        }

        //拼接sourcesDir
        if (buildRuntime)
        {
            debuginfoDir = appDir + "/" + "usr/lib/debug";
            localeParentDir = appDir + "usr" + "/" + SEPARATE_DIR;
        }
        else
        {
            debuginfoDir = appDir + "/" + "files/lib/debug";
            localeParentDir = appDir + "/" + "files" + "/" + SEPARATE_DIR;
        }
        sourcesDir = appDir + "/" + "sources";

        bool separateLocales = std::any_cast<bool>(m_pConfigData->attributeMap["separate-locales"]);

        if (separateLocales && fs::exists(localeParentDir))
        {
            string metadataFile = "";
            string extensionContents = "";
            string output = "";
            string metadataLocaleFile = "";
            string metadataContents = "";

            string localeId = global.configGetVariousId(".Locale");

            metadataFile = KMBuilderUtils::getChildDir(appDir, "metadata");

            //写入metadata
            std::ostringstream oss;
            oss << "\n"
                << "[Extension " << localeId << "]" << std::endl
                << "directory="
                << "share/runtime/locale" << std::endl
                << "autodelete=true" << std::endl
                << "locale-subset=true" << std::endl;
            extensionContents = oss.str();
            // 清空oss以便复用
            oss.str(""); // 清空缓冲区内容

            output = metadataFile;
            if (!KMBuilderUtils::fileSetContents(output, extensionContents))
            {
                return false;
            }

            //写入metadata.locale
            metadataLocaleFile = KMBuilderUtils::getChildDir(appDir, "metadata.locale");
            oss << "[Runtime]" << std::endl << "name=" << localeId << std::endl << std::endl << "[ExtensionOf]" << std::endl << "ref=" << ref << std::endl;
            metadataContents = oss.str();
            // 清空oss以便复用
            oss.str(""); // 清空缓冲区内容

            if (!KMBuilderUtils::fileSetContents(metadataLocaleFile, metadataContents))
            {
                return false;
            }

            subIds.push_back(localeId);
        }

        if (fs::exists(debuginfoDir))
        {
            string metadataFile = "";
            string metadataDebuginfoFile = "";
            string metadataContents = "";
            string extensionContents = "";
            string output = "";
            string debugId = "";
            debugId = global.configGetVariousId(".Debug");

            metadataFile = KMBuilderUtils::getChildDir(appDir, "metadata");
            metadataDebuginfoFile = KMBuilderUtils::getChildDir(appDir, "metadata.debuginfo");

            //写入metadata
            std::ostringstream oss;
            oss << "\n"
                << "[Extension " << debugId << "]" << std::endl
                << "directory=lib/debug" << std::endl
                << "autodelete=true" << std::endl
                << "no-autodownload=true" << std::endl;
            extensionContents = oss.str();
            // 清空oss以便复用
            oss.str(""); // 清空缓冲区内容

            output = metadataFile;
            if (!KMBuilderUtils::fileSetContents(output, extensionContents))
            {
                return false;
            }

            //写入metadata.debuginfo
            oss << "[Runtime]" << std::endl << "name=" << debugId << std::endl << std::endl << "[ExtensionOf]" << std::endl << "ref=" << ref << std::endl;
            metadataContents = oss.str();
            // 清空oss以便复用
            oss.str(""); // 清空缓冲区内容

            if (!KMBuilderUtils::fileSetContents(metadataDebuginfoFile, metadataContents))
            {
                return false;
            }

            subIds.push_back(debugId);
        }

        for (const auto &addExtension : addExtensions)
        {
            std::shared_ptr<BuilderExtension> pBuilderExtension = addExtension.second;
            string extensionMetadataName = "";
            string metadataExtensionFile = "";
            string metadataContents = "";
            string extensionTagOpt = "";

            if (!pBuilderExtension->bundle)
            {
                continue;
            }

            string extensionTag = std::any_cast<string>(m_pConfigData->attributeMap["extension-tag"]);
            if (!extensionTag.empty())
            {
                extensionTagOpt = KMBuilderUtils::argSplice("tag=", extensionTag, "\n");
            }
            else
            {
                extensionTagOpt = "";
            }

            extensionMetadataName = KMBuilderUtils::argSplice("metadata.", pBuilderExtension->name);
            metadataExtensionFile = KMBuilderUtils::getChildDir(appDir, extensionMetadataName);
            //写入metadata
            std::ostringstream oss;
            oss << "[Runtime]" << std::endl << "name=" << pBuilderExtension->name << std::endl << std::endl << "[ExtensionOf]" << std::endl << "ref=" << ref << std::endl << extensionTagOpt;
            metadataContents = oss.str();
            // 清空oss以便复用
            oss.str(""); // 清空缓冲区内容

            if (!KMBuilderUtils::fileSetContents(metadataExtensionFile, metadataContents))
            {
                return false;
            }

            subIds.push_back(pBuilderExtension->name);
        }

        if (subIds.size() > 0)
        {
            string metadataFile = "";
            string output = "";
            string extensionContents = KMBuilderUtils::argSplice("\n", "[Build]\n", "built-extensions=");

            for (auto subId : subIds)
            {
                extensionContents = KMBuilderUtils::argSplice(extensionContents, subId);
                extensionContents = KMBuilderUtils::argSplice(extensionContents, ";");
            }
            metadataFile = KMBuilderUtils::getChildDir(appDir, "metadata");

            if (!KMBuilderUtils::fileSetContents(metadataFile, extensionContents))
            {
                return false;
            }
        }

        //提交commit！
        if (!m_pKMBuilderCache->commit("Finish"))
        {
            return false;
        }
    }
    else
    {
        km_logger.info("Cache hit for finish, skipping");
    }
    return true;
}

void KMBuilderFinish::builderConfigChecksumForFinish()
{
    string json = "";
    m_pKMBuilderCache->updateChecksumFinish();

    string metadata = std::any_cast<string>(m_pConfigData->attributeMap["metadata"]);
    if (!metadata.empty())
    {
        string base_dir = builderContext.getBaseDir();
        string metadataPath = base_dir + "/" + metadata;
        string data = "";

        data = KMBuilderUtils::fileGetContents(metadataPath);
        if (!data.empty())
        {
            m_pKMBuilderCache->updateChecksumFinishJson(data);
        }
        else
        {
            km_logger.info("Can't load metadata file %s", metadata.c_str());
        }
    }

    json = builderConfigSerialize(m_pConfigData);
    m_pKMBuilderCache->updateChecksumFinishJson(json);
}

void KMBuilderFinish::addArg(shared_ptr<BuilderExtension> self, vector<string> &args, string key, string value)
{
    if (value.empty())
    {
        return;
    }
    string argsCommond = "--extension=" + self->name + "=" + key + "=" + value;
    args.push_back(argsCommond);
}

void KMBuilderFinish::addArgb(shared_ptr<BuilderExtension> self, vector<string> &args, string key, bool value)
{
    if (value)
        addArg(self, args, key, "true");
}
void KMBuilderFinish::addArgl(shared_ptr<BuilderExtension> self, vector<string> &args, string key, list<string> value)
{
    if (value.empty())
    {
        return;
    }
    string listStr = "";
    for (auto listValue : value)
    {
        listStr += listValue + "-";
    }
    addArg(self, args, key, listStr);
}

string KMBuilderFinish::builderConfigSerialize(shared_ptr<ConfigData> self)
{
    Json::Value root;

    //attribute_map的map直接存储于root下，反序列化时指定类型
    for (const auto &pair : self->attributeMap)
    {
        noEmptyAddJson(pair.first, pair.second, root);
    }

    Json::Value arr_base_extensions(Json::arrayValue);
    for (auto ex : self->baseExtensions)
    {
        arr_base_extensions.append(ex);
    }

    Json::Value arr_cleanup(Json::arrayValue);
    for (auto ex : self->cleanup)
    {
        arr_cleanup.append(ex);
    }

    Json::Value arr_cleanup_commands(Json::arrayValue);
    for (auto ex : self->cleanupCommands)
    {
        arr_cleanup_commands.append(ex);
    }

    Json::Value arr_cleanup_platform(Json::arrayValue);
    for (auto ex : self->cleanupPlatform)
    {
        arr_cleanup_platform.append(ex);
    }

    Json::Value arr_cleanup_platform_commands(Json::arrayValue);
    for (auto ex : self->cleanupPlatformCommands)
    {
        arr_cleanup_platform_commands.append(ex);
    }

    Json::Value arr_prepare_platform_commands(Json::arrayValue);
    for (auto ex : self->preparePlatformCommands)
    {
        arr_prepare_platform_commands.append(ex);
    }

    Json::Value arr_finish_args(Json::arrayValue);
    for (auto ex : self->finishArgs)
    {
        arr_finish_args.append(ex);
    }

    Json::Value arr_inherit_extensions(Json::arrayValue);
    for (auto ex : self->inheritExtensions)
    {
        arr_inherit_extensions.append(ex);
    }

    Json::Value arr_inherit_sdk_extensions(Json::arrayValue);
    for (auto ex : self->inheritSdkExtensions)
    {
        arr_inherit_sdk_extensions.append(ex);
    }

    Json::Value arr_sdk_extensions(Json::arrayValue);
    for (auto ex : self->sdkExtensions)
    {
        arr_sdk_extensions.append(ex);
    }

    Json::Value arr_platform_extensions(Json::arrayValue);
    for (auto ex : self->platformExtensions)
    {
        arr_platform_extensions.append(ex);
    }

    Json::Value arr_tags(Json::arrayValue);
    for (auto ex : self->tags)
    {
        arr_tags.append(ex);
    }

    //处理build_options结构体
    Json::Value buildOptions;
    builderBuildOptionsToJson(self->buildOptions, buildOptions);

    //处理带结构体的map
    Json::Value addExtensions;
    for (const auto &pair : self->addExtensions)
    {
        string keyName = pair.first;
        Json::Value keyJson;
        builderExtensionToJson(pair.second, keyJson);
        addExtensions[keyName] = keyJson;
    }

    Json::Value addBuildExtensions;
    for (const auto &pair : self->addBuildExtensions)
    {
        string keyName = pair.first;
        Json::Value keyJson;
        builderExtensionToJson(pair.second, keyJson);
        addExtensions[keyName] = keyJson;
    }

    vector<shared_ptr<KMBuilderModule>> vBuilderModule = builderContext.getBuilderConfig()->getModules();
    Json::Value arr_modules(Json::arrayValue);
    for (auto pBuilderModule : vBuilderModule)
    {
        Json::Value keyJson;
        builderModuleToJson(pBuilderModule, keyJson);
        arr_modules.append(keyJson);
    }

    noEmptyArrAddJson("base_extensions", arr_base_extensions, root);
    noEmptyArrAddJson("cleanup", arr_cleanup, root);
    noEmptyArrAddJson("cleanup_commands", arr_cleanup_commands, root);
    noEmptyArrAddJson("cleanup_platform", arr_cleanup_platform, root);
    noEmptyArrAddJson("cleanup_platform_commands", arr_cleanup_platform_commands, root);
    noEmptyArrAddJson("prepare_platform_commands", arr_prepare_platform_commands, root);
    noEmptyArrAddJson("finish_args", arr_finish_args, root);
    noEmptyArrAddJson("inherit_extensions", arr_inherit_extensions, root);
    noEmptyArrAddJson("inherit_sdk_extensions", arr_inherit_sdk_extensions, root);
    noEmptyArrAddJson("sdk_extensions", arr_sdk_extensions, root);
    noEmptyArrAddJson("platform_extensions", arr_platform_extensions, root);
    noEmptyArrAddJson("tags", arr_tags, root);
    noEmptyArrAddJson("modules", arr_modules, root);

    root["m_buildOptions"] = buildOptions;
    root["add_extensions"] = addExtensions;
    root["add_build_extensions"] = addBuildExtensions;

    //序列化
    Json::StyledWriter writer;
    string jsonString = writer.write(root);

    return jsonString;
}

void KMBuilderFinish::builderExtensionToJson(shared_ptr<BuilderExtension> pBuilderExtension, Json::Value &keyJson)
{
    noEmptyAddJson("name", pBuilderExtension->name, keyJson);
    noEmptyAddJson("directory", pBuilderExtension->directory, keyJson);
    noEmptyAddJson("bundle", pBuilderExtension->bundle, keyJson);
    noEmptyAddJson("remove_after_build", pBuilderExtension->removeAfterBuild, keyJson);
    noEmptyAddJson("autodelete", pBuilderExtension->autodelete, keyJson);
    noEmptyAddJson("no_autodownload", pBuilderExtension->noAutoDownload, keyJson);
    noEmptyAddJson("locale_subset", pBuilderExtension->localeSubset, keyJson);
    noEmptyAddJson("subdirectories", pBuilderExtension->subdirectories, keyJson);
    noEmptyAddJson("add_ld_path", pBuilderExtension->addLdPath, keyJson);
    noEmptyAddJson("download_if", pBuilderExtension->downloadIf, keyJson);
    noEmptyAddJson("enable_if", pBuilderExtension->enableIf, keyJson);
    noEmptyAddJson("subdirectory_suffix", pBuilderExtension->subdirectorySuffix, keyJson);
    noEmptyAddJson("version", pBuilderExtension->version, keyJson);

    Json::Value arr_mergeDirs(Json::arrayValue);
    for (auto ex : pBuilderExtension->mergeDirs)
    {
        arr_mergeDirs.append(ex);
    }

    Json::Value arr_versions(Json::arrayValue);
    for (auto ex : pBuilderExtension->versions)
    {
        arr_versions.append(ex);
    }

    keyJson["merge_dirs"] = arr_mergeDirs;
    keyJson["versions"] = arr_versions;
}

void KMBuilderFinish::builderBuildOptionsToJson(shared_ptr<KMBuildOptions> pBuildOptions, Json::Value &keyJson)
{
    noEmptyAddJson("strip", pBuildOptions->m_strip, keyJson);
    noEmptyAddJson("no_debuginfo", pBuildOptions->m_noDebuginfo, keyJson);
    noEmptyAddJson("no_debuginfo_compression", pBuildOptions->m_noDebuginfoCompression, keyJson);
    noEmptyAddJson("cflags", pBuildOptions->m_cFlags, keyJson);
    noEmptyAddJson("cflags_override", pBuildOptions->m_cflagsOverride, keyJson);
    noEmptyAddJson("cppflags", pBuildOptions->m_cppFlags, keyJson);
    noEmptyAddJson("cppflags_override", pBuildOptions->m_cppFlagsOverride, keyJson);
    noEmptyAddJson("cxxflags", pBuildOptions->m_cxxFlags, keyJson);
    noEmptyAddJson("cxxflags_override", pBuildOptions->m_cxxFlagsOverride, keyJson);
    noEmptyAddJson("ldflags", pBuildOptions->m_ldFlags, keyJson);
    noEmptyAddJson("ldflags_override", pBuildOptions->m_ldFlagsOverride, keyJson);
    noEmptyAddJson("append_path", pBuildOptions->m_appendPath, keyJson);
    noEmptyAddJson("prepend_path", pBuildOptions->m_prependPath, keyJson);
    noEmptyAddJson("append_ld_library_path", pBuildOptions->m_appendLdLibraryPath, keyJson);
    noEmptyAddJson("prepend_ld_library_path", pBuildOptions->m_prependLdLibraryPath, keyJson);
    noEmptyAddJson("append_pkg_config_path", pBuildOptions->m_appendPkgConfigPath, keyJson);
    noEmptyAddJson("m_prependPkgConfigPath", pBuildOptions->m_prependPkgConfigPath, keyJson);
    noEmptyAddJson("prefix", pBuildOptions->m_prefix, keyJson);
    noEmptyAddJson("libdir", pBuildOptions->m_libDir, keyJson);

    Json::Value arr_build_args(Json::arrayValue);
    for (auto ex : pBuildOptions->m_buildArgs)
    {
        arr_build_args.append(ex);
    }
    Json::Value arr_test_args(Json::arrayValue);
    for (auto ex : pBuildOptions->m_testArgs)
    {
        arr_test_args.append(ex);
    }
    Json::Value arr_config_opts(Json::arrayValue);
    for (auto ex : pBuildOptions->m_configOpts)
    {
        arr_config_opts.append(ex);
    }
    Json::Value arr_secret_opts(Json::arrayValue);
    for (auto ex : pBuildOptions->m_secretOpts)
    {
        arr_secret_opts.append(ex);
    }
    Json::Value arr_make_args(Json::arrayValue);
    for (auto ex : pBuildOptions->m_makeArgs)
    {
        arr_make_args.append(ex);
    }
    Json::Value arr_make_install_args(Json::arrayValue);
    for (auto ex : pBuildOptions->m_makeInstallArgs)
    {
        arr_make_install_args.append(ex);
    }

    keyJson["build_args"] = arr_build_args;
    keyJson["test_args"] = arr_test_args;
    keyJson["m_configOpts"] = arr_config_opts;
    keyJson["m_secretOpts"] = arr_secret_opts;
    keyJson["m_makeArgs"] = arr_make_args;
    keyJson["m_makeInstallArgs"] = arr_make_install_args;

    for (const auto &pair : pBuildOptions->m_secretEnv)
    {
        keyJson[pair.first] = pair.second;
    }

    for (const auto &pair : pBuildOptions->m_env)
    {
        keyJson[pair.first] = pair.second;
    }
}

void KMBuilderFinish::builderModuleToJson(shared_ptr<KMBuilderModule> pBuilderModule, Json::Value &keyJson)
{
    std::shared_ptr<BuilderModuleData> pBuilderModuleData = pBuilderModule->getData();

    noEmptyAddJson("jsonPath", pBuilderModuleData->m_jsonPath, keyJson);
    noEmptyAddJson("name", pBuilderModuleData->m_name, keyJson);
    noEmptyAddJson("subdir", pBuilderModuleData->m_subdir, keyJson);
    noEmptyAddJson("installRule", pBuilderModuleData->m_installRule, keyJson);
    noEmptyAddJson("testRule", pBuilderModuleData->m_testRule, keyJson);
    noEmptyAddJson("buildSystem", pBuilderModuleData->m_buildSystem, keyJson);
    noEmptyAddJson("disabled", pBuilderModuleData->m_disabled, keyJson);
    noEmptyAddJson("m_rmConfigure", pBuilderModuleData->m_rmConfigure, keyJson);
    noEmptyAddJson("m_noAutogen", pBuilderModuleData->m_noAutogen, keyJson);
    noEmptyAddJson("m_noParallelMake", pBuilderModuleData->m_noParallelMake, keyJson);
    noEmptyAddJson("m_noMakeInstall", pBuilderModuleData->m_noMakeInstall, keyJson);
    noEmptyAddJson("m_noPythonTimestampFix", pBuilderModuleData->m_noPythonTimestampFix, keyJson);
    noEmptyAddJson("cmake", pBuilderModuleData->m_cmake, keyJson);
    noEmptyAddJson("builddir", pBuilderModuleData->m_buildDir, keyJson);
    noEmptyAddJson("m_runTests", pBuilderModuleData->m_runTests, keyJson);

    Json::Value arr_post_install(Json::arrayValue);
    for (auto ex : pBuilderModuleData->m_postInstall)
    {
        arr_post_install.append(ex);
    }

    Json::Value arr_config_opts(Json::arrayValue);
    for (auto ex : pBuilderModuleData->m_configOpts)
    {
        arr_config_opts.append(ex);
    }

    Json::Value arr_secret_opts(Json::arrayValue);
    for (auto ex : pBuilderModuleData->m_secretOpts)
    {
        arr_secret_opts.append(ex);
    }

    Json::Value arr_secret_env(Json::arrayValue);
    for (auto ex : pBuilderModuleData->m_secretEnv)
    {
        arr_secret_env.append(ex);
    }

    Json::Value arr_make_args(Json::arrayValue);
    for (auto ex : pBuilderModuleData->m_makeArgs)
    {
        arr_make_args.append(ex);
    }

    Json::Value arr_make_install_args(Json::arrayValue);
    for (auto ex : pBuilderModuleData->m_makeInstallArgs)
    {
        arr_make_install_args.append(ex);
    }

    Json::Value arr_ensure_writable(Json::arrayValue);
    for (auto ex : pBuilderModuleData->m_ensureWritable)
    {
        arr_ensure_writable.append(ex);
    }

    Json::Value arr_only_arches(Json::arrayValue);
    for (auto ex : pBuilderModuleData->m_onlyArches)
    {
        arr_only_arches.append(ex);
    }

    Json::Value arr_skip_arches(Json::arrayValue);
    for (auto ex : pBuilderModuleData->m_skipArches)
    {
        arr_skip_arches.append(ex);
    }

    Json::Value arr_changes(Json::arrayValue);
    for (auto ex : pBuilderModuleData->m_changes)
    {
        arr_changes.append(ex);
    }

    Json::Value arr_cleanup(Json::arrayValue);
    for (auto ex : pBuilderModuleData->cleanup)
    {
        arr_cleanup.append(ex);
    }

    Json::Value arr_cleanup_platform(Json::arrayValue);
    for (auto ex : pBuilderModuleData->cleanupPlatform)
    {
        arr_cleanup_platform.append(ex);
    }

    Json::Value arr_build_commands(Json::arrayValue);
    for (auto ex : pBuilderModuleData->m_buildCommands)
    {
        arr_build_commands.append(ex);
    }

    Json::Value arr_test_commands(Json::arrayValue);
    for (auto ex : pBuilderModuleData->m_testCommands)
    {
        arr_test_commands.append(ex);
    }

    noEmptyArrAddJson("postInstall", arr_post_install, keyJson);
    noEmptyArrAddJson("configOpts", arr_config_opts, keyJson);
    noEmptyArrAddJson("secretOpts", arr_secret_opts, keyJson);
    noEmptyArrAddJson("secretEnv", arr_secret_env, keyJson);
    noEmptyArrAddJson("makeArgs", arr_make_args, keyJson);
    noEmptyArrAddJson("makeInstallArgs", arr_make_install_args, keyJson);
    noEmptyArrAddJson("ensureWritable", arr_ensure_writable, keyJson);
    noEmptyArrAddJson("onlyArches", arr_only_arches, keyJson);
    noEmptyArrAddJson("skipArches", arr_skip_arches, keyJson);
    noEmptyArrAddJson("changes", arr_changes, keyJson);
    noEmptyArrAddJson("cleanup", arr_cleanup, keyJson);
    noEmptyArrAddJson("cleanup_platform", arr_cleanup_platform, keyJson);
    noEmptyArrAddJson("build_commands", arr_build_commands, keyJson);
    noEmptyArrAddJson("test_commands", arr_test_commands, keyJson);

    //TUDO:YU 功能先略过
    // vector<shared_ptr<KMBuilderSource>> sources;
    // vector<shared_ptr<KMBuilderModule>> modules;
    // shared_ptr<KMBuildOptions> buildOptions;
}

void KMBuilderFinish::noEmptyAddJson(string key, any value, Json::Value &keyJson)
{
    if (value.type() == typeid(std::string) && !std::any_cast<const std::string &>(value).empty())
    {
        keyJson[key] = std::any_cast<const std::string &>(value);
    }
    else if (value.type() == typeid(int))
    {
        keyJson[key] = std::any_cast<int>(value);
    }
    else if (value.type() == typeid(bool))
    {
        keyJson[key] = std::any_cast<bool>(value);
    }
}

void KMBuilderFinish::noEmptyArrAddJson(string key, Json::Value value, Json::Value &keyJson)
{
    if (!value.size() == 0)
    {
        keyJson[key] = value;
    }
}
