#pragma once

#include <iostream>

#include <rapidjson/document.h>
#include <rapidjson/rapidjson.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
using namespace std;

template <typename T>
class NettyServerResultMsg
{
private:
    // 对应客户端该次请求id,如果为空,则代表为是服务端主动下发消息
	std::string requestId;
	// 服务端下发的数据类型
	std::string dataType;
    // 服务端下发的数据内容
    T data;

public:
    NettyServerResultMsg(/* args */){
    }
    ~NettyServerResultMsg(){
    }
    string getRequestId(){
        return requestId;
    }
    string getDataType(){
        return dataType;
    }
    T getData(){
        return data;
    }
    void setRequestId(string RequestId){
        requestId = RequestId;
    }
    void setDataType(string DataType){
        dataType = DataType;
    }
    void setData(T Data){
        data = Data;
    }

    void objectToJson(std::string& str)
    {
        rapidjson::StringBuffer strBuf;
        rapidjson::Writer<rapidjson::StringBuffer> writer(strBuf);
        writer.StartObject();

        writer.Key("requestId");
        writer.String(requestId.c_str());

        writer.Key("dataType");
        writer.String(dataType.c_str());

        writer.Key("data");
        data.objectToJson(writer);

        writer.EndObject();
        str = strBuf.GetString();
    }

    bool jsonToObject(const std::string& json)
    {
        rapidjson::Document doc;
        if (doc.Parse<rapidjson::kParseCommentsFlag>(json.c_str()).HasParseError()) {
            return false;
        }
        // get members
        const auto end = doc.MemberEnd();

        // json_type
        if (end == doc.FindMember("requestId")){
            return false;
        } else {
            if(doc["requestId"].IsNull()){
                requestId = "";
            }
            else if(doc["requestId"].IsString()){
                requestId = doc["requestId"].GetString();
            }
        }
        if (end == doc.FindMember("dataType") || !doc["dataType"].IsString()) {
            return false;
        } else {
            dataType = doc["dataType"].GetString();
        }
        if (end == doc.FindMember("data") || !doc["data"].IsObject()) {
            return false;
        } else {
            const rapidjson::Value& object = doc["data"];
            if(!(data.jsonToObject(object))){
                return false;
            }
        }
        return true;
    }
};