#include "Json.h"

//解析对象
int Json::insertObj(const CString JsonStr, Json& json)
{
    int nLen = 0, pos = 0;
    CString key, NowStr;
    for (int i = 0; i < JsonStr.GetLength(); i++)
    {
        NowStr = JsonStr.GetAt(i);
        switch (pos)
        {
        case 0://判断是不是以{开头
            if (NowStr == _T("{"))
            {
                pos = 1;
            }
            else if (NowStr != _T(" "))
            {
                return -1;
            }
            break;
        case 1://拿到Key值
            if (NowStr == _T("\""))
            {
                i = GetValue(JsonStr, i, key);
                if (i == -1)
                {
                    return -1;
                }
                pos = 2;
            }
            else if (NowStr == _T("}"))
            {
                return i;
            }
            else if (NowStr != _T(" "))
            {
                return -1;
            }
            break;
        case 2://判断Key值后面是不是:号
            if (NowStr == _T(":"))
            {
                pos = 3;
            }
            else if (NowStr != _T(" "))
            {
                return -1;
            }
            break;
        case 3://拿到值
            if (NowStr == _T("\""))
            {//这个值是字符串

                Json m_json;
                i = GetValue(JsonStr, i, m_json.value);
                if (i == -1)
                {
                    return -1;
                }
                m_json.type = 3;
                json.valueMap[key] = m_json;
                pos = 4;
            }
            else if (NowStr == _T("["))
            {//这个值是数组
                Json m_json;
                int a = insertArr(JsonStr.Right(JsonStr.GetLength() - i), m_json);
                if (a == -1)
                    return -1;
                json.valueMap[key] = m_json;
                i += a;
                pos = 4;
            }
            else if (NowStr == _T("{"))
            {//这个值是对象
                Json m_json;
                int a = insertObj(JsonStr.Right(JsonStr.GetLength() - i), m_json);
                if (a == -1)
                    return -1;
                json.valueMap[key] = m_json;
                i += a;
                pos = 4;
            }
            else if (NowStr != _T(" ") && NowStr != _T("\r") && NowStr != _T("\n") && NowStr != _T("\t"))
            {//这个值是数字
                Json m_json;
                int a = insertNum(JsonStr.Right(JsonStr.GetLength() - i), m_json);
                if (a == -1)
                    return -1;
                i += a - 1;
                json.valueMap[key] = m_json;
                pos = 4;
            }
            break;
        case 4://判断后面是否有值
            if (NowStr == _T(","))
            {
                pos = 1;
            }
            else if (NowStr == _T("}"))
            {
                return i;
            }
            else if (NowStr != _T(" "))
            {
                return -1;
            }
            break;
        default:
            return -1;
        }
    }
    return -1;
}

//解析数组
int Json::insertArr(const CString JsonStr, Json& json)
{
    json.type = 2;
    int pos = 0;
    CString NowStr;
    int len = JsonStr.GetLength();
    for (int i = 1; i < len; i++)
    {
        NowStr = JsonStr.GetAt(i);
        switch (pos)
        {
        case 0:
            if (NowStr == _T("{"))
            {//数组里面是对象
                Json m_json;
                int a = insertObj(JsonStr.Right(JsonStr.GetLength() - i), m_json);
                if (a == -1)
                    return -1;
                i += a;
                pos = 1;
                json.valueVector.push_back(m_json);
            }
            else if (NowStr == _T("\""))
            {//数组里面是字符串
                Json m_json;
                i = GetValue(JsonStr, i, m_json.value);
                if (i == -1)
                {
                    return -1;
                }
                m_json.type = 3;
                pos = 1;
                json.valueVector.push_back(m_json);
            }
            else if (NowStr == _T("["))
            {//数组里面是数组
                Json m_json;
                int a = insertArr(JsonStr.Right(JsonStr.GetLength() - i), m_json);
                if (a == -1)
                    return -1;
                i += a;
                pos = 1;
                json.valueVector.push_back(m_json);
            }
            else if (NowStr == _T("]"))
            {
                return i;
            }
            else if (NowStr != _T(" "))
            {//数组里面是数字
                Json m_json;
                int a = insertNum(JsonStr.Right(JsonStr.GetLength() - i), m_json);
                if (a == -1)
                    return -1;
                i += a - 1;
                json.valueVector.push_back(m_json);
                pos = 1;
            }
            else if (NowStr == _T("]"))
            {//空数组
                return i;
            }
            break;
        case 1://判断后面是否还有数据
            if (NowStr == _T(","))
            {
                pos = 0;
            }
            else if (NowStr == _T("]"))
            {
                return i;
            }
            else if (NowStr != _T(" "))
            {
                return -1;
            }
            break;
        default:
            return -1;
        }
    }
    return -1;
}

