#include "Fields.h"
#include "common/Utils.h"
#include "common/JsonN.h"

std::string& Fields::value(std::string key)
{
    static std::string tmp;
    auto it = mapFields.find(key);
    return (it != mapFields.end()) ? it->second : (tmp = "");
}

bool Fields::contains(std::string key)
{
    return (mapFields.find(key) != mapFields.end());
}

std::string Fields::remove(string key)
{
    std::string val;
    auto it = mapFields.find(key);
    if (it != mapFields.end())
    {
        val = it->second;
        mapFields.erase(it);
    }
    return val;
}

void Fields::append(Fields& datafield)
{
    auto& mapVal = datafield.map();
    for (auto it = mapVal.begin(); it != mapVal.end(); it++)
    {
        mapFields[it->first] = it->second;
    }
}

std::map<string, string>& Fields::map()
{
    return mapFields;
}

int Fields::size()
{
    return mapFields.size();
}

bool Fields::isEmpty()
{
    return mapFields.empty();
}

void Fields::clear()
{
    mapFields.clear();
}

void Fields::check(string key, string val, string d)
{
    auto iter = mapFields.find(key);
    if (iter != mapFields.end() && iter->second == val)
    {
        iter->second = d;
    }
}

void Fields::foreachItem(function<void(string key, string& val)> onForaach)
{
    for (auto it = mapFields.begin(); it != mapFields.end(); it++)
    {
        if (onForaach)
        {
            onForaach(it->first, it->second);
        }
    }
}

bool Fields::is_float_number(string key)
{
    auto& s = mapFields[key];
    if (s.empty())
    {
        return false;
    }
    for (auto& c : s)
    {
        if (std::isdigit(c) == 0 && c != '.')
        {
            return false;
        }
    }
    return  true;
}

string Fields::toStr()
{
    string s;
    for (auto it = mapFields.begin(); it != mapFields.end(); it++)
    {
        if (!s.empty()) s += ",";
        s += ("\"" + it->first + "\":\"" + it->second + "\"");
    }
    return "{" + s + "}";
}

string Fields::toSqlInsert(string tableName)
{
    string key;
    string val;
    for (auto it = mapFields.begin(); it != mapFields.end(); it++)
    {
        if (!key.empty())
        {
            key += ",";
            val += ",";
        }
        key += ("`" + it->first + "`");
        if (it->second == "null" || it->second == "NULL")
        {
            val += "NULL";
        }
        else
        {
            val += ("'" + it->second + "'");
        }
    }
    return "INSERT INTO `" + tableName + "` (" + key + ") VALUES(" + val + ");";
}

string Fields::toSqlUpdate(string tableName, string sql_c)
{
    ostringstream oss;
    oss << "update " << tableName << " set ";
    for (auto iter = mapFields.begin(); iter != mapFields.end(); iter++)
    {
        if (iter != mapFields.begin())
        {
            oss << ",";
        };
        oss << "`" << iter->first << "`=";
        if (iter->second == "null" || iter->second == "NULL")
        {
            oss << "NULL";
        }
        else
        {
            oss << "'" << iter->second << "'";
        }
    }
    oss << " " << sql_c << ";";
    return oss.str();
}

string Fields::toSqlUpdate(string tableName, std::vector<std::string> vecKeys, string condition)
{
    std::map<std::string, bool> map_keys;
    for (auto& k : vecKeys) { map_keys[k] = true; }

    ostringstream oss;
    oss << "update " << tableName << " set ";
    for (auto iter = mapFields.begin(); iter != mapFields.end(); iter++)
    {
        auto& k = iter->first;
        auto& v = iter->second;
        if (!map_keys[k]) { continue; }
        if (iter != mapFields.begin())
        {
            oss << ",";
        };
        oss << "`" << k << "`=";
        if (v == "null" || v == "NULL")
        {
            oss << "NULL";
        }
        else
        {
            oss << "'" << v << "'";
        }
    }
    oss << " " << condition << ";";
    return oss.str();
}

void Fields::parseJson(std::string jsonstr)
{
    njson jsonroot;
    JSON::parse(jsonstr, jsonroot);
    for (auto& item : jsonroot.items())
    {
        this->set(item.key(), item.value());
    }
}