/* KMBuilderCache.h
 *
 * Copyright (C) 2023 OpenKylin, Inc
 */

#ifndef __BUILDER_CACHE_H__
#define __BUILDER_CACHE_H__

#include "KMBuilderContext.h"
#include "KMBuilderConfigTypes.h"

#include <string>
#include <ostree.h>
#include <gio/gio.h>

using namespace std;

/* Bump this if format changes in incompatible ways to force rebuild */
#define BUILDER_EXTENSION_CHECKSUM_VERSION "1"

struct BuilderCache
{
    bool isDisabled;
    string appDir;
    string cacheDir;
    string ccacheDir;
    string buildDir;
    string manifestName;
    string branch;
    string stage;
    string lastParent;
    string curChecksum;
    GChecksum *pChecksum;
    GHashTable *pHashUnusedStages;
    OstreeRepo *repo;
    OstreeRepoDevInoCache *pDevinoToCsumcache;
};

class KMBuilderCache
{
public:
    KMBuilderCache();
    virtual ~KMBuilderCache();

public:
    /**
     * @brief : 初始化
     * @return: true-成功; false-失败
     */
    bool init();

    /**
     * @brief : 禁用缓存
     * @return : true-成功; false-失败
     */
    void disableCache();

    /**
     * @brief : 查找是否已处理
     * @param : stage: 阶段名称
     * @return : true-成功; false-失败
     */
    bool find(const string &stage);

    /**
     * @brief : commit 提交
     * @param : body 提交的内容
     * @return : true-成功; false-失败
     */
    bool commit(const string &body);

    /**
     * @brief : 获取缓存结构
     * @return : 缓存结构
     */
    BuilderCache getBuilderCache();

    /**
     * @brief : 获取改变
     */
    bool getChanges(vector<string> &changes);

    /**
     * @brief : 更新checksum
     * @return : true-成功; false-失败
     */
    void updateInitChecksum();

    /**
     * @brief : 更新module checksum
     * @return : true-成功; false-失败
     */
    void updataModuleChecksum(shared_ptr<KMBuilderModule> &module);

    /**
     * @brief : 执行finish期间更新checksum
     * @return : true-成功; false-失败
     */
    void updateChecksumFinish();

    /**
     * @brief : 执行PlatformPrepare期间更新checksum
     * @return : true-成功; false-失败
     */
    void ChecksumForPlatformBase();
    void ChecksumForPlatformPrepare();
    void checksumForModulesCleanPlatform(const std::vector<std::shared_ptr<KMBuilderModule>> &modules);

    void ChecksumForPlatformFinish();
    void ChecksumForBundleSources();

    /**
     * @brief : 执行finish期间更新checksum
     * @return : true-成功; false-失败
     */
    void updateChecksumFinishJson(const string &json);

    /**
     * @brief : 执行cleanup期间更新checksum
     * @return : true-成功; false-失败
     */
    void updateChecksumcleanup();
    /**
     * @brief : 执行cleanup期间更新checksum
     * @return : true-成功; false-失败
     */
    void ChecksumForCleanup(shared_ptr<BuilderModuleData> self);

    /**
     * @brief : 获取标准输出改变
     * @param : changes 输出改变
     * @return : true-成功; false-失败
     */
    bool getOutstandChanges(vector<string> &changes);

    /**
     * @brief : 确保执行Checkout
     */
    void ensureCheckout();

    vector<string> cacheGetAllChanges();
    vector<string> getAllChanges(GFile *from, GFile *to);

protected:
    /**
     * @brief : 仓库初始化
     * @return: true-成功; false-失败
     */
    bool repoInit();

    /**
     * @brief : 获取ref命令
     * @param : 返回ref名称
     * @return : true-成功; false-失败
     */
    bool getRef(string &ref);

    string getRefStr(string stage);

    /**
     * @brief : 缓存目录checkout
     * @param : commit名
     * @param : isDelDir是否删除目录
     * @return : true-成功; false-失败
     */
    bool checkout(const string &commit, bool isDelDir);

    /**
     * @brief : 更新checksum字符串
     */
    void updateChecksumStr(const string &str);

    /**
     * @brief : 更新checksum bool
     * @param : boolvalue 布尔值
     */
    void updateChecksumBool(bool boolvalue);

    /**
     * @brief : 更新checksum字符串数组
     * @param : vec 字符串数组
     */
    void updateChecksumStrVec(const vector<string> &vec);

    /**
     * @brief : 更新checksum字符串链表
     * @param : vec 字符串数组
     */
    void updateChecksumStrList(const list<string> &l);

    /**
     * @brief : 更新buidextension
     * @param : buidextension 结构体
     */
    void updateBuildExtChecksum(const string &name, const shared_ptr<BuilderExtension> &ext);

    /**
     * @brief : 更新buidoptions
     * @param : KMBuildOptions 结构体
     */
    void updateBuildOptChecksum(shared_ptr<KMBuildOptions> &buildOtions);

    /**
     * @brief : 更新buidextension
     * @param : buidextension 结构体
     */
    void updateChecksumStrVecCompat(const vector<string> &vec);

    /**
     * @brief : variant 解压
     * @param : variant
     * @param : type 类型
     * @return : 解压后的variant
     */
    GVariant *variantUncompress(GVariant *variant, const GVariantType *type);

    /**
     * @brief : variant 压缩
     * @param : variant
     * @return : 压缩后的variant
     */
    GVariant *variantCompress(GVariant *variant);

    /**
     * @brief : 读取文件流
     * @param : in 输入流
     * @param : null_terminate 是否以空字符结尾
     * @return : 返回字节流
     */
    GBytes *readStream(GInputStream *in, bool nullterminate);

    /**
     * @brief : 获取改变
     * @param : from 源目录
     * @param : to 目标目录
     * @param : changes 改变
     * @param : removeChanges 删除改变
     * @return : true-成功; false-失败
     */
    bool doGetChanges(GFile *from, GFile *to, vector<string> &changes, vector<string> &removeChanges);

    /**
     * @brief : 可变树裁剪旧文件
     * @param : mtree 可变树
     * @param : old 旧文件
     * @return : true-成功; false-失败
     */
    bool mtreePruneOldfiles(OstreeMutableTree *mtree, OstreeRepoFile *old);

private:
    BuilderCache m_builderCache;
};

#endif /* __BUILDER_CACHE_H__ */