//解析数字
int Json::insertNum(CString str, Json& json)
{
    if (str.Find(_T("true")) == 0)
    {
        //判断是true
        json.type = 5;
        json.value = _T("true");
        return 4;
    }
    else if (str.Find(_T("false")) == 0)
    {
        //判断是false
        json.type = 5;
        json.value = _T("false");
        return 5;
    }
    else if (str.Find(_T("null")) == 0)
    {
        //判断是null
        json.type = 6;
        json.value = _T("null");
        return 4;
    }
    else
    {
        CString tmpStr, NowStr;
        BOOL isFloat = FALSE;
        int len = str.GetLength();
        for (int i = 0; i < len; i++)
        {
            NowStr = str.GetAt(i);
            if (i == 0 && NowStr == _T("-"))
            {
                tmpStr += NowStr;
                continue;
            }
            if (NowStr == "0" || NowStr == "1" || NowStr == "2" || NowStr == "3" || NowStr == "4" || NowStr == "5" || NowStr == "6" || NowStr == "7" || NowStr == "8" || NowStr == "9")
            {
                //是纯数字
                tmpStr += NowStr;
                continue;
            }
            else  if (NowStr == _T("."))
            {
                if (isFloat == FALSE)
                {
                    isFloat = TRUE;
                    tmpStr += NowStr;
                    continue;
                }
                else
                {
                    return -1;
                }
            }
            json.type = 4;
            json.value = tmpStr;
            return i;
        }
        return -1;
    }
}

int Json::GetValue(CString jsonStr, int Begin, CString& value)
{
    CString NowStr;
    int nlen, len = Begin;
    nlen = jsonStr.Find(_T("\""), Begin + 1);
    while (nlen != -1)
    {
        NowStr = jsonStr.GetAt(nlen - 1);
        if (NowStr != _T("\\"))
        {
            value = jsonStr.Mid(Begin + 1, nlen - Begin - 1);
            return nlen;
        }
        len = nlen;
        nlen = jsonStr.Find(_T("\""), len + 1);
    }
    return -1;
}


Json::~Json()
{
    type = 0;
    valueMap.clear();
    valueVector.clear();
}

//解析数据
int Json::parse(CStringA str)
{
    CString JsonStr;
    JsonStr = str;
    int len = parse(JsonStr);
    if (len == -1)
        return -1;
    return ((CStringA)JsonStr.Left(len)).GetLength();
}

//解析数据
int Json::parse(CStringW JsonStr)
{
    valueMap.clear();
    valueVector.clear();
    CString TmpStr = JsonStr;
    int nLen = 0, len = -1;
    TmpStr.Replace(_T("\r"), _T(" "));
    TmpStr.Replace(_T("\n"), _T(" "));
    TmpStr.Replace(_T("\t"), _T(" "));
    TmpStr = TmpStr.TrimLeft();
    nLen = JsonStr.GetLength() - TmpStr.GetLength();
    if (TmpStr.Find(_T("{")) == 0)
    {
        len = insertObj(TmpStr, *this);
    }
    else if (TmpStr.Find(_T("[")) == 0)
    {
        len = insertArr(TmpStr, *this);
    }
    if (len == -1)
    {
        valueMap.clear();
        if (valueVector.size() != 0)
            valueVector.clear();
        value = _T("");
        return -1;
    }
    nLen += len + 1;
    return nLen;
}


Json& Json::operator[](int JsonInt)
{
    if (JsonInt >= valueVector.size())
    {
        return valueMap.end()->second;
    }
    return valueVector[JsonInt];
}

Json& Json::operator[](CStringW JsonStr)
{
    int len = JsonStr.Find(_T("\""));
    CStringW str;
    while (len != -1)
    {
        if (len == 0)
        {
            str += _T("\\\"");
        }
        else if (JsonStr.GetAt(len - 1) != _T('\\'))
        {
            str = str + JsonStr.Left(len) + _T("\\\"");
        }
        JsonStr.Delete(0, len + 1);
        len = JsonStr.Find(_T("\""));
    }
    str += JsonStr;
    return valueMap[str];
}

Json& Json::operator[](CStringA JsonStr)
{
    int len = JsonStr.Find("\"");
    CStringA str;
    while (len != -1)
    {
        if (len == 0)
        {
            str += "\\\"";
        }
        else if (JsonStr.GetAt(len - 1) != '\\')
        {
            str = str + JsonStr.Left(len) + "\\\"";
        }
        JsonStr.Delete(0, len + 1);
        len = JsonStr.Find("\"");
    }
    str += JsonStr;
    return valueMap[(CString)str];
}

void Json::operator=(int JsonInt)
{
    type = 4;
    value.Format(_T("%d"), JsonInt);
    valueMap.clear();
    if (valueVector.size() != 0)
        valueVector.clear();
}

void Json::operator=(CStringA JsonStr)
{
    type = 3;
    valueMap.clear();
    if (valueVector.size() != 0)
        valueVector.clear();
    int len = JsonStr.Find("\"");
    CStringA str;
    while (len != -1)
    {
        if (len == 0)
        {
            str += "\\\"";
        }
        else if (JsonStr.GetAt(len - 1) != '\\')
        {
            str = str + JsonStr.Left(len) + "\\\"";
        }
        JsonStr.Delete(0, len + 1);
        len = JsonStr.Find("\"");
    }
    str += JsonStr;
    value = str;
}

