#include "KMBuilderExport.h"

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

KMBuilderExport::~KMBuilderExport()
{
}

bool KMBuilderExport::exportStage()
{
    bool isBuildOnly = builderContext.isBuildOnly();
    bool isExportOnly = builderContext.isExportOnly();
    if (!builderContext.isBuildOnly() && !builderContext.isPackageOnly() && (!builderContext.getRepo().empty()) && (builderContext.isExportOnly() || m_builderCache.isDisabled))
    {
        //用于获取全局数据
        KMBuilderGlobal global;

        vector<string> excludeDirs = configGetExcludeDirs();

        if (!builderContext.getRepo().empty())
        {
            m_exportRepo = builderContext.getRepo();
        }

        km_logger.info("Exporting %s to repo!", std::any_cast<string>(m_pConfigData->attributeMap["id"]).c_str());
        //builder_set_term_title (_("Exporting to repository"));

        //参数获取
        bool peripheralRuntime = false;
        string peripheralLocation = m_exportRepo;
        string peripheralDirectory = KMBuilderUtils::getBasename(builderContext.getAppDir());
        string peripheralBranch = global.configGetBranch();
        string peripheralCollectionId = std::any_cast<string>(m_pConfigData->attributeMap["collection-id"]);
        int peripheralTokenType = builderContext.getTokenType();

        //额外参数
        bool separateLocales = std::any_cast<bool>(m_pConfigData->attributeMap["separate-locales"]);
        vector<string> extrArgs;
        extrArgs.push_back("--exclude=/lib/debug/*");
        extrArgs.push_back("--include=/lib/debug/app");
        extrArgs.push_back(separateLocales ? "--exclude=/share/runtime/locale/*/*" : "skip");
        //执行导出
        if (!doExport(peripheralRuntime, peripheralLocation, peripheralDirectory, excludeDirs, peripheralBranch, peripheralCollectionId, peripheralTokenType, extrArgs))
        {
            km_logger.info("Export failed:!");
            return false;
        }

        /* 导出常规区域扩展 */
        vector<string> dirEnum = KMBuilderUtils::enumerateDirectoryPath(builderContext.getAppDir());
        for (auto fileName : dirEnum)
        {
            fileName = KMBuilderUtils::getBasename(fileName);
            KMBuilderGlobal builderGlobal;
            string localeId = builderGlobal.configGetVariousId(".Locale");

            if (fileName.compare("metadata.locale") == 0)
            {
                km_logger.info("Exporting %s to repo", localeId);
            }
            else
            {
                continue;
            }

            //参数获取
            bool runtime = true;
            string location = m_exportRepo;
            string directory = KMBuilderUtils::getBasename(builderContext.getAppDir());
            vector<string> excludeDirsEmpty; //初始化为空
            string branch = global.configGetBranch();
            string collectionId = std::any_cast<string>(m_pConfigData->attributeMap["collection-id"]);
            int tokenType = builderContext.getTokenType();
            //额外参数
            string metadataArg = "";
            string filesArg = "";
            metadataArg = KMBuilderUtils::argSplice("--metadata=", fileName);
            bool bRuntime = std::any_cast<bool>(m_pConfigData->attributeMap["build-runtime"]);
            if (bRuntime)
            {
                filesArg = "--files=usr";
            }
            else
            {
                filesArg = "--files=files";
            }
            filesArg += "/share/runtime/locale/";
            vector<string> extrArgs;
            extrArgs.push_back(metadataArg);
            extrArgs.push_back(filesArg);

            //执行导出
            if (!doExport(runtime, location, directory, excludeDirsEmpty, branch, collectionId, tokenType, extrArgs))
            {
                km_logger.info("Export failed:!");
                return false;
            }
        }

        /* 导出调试扩展 */
        string debuginfoMetadata = "";
        debuginfoMetadata = KMBuilderUtils::getChildPath(builderContext.getAppDir(), "metadata.debuginfo");
        if (KMBuilderUtils::pathExists(debuginfoMetadata))
        {
            KMBuilderGlobal builderGlobal;
            string debug_id = builderGlobal.configGetVariousId(".Debug");
            km_logger.info("Exporting  %s to repo", debug_id.c_str());

            //参数获取
            bool runtime = true;
            string location = m_exportRepo;
            string directory = KMBuilderUtils::getBasename(builderContext.getAppDir());
            vector<string> excludeDirsEmpty; //初始化为空
            string branch = global.configGetBranch();
            string collectionId = std::any_cast<string>(m_pConfigData->attributeMap["collection-id"]);
            int tokenType = builderContext.getTokenType();
            //额外参数
            string filesArg = "";
            bool bRuntime = std::any_cast<bool>(m_pConfigData->attributeMap["build-runtime"]);
            if (bRuntime)
            {
                filesArg = "--files=usr/lib/debug";
            }
            else
            {
                filesArg = "--files=files/lib/debug";
            }

            vector<string> extrArgs;
            extrArgs.push_back("--metadata=metadata.debuginfo");
            extrArgs.push_back(filesArg);

            if (!doExport(runtime, location, directory, excludeDirsEmpty, branch, collectionId, tokenType, extrArgs))
            {
                km_logger.info("Export failed:!");
                return false;
            }
        }

        map<string, shared_ptr<BuilderExtension>> addExtensions = m_pConfigData->addExtensions;
        for (auto builderExtension : addExtensions)
        {
            if (!builderExtension.second->bundle)
            {
                continue;
            }

            string extensionId = builderExtension.second->name;
            string metadataArg = KMBuilderUtils::argSplice("--metadata=metadata.", extensionId);
            string filesArg = "--files=";
            bool bRuntime = std::any_cast<bool>(m_pConfigData->attributeMap["build-runtime"]);
            if (bRuntime)
            {
                filesArg = filesArg + "usr" + "/";
            }
            else
            {
                filesArg += filesArg + "files" + "/";
            }
            filesArg = KMBuilderUtils::argSplice(filesArg, builderExtension.second->directory);
            km_logger.info("Exporting %s to repo", extensionId.c_str());

            string extension_branch = builderExtension.second->version;
            if (extension_branch.empty())
            {
                extension_branch = global.configGetBranch();
            }

            //参数获取
            bool runtime = true;
            string location = m_exportRepo;
            string directory = KMBuilderUtils::getBasename(builderContext.getAppDir());
            vector<string> excludeDirsEmpty; //初始化为空
            string collectionId = std::any_cast<string>(m_pConfigData->attributeMap["collection-id"]);
            int tokenType = builderContext.getTokenType();
            //额外参数

            vector<string> extrArgs;
            extrArgs.push_back(metadataArg);
            extrArgs.push_back(filesArg);

            if (!doExport(runtime, location, directory, excludeDirsEmpty, extension_branch, collectionId, tokenType, extrArgs))
            {
                km_logger.info("Export failed:!");
                return false;
            }
        }

        /* 导出源扩展 */
        string sourcesinfoMetadata = KMBuilderUtils::getChildPath(builderContext.getAppDir(), "metadata.sources");
        if (KMBuilderUtils::pathExists(sourcesinfoMetadata))
        {
            KMBuilderGlobal builderGlobal;
            string sources_id = builderGlobal.configGetVariousId(".Sources");
            km_logger.info("Exporting %s to repo", sources_id);

            //参数获取
            bool runtime = true;
            string location = m_exportRepo;
            string directory = KMBuilderUtils::getBasename(builderContext.getAppDir());
            vector<string> excludeDirsEmpty; //初始化为空
            string branch = global.configGetBranch();
            string collectionId = std::any_cast<string>(m_pConfigData->attributeMap["collection-id"]);
            int tokenType = builderContext.getTokenType();
            //额外参数
            string filesArg = "";
            bool bRuntime = std::any_cast<bool>(m_pConfigData->attributeMap["build-runtime"]);

            vector<string> extrArgs;
            extrArgs.push_back("--metadata=metadata.sources");
            extrArgs.push_back("--files=sources");
            if (!doExport(runtime, location, directory, excludeDirsEmpty, branch, collectionId, tokenType, extrArgs))
            {
                km_logger.info("Export failed:!");
                return false;
            }
        }

        /* 导出平台 */
        string platformId = std::any_cast<string>(m_pConfigData->attributeMap["id-platform"]);
        bool bRuntime = std::any_cast<bool>(m_pConfigData->attributeMap["build-runtime"]);
        if (bRuntime && !platformId.empty())
        {
            km_logger.info("Exporting %s to repo", platformId);

            //参数获取
            bool runtime = true;
            string location = m_exportRepo;
            string directory = KMBuilderUtils::getBasename(builderContext.getAppDir());
            vector<string> excludeDirsEmpty; //初始化为空
            string branch = global.configGetBranch();
            string collectionId = std::any_cast<string>(m_pConfigData->attributeMap["collection-id"]);
            int tokenType = builderContext.getTokenType();
            //额外参数
            string filesArg = "";
            bool bSeparateLocales = std::any_cast<bool>(m_pConfigData->attributeMap["separate-locales"]);
            if (bSeparateLocales)
            {
                filesArg = "--exclude=/share/runtime/locale/*/*";
            }
            else
            {
                filesArg = "skip";
            }

            vector<string> extrArgs;
            extrArgs.push_back("--metadata=metadata.platform");
            extrArgs.push_back("--files=platform");
            extrArgs.push_back(filesArg);
            if (!doExport(runtime, location, directory, excludeDirsEmpty, branch, collectionId, tokenType, extrArgs))
            {
                km_logger.info("Export failed:!");
                return false;
            }
        }

        /* 导出平台本地设置 */
        vector<string> dirEnum2 = KMBuilderUtils::enumerateDirectoryPath(builderContext.getAppDir());
        for (auto fileName : dirEnum2)
        {
            fileName = KMBuilderUtils::getBasename(fileName);
            KMBuilderGlobal builderGlobal;
            string localeId = builderGlobal.configGetVariousIdPlatform(".Locale");
            if (fileName.compare("metadata.platform.locale") == 0)
            {
                km_logger.info("Exporting %s to repo", localeId);
            }
            else
            {
                continue;
            }

            //参数获取
            bool runtime = true;
            string location = m_exportRepo;
            string directory = KMBuilderUtils::getBasename(builderContext.getAppDir());
            vector<string> excludeDirsEmpty; //初始化为空
            string branch = global.configGetBranch();
            string collectionId = std::any_cast<string>(m_pConfigData->attributeMap["collection-id"]);
            int tokenType = builderContext.getTokenType();
            //额外参数
            string metadataArg = KMBuilderUtils::argSplice("--metadata=", fileName);
            string filesArg = "--files=platform/share/runtime/locale/";

            vector<string> extrArgs;
            extrArgs.push_back(metadataArg);
            extrArgs.push_back(filesArg);
            if (!doExport(runtime, location, directory, excludeDirsEmpty, branch, collectionId, tokenType, extrArgs))
            {
                km_logger.info("Export failed:!");
                return false;
            }
        }
    }

    return true;
}

