#include "KMSearch.h"

#include <sys/personality.h>
#include <ctime>
#include <iostream>
#include <sstream>
#include <fcntl.h>
#include <grp.h>
#include <pwd.h>

#ifdef USE_SECCOMP
#  include <seccomp.h>
#endif

#include "common/KMBuildinsUtils.h"
#include "common/KMConfig.h"
#include "common/KMError.h"
#include "common/KMFile.h"
#include "common/KMJsonHelper.h"
#include "common/KMLogger.h"
#include "common/KMOptions.h"
#include "common/KMUtil.h"
#include "common/kmtranslation.h"
#include "common/KMParseSummaryJson.h"


class KMSearch::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;
    std::string m_remote;
    // std::string m_name;
    std::string m_arch;
    vector<string> m_vecRefs;
};

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

void KMSearch::Options::postParseHook()
{
    checkOptions(m_varsMap);

    if (m_bHelp)
    {
        showUsage();
        exit(EXIT_SUCCESS);
    }
}

/**
 * @brief 命令行参数添加描述选项
 */
void KMSearch::Options::addOptions()
{
    m_optionsDescription = std::make_unique<opt::options_description>(_("\nUsage:\n \tkaiming search [OPTION…] <name> - Get info about an app or runtime "));

    opt::options_description helpOptions(_("Help Options"));
    helpOptions.add_options()("help,h", _("Show help options"));

    opt::options_description appOptions(_("Application Options"));
    appOptions.add_options()("arch=ARCH", opt::value<string>(&m_arch), _("Specify query arch"));

    opt::options_description positionalOptions(_("Positional Options"));
    positionalOptions.add_options()("REF...", opt::value<vector<string>>(&m_vecRefs), _("REF..."));

    m_optionsDescription->add(helpOptions).add(appOptions).add(positionalOptions);

    m_optionsPositionalDescription->add("REF...", 1);
}

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

class KMSearch::Private
{
public:
    std::shared_ptr<Options> m_options;
    std::shared_ptr<KMFolder> m_folder;
    std::string m_repoPath;
    std::shared_ptr<KMPackageManager> m_packageManager;
};

REGISTER_SUBCOMMAND_DYNCREATE(search, KMSearch)

KMSearch::KMSearch()
    : d(std::make_unique<Private>())
{
    init();
}

KMSearch::~KMSearch() { }

/**
 * @brief search 命令参数处理
 * 列出所有已安装的软件包信息,只支持不含参数
 * @param argc
 * @param argv
 * @return int
 */
int KMSearch::despose(int argc, char **argv)
{
    vector<string> vecSearch;

    init();

    d->m_options->parseCommandLine(argc, argv);

    if (d->m_options->m_vecRefs.size() < 1)
    {
        kmlogger.error("Args error");
        return KM_ERROR_INVALID_ARGS;
    }

    for (auto &ref : d->m_options->m_vecRefs)
    {
        vecSearch.push_back(ref);
    }


    int ret = start(vecSearch);

    return EXIT_SUCCESS;
}

int KMSearch::start(const vector<string> &vectorIds)
{
    PackageManagerOptions pmOptions;
    pmOptions.relativeRepoPath = d->m_options->m_remote;
    pmOptions.arch = d->m_options->m_arch;
    int ret = d->m_packageManager->processTask(TASK_TYPE_SEARCH, vectorIds, pmOptions);
    
    return ret;
}

string KMSearch:: getRemoteInfo(string name)
{
    PackageManagerOptions pmOptions;
    pmOptions.relativeRepoPath = d->m_options->m_remote;
    pmOptions.isPrint = false;
    string completePath = d->m_packageManager->searchInfo(name, pmOptions);
    return completePath;
}

void KMSearch::init()
{
    d->m_options = make_shared<Options>();
    d->m_folder = shared_ptr<KMFolder>(new KMFolder("/opt/kaiming", false));
    d->m_packageManager = shared_ptr<KMPackageManager>(new KMPackageManager());
}