#include "kmcreateusbutils.h"

#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>

#include "common/KMLogger.h"
#include "common/KMUtil.h"

static gboolean locked;
static volatile guint cachedColumns = 0;
static volatile guint cachedLines = 0;

/**
 * @brief 提交和子路径释放函数
 * @param commitSubpath 结构体指针
 * @return void
 */
void commitAndSubpathsFree(CommitAndSubpaths *commitSubpath)
{
    g_free(commitSubpath->commit);
    g_strfreev(commitSubpath->subpaths);
    g_free(commitSubpath);
}

/**
 * @brief 提交和子路径创建函数
 * @param commit 提交字符串指针
 * @param subpaths 子路径指针的指针
 * @return CommitAndSubpaths* 指针
 */
CommitAndSubpaths *commitAndSubpathsNew(const char *commit, const char *const *subpaths)
{
    CommitAndSubpaths *commitSubpath = g_new(CommitAndSubpaths, 1);

    commitSubpath->commit = g_strdup(commit);
    commitSubpath->subpaths = g_strdupv((char **)subpaths);
    return commitSubpath;
}

/**
 * @brief 是否以sudo权限运行
 * @return bool true 是 fase 否
 */
bool runningUnderSudo()
{
    return (getenv("SUDO_COMMAND") == nullptr) ? false : true;
}

/**
 * @brief 分割字符串
 * @param str 字符串
 * @param separator 分割字符串
 * @param front 分割后前面的字符串
 * @return 0 成功 非0 失败
 */
int splits(string &str, const string &separator, string &front)
{
    int pos = str.find(separator);
    if (pos == string::npos)
    {
        front = str;
        return -1;
    }

    front = str.substr(0, pos);
    str = str.substr(pos + 1, str.size() - pos);
    return pos;
}

/**
 * @brief 获取文件描述符和文件状态
 * @param path 路径
 * @param mode 权限
 * @param fd 文件描述符
 * @param st 文件状态
 * @return true 成功 false 失败
 */
bool getFdAndStat(const int &fd, const string &path, const int &flags, int &dfd, struct stat &st)
{
    if (fd == -1)
    {
        dfd = openat(AT_FDCWD, path.c_str(), flags);
    }
    else
    {
        dfd = openat(fd, path.c_str(), flags);
    }

    if (dfd == -1)
    {
        KMError("openat file " + path + " fail ");
        return false;
    }

    if (fstat(dfd, &st) != 0)
    {
        KMError("fstat error");
        return false;
    }

    return true;
}

/**
 * @brief 从部署目录中获取子路径
 * @param subpaths deploy子路径
 * @return 返回子目录数组
 */
char **getSubpathsFromDeploySubpaths(const char *const *ppSubpaths)
{
    g_autoptr(GPtrArray) pResSubpaths = nullptr;

    if (ppSubpaths == nullptr || ppSubpaths[0] == nullptr)
    {
        return nullptr;
    }

    pResSubpaths = g_ptr_array_new_with_free_func(g_free);
    g_ptr_array_add(pResSubpaths, g_strdup("/metadata"));
    for (int i = 0; ppSubpaths[i] != nullptr; i++)
    {
        g_ptr_array_add(pResSubpaths, g_build_filename("/files", ppSubpaths[i], nullptr));
    }
    g_ptr_array_add(pResSubpaths, nullptr);

    return (char **)g_ptr_array_free(KMUtil::stealPointer(&pResSubpaths), false);
}