vector<string> KMBuilderExport::configGetExcludeDirs()
{
    vector<string> dirs;
    map<string, shared_ptr<BuilderExtension>> addExtensions = m_pConfigData->addExtensions;

    for (auto builderExtension : addExtensions)
    {
        if (builderExtension.second->bundle)
        {
            dirs.push_back(builderExtension.second->directory);
        }
    }
    return dirs;
}

bool KMBuilderExport::doExport(bool runtime, string location, string directory, vector<string> excludeDirs, string branch, string collectionId, int tokenType, vector<string> extrArgs)
{
    vector<string> args;
    args.push_back("kaiming");
    args.push_back("build-export");

    string archArgs = KMBuilderUtils::argSplice("--arch=", KMBuilderUtils::getArch());
    args.push_back(archArgs);

    if (runtime)
    {
        args.push_back("--runtime");
    }

    if (!builderContext.getSubject().empty())
    {
        string subjectArgs = KMBuilderUtils::argSplice("--subject=", builderContext.getSubject());
        args.push_back(subjectArgs);
    }

    if (!builderContext.getBody().empty())
    {
        string bodyArgs = KMBuilderUtils::argSplice("--body=", builderContext.getBody());
        args.push_back(bodyArgs);
    }

    if (!builderContext.getGpgHomeDir().empty())
    {
        string gpgHomedirArgs = KMBuilderUtils::argSplice("--gpg-homedir=", builderContext.getGpgHomeDir());
        args.push_back(gpgHomedirArgs);
    }

    for (auto gpgSign : builderContext.getGpgHomeDir())
    {
        string gpgSignArgs = KMBuilderUtils::argSplice("--gpg-sign=", gpgSign);
        args.push_back(gpgSignArgs);
    }

    if (!collectionId.empty())
    {
        string collectionIdArgs = KMBuilderUtils::argSplice("--collection-id=", collectionId);
        args.push_back(collectionIdArgs);
    }

    if (tokenType >= 0)
    {
        string tokenTypeArgs = KMBuilderUtils::argSplice("--token-type=", tokenType);
        args.push_back(tokenTypeArgs);
    }

    /* 处理附加参数*/
    for (auto extrArg : extrArgs)
    {
        args.push_back(extrArg);
    }

    //exclude参数添加
    if (excludeDirs.size())
    {
        for (auto exclude_dir : excludeDirs)
        {
            string excludeArgs = KMBuilderUtils::argSplice("--exclude=/", exclude_dir, "/*");
            args.push_back(excludeArgs);
        }
    }

    /* 固定参数. */
    args.push_back(location);
    args.push_back(directory);
    args.push_back(branch);

    //启动进程，去执行build-export命令行
    string tempArgDir = "";
    if (!KMBuilderUtils::spawn(tempArgDir, G_SUBPROCESS_FLAGS_NONE, args))
    {
        return false;
    }

    return true;
}
