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

#ifndef __KMVARIANTDICT_H__
#define __KMVARIANTDICT_H__

#include <memory>
#include <string>
#include <vector>
#include <stdarg.h>
#include <glib.h>

/**
 * 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__

