#include "KMPS.h"

#include <map>

#include "common/KMLogger.h"
#include "common/KMUtil.h"
#include "common/KMConfigData.h"
#include "common/KMCrun.h"

using namespace std;

/**
 * @brief 安装子命令的参数解析
 */
class KMPS::Options : public KMOptions
{
public:
    Options() = default;
    virtual ~Options() = default;

protected:
    /**
     * @brief 命令行参数解析后操作
     */
    void preParseHook() override;

    /**
     * @brief 命令行参数解析后操作
     */
    void postParseHook() override;

private:
    /**
     * @brief 命令行参数添加描述选项
     */
    void addOptions();

    /**
     * @brief 命令行参数检查项
     */
    void checkOptions(const opt::variables_map &varsMap);

public:
    bool m_bHelp;
    vector<string> m_vecRefs;
};

void KMPS::Options::preParseHook()
{
    addOptions();
}

/**
 * @brief 命令行参数解析后操作
 */
void KMPS::Options::postParseHook()
{
    checkOptions(m_varsMap);

    if (m_bHelp)
    {
        showUsage();
        exit(EXIT_SUCCESS);
    }
}
/**
 * @brief 命令行参数添加描述选项
 */
void KMPS::Options::addOptions()
{
    m_optionsDescription = std::make_unique<opt::options_description>(_("\n用法:\n \tkaiming ps [选项]  - 列出正在运行的容器应用"));

    opt::options_description helpOptions(_("帮助选项"));
    helpOptions.add_options()("help,h", _("显示帮助选项"));

    m_optionsDescription->add(helpOptions);
}

/**
 * @brief 命令行参数检查项
 * @param varsMap 存储命令行参数
 */
void KMPS::Options::checkOptions(const opt::variables_map &varsMap)
{
    checkOption(varsMap, "help", "h", m_bHelp);
}

class KMPS::Private
{
public:
    std::shared_ptr<Options> m_options;
};

REGISTER_SUBCOMMAND_DYNCREATE(ps, KMPS)

KMPS::KMPS()
    : m_dPtr(make_shared<Private>())
{
    init();
}

KMPS::~KMPS()
{
}

/**
 * @brief ps 命令参数处理,不需要参数
 * 列出所有正在运行的容器应用,只支持不含参数
 * 使用实例:
 * kaiming ps
 * @param argc 参数个数
 * @param argv 参数列表
 * @return int 0:成功,非0:失败
 */

int KMPS::despose(int argc, char **argv)
{
    m_dPtr->m_options->parseCommandLine(argc, argv);

    vector<ContainerListItem> item;
    vector<string> args = { "list", "--format=json" };
    if (!KMCrun::exec<vector<ContainerListItem>>(args, item))
    {
        return EXIT_FAILURE;
    }

    std::vector<KMPSInfoList> psInfos;
    for (auto &i : item)
    {
        // 获取信息
        KMPSInfoList psInfo;
        psInfo.containerid = i.id;
        psInfo.pid = i.pid;
        psInfo.path = i.bundle;
        State itemAppid;
        vector<string> argsAppid = { "state", psInfo.containerid };
        if (!KMCrun::exec<State>(argsAppid, itemAppid))
        {
            continue;
        }

        psInfo.appid = itemAppid.annotations.value_or(std::map<std::string, std::string>{})["kaiming.app.id"];
        psInfos.emplace_back(psInfo);
    }

    printAppInfo(psInfos);

    return EXIT_SUCCESS;
}

void KMPS::init()
{
    m_dPtr->m_options = make_shared<Options>();
}

/**
 * @brief 格式化输出包信息
 */
void KMPS::printAppInfo(const vector<KMPSInfoList> &psInfos)
{
    // 打印表头
    printf("%-30s %-40s %-10s %-80s\n", "appid", "containerid", "pid", "path");

    // 遍历数组并打印每个元素
    for (const auto &psInfo : psInfos)
    {
        printf("%-30s %-40s %-10s %-80s\n",
               psInfo.appid.c_str(),
               psInfo.containerid.c_str(),
               to_string(psInfo.pid).c_str(),
               psInfo.path.c_str());
    }
}
