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

#include "KMKill.h"

#include "common/KMFolder.h"
#include "common/KMLogger.h"

#include "common/KMContainer.h"
#include "common/KMCrun.h"
#include "common/KMConfigData.h"

using namespace std;


class KMKill::Options : public KMOption::Options
{
public:
    Options() = default;
    ~Options() override = default;

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

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

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

public:
    bool m_bHelp;
    std::string args;
};

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

/**
 * @brief 命令行参数解析后操作
 */
void KMKill::Options::postParseHook()
{
    if (m_bHelp)
    {
        showUsage();
        exit(EXIT_SUCCESS);
    }
}

/**
 * @brief 命令行参数添加描述选项
 */
void KMKill::Options::addOptions()
{
   setDescription(_("\nUsage:\n \tkaiming kill [option…] containerid/pid/appid - Stop the running container application\n"));
   
    //帮助选项
    addOption("help","h", KMOption::value<bool>(&m_bHelp)->defaultValue(false), _("Display Help Options"));

    //位置选项
    addPositionOption("ref", KMOption::value<std::string>(&args), 1,_("ref support:\ncontainerId containerId \npid processID \nid applicationID"));
}



REGISTER_SUBCOMMAND_DYNCREATE(kill, KMKill)

class KMKill::Private
{
public:
    std::unique_ptr<Options> options;
};

KMKill::KMKill()
    : m_dPtr(make_shared<Private>())
{
    m_dPtr->options = std::make_unique<Options>();
}

KMKill::~KMKill()
{
}

/**
 * @brief 子命令运行
 * @param argc 参数个数
 * @param argv 参数数组
 * @return int 0 成功
 */
int KMKill::dispose(int argc, char **argv)
{
    m_dPtr->options->parseCommandLine(argc, argv);
    string app = m_dPtr->options->args;

    std::vector<ContainerListItem> item;
    std::vector<string> arg = { "list", "--format=json" };
    //这里调用了crun函数 exec族函数
    if (!KMCrun::exec<std::vector<ContainerListItem>>(arg, item))
    {
        KMError(string("can not find ") + app);
        return EXIT_FAILURE;
    }

    bool bFind = false;
    for (const auto &i : item)
    {
        State itemContainerId;
        std::vector<string> argContainerId = { "state", i.id };
        KMCrun::exec<State>(argContainerId, itemContainerId);

        if (app == itemContainerId.id || app == itemContainerId.annotations.value().at("kaiming.app.id") || app == std::to_string(itemContainerId.pid.value()))
        {
            std::vector<string> args_kill = { "kill", i.id, "SIGKILL" };
            if (!KMCrun::exec(args_kill))
            {
                KMError(string("can not kill ") + app);
                return EXIT_FAILURE;
            }
            bFind = true;
        }
    }

    if (!bFind)
    {
        KMError(string("can not find ") + app);
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}
