#include "KMUninstall.h"

#include <memory>

#include "common/KMError.h"
#include "common/KMFolder.h"
#include "common/KMLogger.h"
#include "common/KMMetaData.h"
#include "common/KMOSTreeHandler.h"

REGISTER_SUBCOMMAND_DYNCREATE(uninstall, KMUninstall)

class KMUninstall::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;
    bool m_assumeYes;
    bool m_unusedYes;
    bool m_deleteDataYes;
    string m_arch;

    string m_sideload;
    string m_repoPath;
    vector<string> m_vecRefs;
};

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

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

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

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

    m_optionsDescription = std::make_unique<opt::options_description>(_("\nUsage:\n \tkaiming uninstall [OPTION…] [REF…] - Uninstall an application or applications "));

    opt::options_description helpOptions(_("Help Options"));
    helpOptions.add_options()("help,h", opt::bool_switch(&m_bHelp)->default_value(false), _("Show help options"));

    opt::options_description appOptions(_("Application Options"));
    appOptions.add_options()("assumeyes,y", opt::bool_switch(&m_assumeYes)->default_value(false), _("Automatically answer all questions yes"))
                            ("arch=ARCH", opt::value<string>(&m_arch), _("Architecture"))
                            ("unused,u", opt::bool_switch(&m_unusedYes)->default_value(false),_("Uninstall all unused runtime environments"))
                            ("delete-data,d", opt::bool_switch(&m_deleteDataYes)->default_value(false),_("Support deleting user data"));

    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 KMUninstall::Options::checkOptions(const opt::variables_map &varsMap)
{
    checkOption(varsMap, "help", "h", m_bHelp);
    checkOption(varsMap, "assumeyes", "y", m_assumeYes);
    checkOption(varsMap, "unused","u",m_unusedYes);
    checkOption(varsMap, "delete-data","d",m_deleteDataYes);

}

class KMUninstall::Private
{
public:
    shared_ptr<KMFolder> m_folder;
    map<string, KMRef> m_mapRefs;
    shared_ptr<KMOSTreeHandler> m_ostreeHandler;

    std::shared_ptr<Options> m_options;
    std::shared_ptr<KMPackageManager> m_packageManager;
};

KMUninstall::KMUninstall()
    : m_dPtr(make_shared<Private>())
{
    m_dPtr->m_folder = make_shared<KMFolder>(KMFolder());
    m_dPtr->m_ostreeHandler = shared_ptr<KMOSTreeHandler>(new KMOSTreeHandler(m_dPtr->m_folder->getRepoPath()));
    m_dPtr->m_mapRefs = m_dPtr->m_ostreeHandler->getLocalRefs(BASE_REOMTE);
}

KMUninstall::~KMUninstall() { }

int KMUninstall::despose(int argc, char **argv)
{
    vector<string> vecUninstall;

    init();
    m_dPtr->m_options->parseCommandLine(argc, argv);
    
     if (m_dPtr->m_options->m_vecRefs.size() < 1)
    {
        kmlogger.error("Args error");
        return KM_ERROR_INVALID_ARGS;
    }

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

    return process(vecUninstall);
}

/// @brief 暂时只支持卸载 app，runtime 不支持卸载
/// @param vec_name 要卸载的 app
/// @return
int KMUninstall::process(const vector<string> &vectorAppIds)
{
    PackageManagerOptions pmOptions;
    pmOptions.assumeYes = m_dPtr->m_options->m_assumeYes;
    pmOptions.unusedYes = m_dPtr->m_options->m_unusedYes;
    pmOptions.deletedataYes = m_dPtr->m_options->m_deleteDataYes;
    pmOptions.arch = m_dPtr->m_options->m_arch;
    pmOptions.relativeRepoPath = m_dPtr->m_options->m_repoPath;

    int ret = m_dPtr->m_packageManager->processTask(TASK_TYPE_UNINSTALL, vectorAppIds, pmOptions);
    return ret;
}

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

}

vector<string> KMUninstall::getRuntimeApp(const string &name)
{
    // 遍历 app 查看依赖

    return vector<string>();
}