void Json::operator=(CStringW JsonStr)
{
    type = 3;
    valueMap.clear();
    if (valueVector.size() != 0)
        valueVector.clear();
    int len = JsonStr.Find(_T("\""));
    CStringW str;
    while (len != -1)
    {
        if (len == 0)
        {
            str += _T("\\\"");
        }
        else if (JsonStr.GetAt(len - 1) != _T('\\'))
        {
            str = str + JsonStr.Left(len) + _T("\\\"");
        }
        JsonStr.Delete(0, len + 1);
        len = JsonStr.Find(_T("\""));
    }
    str += JsonStr;
    value = str;
}

void Json::operator=(Json json)
{
    type = json.type;
    valueMap = json.valueMap;
    valueVector = json.valueVector;
    value = json.value;
}

void Json::append(Json json)
{
    type = 2;
    value = "";
    valueMap.clear();
    valueVector.push_back(json);
}

void Json::clear()
{
    type = 0;
    value = "";
    valueMap.clear();
    valueVector.clear();
}

void Json::RemoveAt(CStringA Item)
{
    if (valueMap.find((CString)Item) != valueMap.end())
        valueMap.erase((CString)Item);
}

void Json::RemoveAt(CString Item)
{
    if (valueMap.find(Item) != valueMap.end())
        valueMap.erase(Item);
}

void Json::RemoveAt(INT Index)
{
    if (valueVector.size() > Index)
        valueVector.erase(valueVector.begin() + Index);
}

CStringA Json::asCStringA()
{
    CStringA tmp;
    tmp = value;
    switch (type)
    {
    case 3:
        tmp.Replace("\\\"", "\"");
        return tmp;
        break;
    case 4:
        return tmp;
        break;
    case 5:
        return tmp;
        break;
    case 6:
        return tmp;
        break;
    default:
        return "";
        break;
    }
}

CString Json::asCString()
{
    CString tmp;
    switch (type)
    {
    case 3:
        tmp = value;
        tmp.Replace(_T("\\\""), _T("\""));
        return tmp;
        break;
    case 4:
        return value;
        break;
    case 5:
        return value;
        break;
    case 6:
        return value;
        break;
    default:
        return _T("");
        break;
    }
}

int Json::asInt()
{
    switch (type)
    {
    case 3:
        return _ttoi(value);
        break;
    case 4:
        return _ttoi(value);
        break;
    case 5:
        if (value == _T("true"))
            return 1;
        return 0;
        break;
    default:
        return 0;
        break;
    }
    return 0;
}

double Json::asDouble()
{
    switch (type)
    {
    case 3:
        return _ttof(value);
        break;
    case 4:
        return _ttof(value);
        break;
    case 5:
        if (value == _T("true"))
            return 1;
        return 0;
        break;
    default:
        return 0;
        break;
    }
}

//获取数组或者MAP的个数
UINT Json::Size()
{
    size_t len = 0;
    switch (type)
    {
    case 0:
        len = valueMap.size();
        break;
    case 1:
        len = valueMap.size();
        break;
    case 2:
        len = valueVector.size();
        break;
    default:
        break;
    }
    return (UINT)len;
}

std::map<CString, Json>::iterator Json::getBegin()
{
    return valueMap.begin();
}

std::map<CString, Json>::iterator Json::getEnd()
{
    return valueMap.end();
}

std::map<CString, Json>::iterator Json::Find(CString key)
{
    if (type == 0 || type == 1)
    {
        return valueMap.find(key);
    }
    return valueMap.end();
}

CStringW Json::writeCString()
{
    CString str = _T("");
    if (type <= 1)
    {
        str += _T("{");
        if (valueMap.size() == 0)
        {
            str += _T("}");
            return str;
        }
        auto end = valueMap.end();
        end--;
        for (auto tmp = valueMap.begin(); tmp != valueMap.end(); tmp++)
        {
            if (tmp == end)
            {
                str += _T("\"") + tmp->first + _T("\":") + tmp->second.writeCString() + _T("}");
            }
            else
            {
                str += _T("\"") + tmp->first + _T("\":") + tmp->second.writeCString() + _T(",");
            }
        }
    }
    else if (type == 2)
    {
        str += _T("[");
        for (int i = 0; i < valueVector.size(); i++)
        {
            if (i == valueVector.size() - 1)
            {
                str += valueVector[i].writeCString() + _T("]");
            }
            else
            {
                str += valueVector[i].writeCString() + _T(",");
            }
        }
    }
    else if (type == 3)
    {
        str = _T("\"") + value + _T("\"");
    }
    else if (type == 4)
    {
        str = value;
    }
    else if (type == 5)
    {
        str = value;
    }
    else if (type == 6)
    {
        str = value;
    }
    return str;
}

CStringA Json::write()
{
    CStringA str;
    str = writeCString();
    return str;
}