/* common/kmostreecore.cpp
 *
 * Copyright (C) 2023 OpenKylin, Inc
 */

#include "KMOstreeCore.h"

#include <ostree.h>

/**
 * validateCollectionId:
 * @brief : 验证collectionId的合法性
 * @param : [in] collectionId
 * @param : [out] errMsg，错误信息
 * @return: ture-合法; false-不合法
 */
bool KMOstreeCore::validateCollectionId(const std::string &collectionId, std::string &errMsg)
{
    g_autoptr(GError) gerror = NULL;

    bool ret = ostree_validate_collection_id(collectionId.c_str(), &gerror);
    if (!ret && gerror)
    {
        errMsg = gerror->message;
    }

    return ret;
}

/**
 * validateChecksumString:
 * @brief : 验证校验和字符串的正确性
 * @param : [in] checksum，校验和字符串
 * @param : [out] errMsg，错误信息
 * @return: ture-合法; false-不合法
 */
bool KMOstreeCore::validateChecksumString(const std::string &checksum, std::string &errMsg)
{
    g_autoptr(GError) gerror = NULL;

    bool ret = ostree_validate_checksum_string(checksum.c_str(), &gerror);
    if (!ret && gerror)
    {
        errMsg = gerror->message;
    }

    return ret;
}

/**
 * checksumToBytes_v:
 * @brief : 校验和字符串类型转换为KMVariant类型
 * @param : [in] checksum，校验和字符串
 * @return: 转换后的KMVariant类型指针
 */
KMVariant KMOstreeCore::checksumToBytes_v(const std::string &checksum)
{
    return ostree_checksum_to_bytes_v(checksum.c_str());
}

/**
 * @param : [in] dirInfo, a GFileInfo containing directory information
 * @param : [in] xattrs, 可选的扩展属性
 * @return: 一个新的GVariant包含OSTREE_OBECT_TYPE_DIR_META
 */
KMVariant KMOstreeCore::createDirectoryMetadata(KMFileInfo dirInfo, KMVariant *xattrs)
{
    if (xattrs)
    {
        return ostree_create_directory_metadata(dirInfo.get(), xattrs->get());
    }
    else
    {
        return ostree_create_directory_metadata(dirInfo.get(), nullptr);
    }
}

/**
 * @brief : 将二进制校验和转换为字符串格式
 * @param : [in] csum, An binary checksum of length 32.
 * @return: String form of csum .
 * @note: typedef std::basic_string<unsigned char> kmustring;
 *        kmustring里面存放二进制时，对某些符号不支持，不再用于存放二进制数据，改用unsigned char*类型
 */
std::string KMOstreeCore::checksumFromBytes(const unsigned char *csum)
{
    g_autofree char *checksum = NULL;

    checksum = ostree_checksum_from_bytes(csum);
    if (checksum)
    {
        return checksum;
    }
    else
    {
        return "";
    }
}

std::string KMOstreeCore::checksumFromBytesVariant(KMVariant csum_v)
{
    g_autofree char *checksum = NULL;

    checksum = ostree_checksum_from_bytes_v(csum_v.get());
    if (checksum)
    {
        return checksum;
    }
    else
    {
        return "";
    }
}

/**
 * @brief : 从“裸”文件表示转换为OSTREE_OBECT_TYPE_FILE流。这是向OstreRepo写入数据的基本操作。
 * @param : [in] input, 文件原始内容流
 * @param : [in] tmpFileInfo, A file info
 * @param : [in] xattrs, 可选的扩展属性
 * @param : [out] outInput, 序列化的对象流
 * @param : [out] outLength, 流的长度
 * @param : [out] errMsg, 错误信息
 * @return: true-转换成功；false-转换失败
 */
bool KMOstreeCore::rawFileToContentStream(KMInputStream &input, KMFileInfo &tmpFileInfo, KMVariant xattrs, KMInputStream &outInput, std::uint64_t &outLength, std::string &errMsg)
{
    g_autoptr(GError) gerror = nullptr;
    GInputStream *inputStream = nullptr;

    bool ret = ostree_raw_file_to_content_stream(input.get(), tmpFileInfo.get(), xattrs.get(), &inputStream, &outLength, nullptr, &gerror);

    if (ret)
    {
        outInput = inputStream;
    }
    else
    {
        if (gerror)
        {
            errMsg = gerror->message;
        }
    }

    return ret;
}

/**
 * @brief : 获取提交的时间戳
 * @param : [in] commit, Commit对象
 * @return: 自Unix纪元以来的时间戳（秒），UTC
 */
std::uint64_t KMOstreeCore::getTimestampOfCommit(KMVariant &commit)
{
    return ostree_commit_get_timestamp(commit.get());
}

/**
 * @brief : 将校验和从字符串转换为二进制，无需分配内存。在热代码路径中使用此函数。
 * @param : [in] checksum, SHA256字符串校验和
 * @param : [out] buf, 至少有32字节空间的输出缓冲区
 */
void KMOstreeCore::checksumInplaceToBytes(const char *checksum, unsigned char *buf)
{
    ostree_checksum_inplace_to_bytes(checksum, buf);
}

/**
 * @brief : 用csum的已修改base64编码覆盖buf的内容。“已修改”一词指的是使用了字符“_”而不是“/”
 * @param : [in] csum, 长度为32的二进制校验和。
 * @param : [out] buf, 输出位置，长度必须至少为44字节
 */
void KMOstreeCore::checksumB64InplaceFromBytes(const unsigned char *csum, char *buf)
{
    ostree_checksum_b64_inplace_from_bytes(csum, buf);
}

/**
 * @brief : 用字符串化版本的csum覆盖buf的内容。
 * @param : [in] checksum, 长度为32的二进制校验和。
 * @param : [out] buf, 输出位置，长度必须至少为45字节
 * @note  : 上面说明是ostree文档上的，感觉应该是不对的，应该是如下面的才对
 * @param : [in] checksum, base64编码的至少为44字节的校验和
 * @param : [out] buf, 输出位置，长度为32的二进制校验和
 */
void KMOstreeCore::checksumB64InplaceToBytes(const char *checksum, unsigned char *buf)
{
    ostree_checksum_b64_inplace_to_bytes(checksum, buf);
}
