/* kmcreateusb.h
 *
 * Copyright (C) 2024 OpenKylin, Inc
 */

#ifndef __KMCREATEUSB_H__
#define __KMCREATEUSB_H__

#include "app/KMSubCommand.h"
#include "common/KMMetaData.h"
#include "common/KMOptions.h"
#include "common/KMStorageDir.h"
#include "common/kmtranslation.h"

/**
 * @brief export command
 */
class KMCreateUsb : public KMSubCommand
{
    DECLARE_DYNCREATE(KMCreateUsb);

public:
    KMCreateUsb();
    virtual ~KMCreateUsb();

    int despose(int argc, char **argv) override;

private:
    /**
     * @brief 数据解析与环境检查
     * @return true 成功 false 失败
     */
    bool checkEnv(int argc, char **argv);

    /**
     * @brief 是否已导出
     * @return true 存在 false 不存在
     */
    bool isExistExport();

    /**
     * @brief 添加相关信息,包括extions,runtime等
     * @return bool true 成功 false 失败
     */
    bool addRelated(GHashTable *allRefs, GHashTable *allCollectionIds, KMStorageDir &dir, KMRef &ref);
    /**
     * @brief 添加运行时信息
     * @param allRefs 仓库哈希表
     * @param allCollectionIds id哈希表
     * @param ref KMRef结构体
     * @return bool true 成功 false 失败
     */
    bool addRuntime(GHashTable *allRefs, GHashTable *allCollectionIds, KMStorageDir &dir, KMRef &ref);

    /**
     * @brief 更新RemoteArch哈希表
     * @param remote 远程
     * @param arch 架构
     */
    void updateRemoteArchHashTab(GHashTable *allRemoteArch, const string &remote, const string &arch);

    /**
     * @brief 获取deployData信息
     * @param dir 目录
     * @param ref KMRef 结构
     * @param remote 远程名
     * @param commit 提交名
     * @param runtime 运行时
     * @return true 成功 false 失败
     */
    bool getDeployInfo(KMStorageDir &dir, KMRef &ref, string &remote, string &commit, string &runtime);

    /**
     * @brief 操作更新哈希表
     * @param dir 目录
     * @param ref KMRef 结构
     * @param repo 指针
     * @return true 成功 false 失败
     */
    bool doUpdateHashTab(GHashTable *allRefs, GHashTable *allCollectionIds, KMStorageDir &dir, KMRef &ref, OstreeRepo **repo);

    /**
     * @brief 更新哈希表
     */
    void updateHashTab(GHashTable *allRefs, GHashTable *allCollectionIds, KMRef &ref, const string &refCollectionId, const string &remote, const string &commit, char **ppSubpaths);

    /**
     * @brief 添加ostree-metadata和appstream
     * @param allRefs 哈希表
     * @param allCollectionIds 哈希表
     * @param remoteArch 哈希表
     * @param OstreeRepo* 指针
     */
    void addMetaAndAppstream(GHashTable *allRefs, GHashTable *allCollectionIds, GHashTable *remoteArch, OstreeRepo *srcRepo);

    /**
     * @brief 将应用程序或运行时复制到可移动媒体上
     * @return bool true 成功 false 失败
     */
    bool createUsb();

    /**
     * @brief 离线包导出判断ref有效性
     * @param allRefs ref哈希表
     * @param srcRepo OstreeRepo指针
     * @param mountRootPath 导出路径
     * @return true 成功 false 失败
     */
    bool doCreateUsb(GHashTable *allRefs, OstreeRepo *srcRepo, string mountRootPath);

    /**
     * @brief 离线包导出
     * @param allRefs ref哈希表
     * @param srcRepo OstreeRepo指针
     * @param mountRootPath 导出路径
     * @return true 成功 false 失败
     */
    bool ostreeCreateUsb(GHashTable *allRefs, OstreeRepo *srcRepo, string mountRootPath);

private:
    /**
     * @brief 创建软连接
     * @param destRepoPath 目的仓库路径
     * @param destRepoStbuf 目的路径属性结构
     * @return true 成功 false 失败
     */
    bool createSyslink(const string &destRepoPath, const struct stat &destRepoStbuf);

    /**
     * @brief 根据app和runtime判断KaimingKinds值
     * @param app 是否为应用程序
     * @param runtime 是否为运行时
     * @return KaimingKinds值
     */
    bool kaimingkindsFromRools(bool app, bool runtime, KaimingKinds &kinds);

    /**
     * @brief 分解名称，获取对应的id,arch,branch
     * @param name 名称
     * @param id arch brach
     * @return bool ture 成功 false 失败
     */
    bool splitName(const string &name, string &id, string &arch, string &branch);

    /**
     * @brief 获取已安装的目录和ref
     * @param name 名称
     * @param vecDir KMStorageDir目录
     * @param kinds 查询类型
     * @param installDir 返回安装目录
     * @param installRef 返回KMRef结构
     * @return bool ture 成功 false 失败
     */
    bool getDirAndRef(const string &name, vector<KMStorageDir> &vecDir, const KaimingKinds &defaultKinds, KMStorageDir &installDir, KMRef &installRef);

    /**
     * @brief 获取已安装的ref
     * @param name 名称
     * @param dir KMStorageDir目录类型
     * @param kinds 查询类型
     * @param ref 返回的KMRef结构
     * @return bool ture 成功 false 失败
     */
    bool getInstalledKMRef(const string &name, KMStorageDir &dir, const KaimingKinds &kinds, KMRef &ref);

    /**
     * @brief 获取KaimingKinds类型
     * @param name 名称
     * @param kinds 类型
     * @return bool ture 成功 false 失败
     */
    bool getKMKinds(const string &name, KaimingKinds &kinds);

    /**
     * @brief 获取导出的目录
     * @param vecDir 仓库目录集合
     * @return bool ture 成功 false 失败
     */
    bool getInstallKmdir(vector<KMStorageDir> &vecDir);

private:
    class Options;
    class Private;
    std::unique_ptr<Private> d;
};

#endif
