#ifndef _Fields_H_
#define _Fields_H_

#include <map>
#include <string>
#include <vector>
#include <sstream>
#include <unordered_map>
#include <functional>
using namespace std;

struct PageInfo
{
    int total {0};
    int index {0};
    int size {10};
};

class Fields
{
public:
    Fields() {};

    template <typename T>
    void set(string key, T val, int precision=2)
    {
        stringstream ss;
        ss.precision(precision);
        ss << std::fixed << val;
        mapFields[key] = ss.str();
    }

    template <typename T>
    T get(string key, int precision = 2)
    {
        T val {};
        auto iter = mapFields.find(key);
        if (iter != mapFields.end())
        {
            stringstream ss(iter->second);
            ss.precision(precision);
            ss >> val;
        }
        return val;
    }

    template <typename T>
    void get(string key, T& val, int precision = 2)
    {
        auto iter = mapFields.find(key);
        if (iter != mapFields.end())
        {
            stringstream ss(iter->second);
            ss.precision(precision);
            ss >> val;
        }
    }

    /**
    * 获取值
    * @param: [string key] 索引名称
    */
    std::string& value(std::string key);

    /**
    * 是否包含 key
    * @param: [string key] 索引名称
    * @return: true: 包含； false：不包含
    */
    bool contains(std::string key);

    /**
    * 删除指定索引的值
    * @param: [string key] 索引名称
    */
    std::string remove(string key);

    /**
    * 追加合并
    * @param: [DataFields& fields] 要合并的数据
    */
    void append(Fields& fields);

    /**
    * 获取数据项 map
    */
    std::map<string, string>& map();
    
    /**
    * 获取数据项的大小
    */
    int size();

    /**
    * 判断是否含有数据项
    * @param: [string key] 索引名称
    */
    bool isEmpty();

    /**
    * 清空数据项
    */
    void clear();

    /**
    * 检查某一数据项的值进行替换，如果该项的值是val，则替换成成d
    * @param: [string key] 索引名称
    * @param: [string val] 要检查的值
    * @param: [string d] 替换的值
    */
    void check(string key, string val, string d);

    /**
    * 遍历数据项
    * @param: [function... onForaach] 回调函数
    */
    void foreachItem(function<void(string key, string& val)> onForaach);


    /**
    * 判断数据项是否是float数值类型
    * @param: [string key] 索引名称
    */
    bool is_float_number(string key);

    /**
    * 转换成键值对的字符串格式
    */
    string toStr();

    /**
    * 转换成插入数据的 sql 语句
    * @param: [string tableName] 数据表名称
    */
    string toSqlInsert(string tableName);

    /**
    * 转换成更新数据的 sql 语句
    * @param: [string tableName] 数据表名称
    * @param: [string condition] sql的更新条件，例如： where id='1'
    */
    string toSqlUpdate(string tableName, string condition);

    /**
    * 转换成更新数据的 sql 语句
    * @param: [string tableName] 数据表名称
    * @param: [string vecKeys] 需要更新的字段名称
    * @param: [string condition] sql的更新条件，例如： where id='1'
    */
    string toSqlUpdate(string tableName, std::vector<std::string> vecKeys, string condition);

    void parseJson(std::string jsonstr);

private:
    std::map<string, string> mapFields;
};

#endif