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

#ifndef __KMVARIANTDICT_H__
#define __KMVARIANTDICT_H__

#include <glib.h>
#include <stdarg.h>

#include <memory>
#include <string>
#include <vector>


/**
 * KMVariant:
 * @brief : 为了方便使用，对glib中的GVariant类型进行了简单封装
 * @note  :
 *          1. 构建参数类型注意使用glib中GVariant支持的类型，如基础类型等；format格式必需是glib中的GVariant类型支持的格式
 *          2. 当前只定义了使用到的方法，不存在的方法请自行添加
 */
class KMVariant
{
public:
    // template<typename... Args>
    // KMVariant(const char* format, Args&&... args)
    // {
    //     m_variant = g_variant_ref_sink(g_variant_new(format, std::forward<Args>(args)...));
    // }
    KMVariant();
    KMVariant(const char *format, ...);
    KMVariant(GVariant *variant);
    KMVariant(const KMVariant &other);
    KMVariant(KMVariant &&other);

    ~KMVariant();

    KMVariant &operator=(const KMVariant &other);
    KMVariant &operator=(KMVariant &&other);
    KMVariant &operator=(GVariant *variant);

    GVariant *get() { return m_variant; }

    operator bool() const { return m_variant != nullptr; }

    KMVariant getChildValue(std::size_t index);

    template<typename... Args>
    void getChild(std::size_t index, const char *format, Args &&...args)
    {
        if (m_variant)
            g_variant_get_child(m_variant, index, format, std::forward<Args>(args)...);
    }

    bool lookup(const char *key, std::string &value);
    bool lookup(const char *key, std::uint64_t &value);
    bool lookup(const char *key, int &value);
    bool lookup(const char *key, std::vector<std::string> &value);

    KMVariant lookupValue(const char *key, const char *format);

    std::size_t childrenCount();

    std::size_t getSize();
    const void *getData();
    GBytes *getDataAsBytes();

    void clear();

private:
    GVariant *m_variant = nullptr;
};

/**
 * KMVariantBuilder:
 * @brief : 为了方便使用，对glib中的GVariantBuilder类型进行了简单封装
 * @note  :
 *          1. 构建参数formatOfType会转为GVariantType类型，其格式必需是glib中的GVariant类型支持的格式
 *          2. 当前只定义了使用到的方法，不存在的方法请自行添加
 */
class KMVariantBuilder
{
public:
    KMVariantBuilder(const std::string &formatOfType);
    ~KMVariantBuilder();

    template<typename... Args>
    void add(const char *format, Args &&...args)
    {
        g_variant_builder_add(m_builder, format, std::forward<Args>(args)...);
    }

    void addValue(KMVariant value);

    /**
     * @brief : 结束生成器过程并返回构造的值
     */
    KMVariant end();

private:
    GVariantBuilder *m_builder = nullptr;
    std::string m_formatOfType;
};

/**
 * KMVariantDict:
 * @brief : 为了方便使用，对glib中的GVariantDict类型进行了简单封装
 * @note  :
 *          21 当前只定义了使用到的方法，不存在的方法请自行添加
 */
class KMVariantDict
{
public:
    KMVariantDict();
    ~KMVariantDict();

    void insert(const std::string &key, const std::string &value);
    void insert(const std::string &key, std::uint64_t value);
    void insert(const std::string &key, std::int64_t value);
    void insert(const std::string &key, int value);
    void insert(const std::string &key, KMVariant value);

    bool remove(const std::string &key);

    bool contains(const std::string &key) const;

    KMVariant end();

    GVariantDict *get();

    operator bool() const;

private:
    class Private;
    std::shared_ptr<Private> d = nullptr;
};

#endif // !__KMVARIANTDICT_H__
