﻿#include "jidu_client.h"
#include "jidu_uri.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstring>
#include "cJSON.h"
#include "tracer.h"
#include "algorithm.h"
#include "otxproxy.h"
#include "jidu_vehicleConfig.h"
#include "jidu_dataCenter.h"
#include "MyStringUtils.h"
#include "jidu_envConfig.h"
#include "libxml/parser.h"
#include "libxml/xpath.h"
#include <mutex>
#include <direct.h>
#include "jidu.h"

//TODO true:在staging环境下 日志上传到prod环境中，false：在staging环境下 日志上传到在staging环境中
bool staging_2_prod() {
	bool flag = false;

	string appPath = EnvConfig::getInstance()->getAppPath();
	string cfgPath = appPath.append("Diagnosis.Entry.exe.config");

	//TODO 加载配置文件 Diagnosis.Entry.exe.config
	xmlKeepBlanksDefault(false);
	xmlDoc* xmldoc = xmlParseFile(cfgPath.c_str());
	if (xmldoc != NULL)
	{
		xmlXPathContext* xpathCtx = xmlXPathNewContext(xmldoc);
		xmlXPathObject* xpathObj = xmlXPathEvalExpression(BAD_CAST"/configuration/appSettings", xpathCtx);
		if (xpathObj->nodesetval != NULL) {
			for (size_t i = 0; i < xpathObj->nodesetval->nodeNr; i++)
			{
				xmlNodePtr node = xpathObj->nodesetval->nodeTab[i];
				for (xmlNodePtr child = node->children; child != NULL; child = child->next) {
					if (xmlHasProp(child, BAD_CAST"key")) {
						std::string key = (char*)xmlGetProp(child, BAD_CAST"key");
						if (key._Equal("eolEnvironment") && xmlHasProp(child, BAD_CAST"value")) {
							std::string val = (char*)xmlGetProp(child, BAD_CAST"value");
							if (val._Equal("true")) {
								flag = true;
							}
						}
					}
				}
			}
		}
		xmlXPathFreeContext(xpathCtx);
		xmlFreeDoc(xmldoc);
	}
	else {
		Tracer::error("can't find config", cfgPath);
	}
	xmlKeepBlanksDefault(true);
	return flag;
}

bool IsIntegrationTesting() {
	bool flag = false;

	string appPath = EnvConfig::getInstance()->getAppPath();
	string cfgPath = appPath.append("Diagnosis.Entry.exe.config");

	//TODO 加载配置文件 Diagnosis.Entry.exe.config
	xmlKeepBlanksDefault(false);
	xmlDoc* xmldoc = xmlParseFile(cfgPath.c_str());
	if (xmldoc != NULL)
	{
		xmlXPathContext* xpathCtx = xmlXPathNewContext(xmldoc);
		xmlXPathObject* xpathObj = xmlXPathEvalExpression(BAD_CAST"/configuration/appSettings", xpathCtx);
		if (xpathObj->nodesetval != NULL) {
			for (size_t i = 0; i < xpathObj->nodesetval->nodeNr; i++)
			{
				xmlNodePtr node = xpathObj->nodesetval->nodeTab[i];
				for (xmlNodePtr child = node->children; child != NULL; child = child->next) {
					if (xmlHasProp(child, BAD_CAST"key")) {
						std::string key = (char*)xmlGetProp(child, BAD_CAST"key");
						if (key._Equal("IsIntegrationTesting") && xmlHasProp(child, BAD_CAST"value")) {
							std::string val = (char*)xmlGetProp(child, BAD_CAST"value");
							if (val._Equal("true")) {
								flag = true;
							}
						}
					}
				}
			}
		}
		xmlXPathFreeContext(xpathCtx);
		xmlFreeDoc(xmldoc);
	}
	else {
		Tracer::error("can't find config", cfgPath);
	}
	xmlKeepBlanksDefault(true);
	return flag;
}

bool getMockDataFormat(string& format) {
	bool flag = false;

	string appPath = EnvConfig::getInstance()->getAppPath();
	string cfgPath = appPath.append("Diagnosis.Entry.exe.config");

	//TODO 加载配置文件 Diagnosis.Entry.exe.config
	xmlKeepBlanksDefault(false);
	xmlDoc* xmldoc = xmlParseFile(cfgPath.c_str());
	if (xmldoc != NULL)
	{
		xmlXPathContext* xpathCtx = xmlXPathNewContext(xmldoc);
		xmlXPathObject* xpathObj = xmlXPathEvalExpression(BAD_CAST"/configuration/appSettings", xpathCtx);
		if (xpathObj->nodesetval != NULL) {
			for (size_t i = 0; i < xpathObj->nodesetval->nodeNr; i++)
			{
				xmlNodePtr node = xpathObj->nodesetval->nodeTab[i];
				for (xmlNodePtr child = node->children; child != NULL; child = child->next) {
					if (xmlHasProp(child, BAD_CAST"key")) {
						std::string key = (char*)xmlGetProp(child, BAD_CAST"key");
						if (key._Equal("Eol_Server_MockData_Type") && xmlHasProp(child, BAD_CAST"value")) {
							format = (char*)xmlGetProp(child, BAD_CAST"value");
							flag = true;
						}
					}
				}
			}
		}
		xmlXPathFreeContext(xpathCtx);
		xmlFreeDoc(xmldoc);
	}
	else {
		Tracer::error("can't find config", cfgPath);
	}
	xmlKeepBlanksDefault(true);
	return flag;
}

bool mockDataXml2Json(string xmlPath, string& jsonString) {

	bool flag = false;

	xmlKeepBlanksDefault(false);
	xmlDoc* xmldoc = xmlParseFile(xmlPath.c_str());
	if (xmldoc != NULL)
	{
		xmlXPathContext* xpathCtx = xmlXPathNewContext(xmldoc);
		xmlXPathObject* xpathObj = xmlXPathEvalExpression(BAD_CAST"/root", xpathCtx);
		if (xpathObj->nodesetval != NULL) {
			for (size_t i = 0; i < xpathObj->nodesetval->nodeNr; i++)
			{
				xmlNodePtr node = xpathObj->nodesetval->nodeTab[i];
				xmlChar* nodeName = BAD_CAST node->name;
				cJSON* objRoot = cJSON_CreateObject();
				for (xmlNodePtr child = node->children; child != NULL; child = child->next) {
					if (child->children == NULL) {
						continue;
					}
					xmlChar* childName = BAD_CAST child->name;
					if (0 == xmlStrcmp(childName, BAD_CAST"code")) {
						cJSON_AddNumberToObject(objRoot, "code", stoi((char*)child->children->content));
					}
					else if (0 == xmlStrcmp(childName, BAD_CAST"data")) {
						cJSON* objData = cJSON_CreateObject();
						cJSON* arrayEcuList = cJSON_CreateArray();

						for (xmlNodePtr childData = child->children; childData != NULL; childData = childData->next) {
							xmlChar* childDataName = BAD_CAST childData->name;
							if (childData->children == NULL) {
								continue;
							}
							if (childData->children->content == NULL) {
								if (0 == xmlStrcmp(childDataName, BAD_CAST"ecuList")) {
									cJSON* objEcuListItem = cJSON_CreateObject();
									cJSON* arrayEcuSpwnList = cJSON_CreateArray();
									for (xmlNodePtr ecuItem = childData->children; ecuItem != NULL; ecuItem = ecuItem->next) {
										if (ecuItem->children == NULL) {
											continue;
										}
										xmlChar* itemName = BAD_CAST ecuItem->name;
										if (ecuItem->children->content == NULL) {
											if (0 == xmlStrcmp(itemName, BAD_CAST"ecuSwpnList")) {
												cJSON* objEcuSwpnList = cJSON_CreateObject();
												for (xmlNodePtr ecuSwpnListItem = ecuItem->children; ecuSwpnListItem != NULL; ecuSwpnListItem = ecuSwpnListItem->next) {
													if (ecuSwpnListItem->children == NULL) {
														continue;
													}
													xmlChar* itemEcuSwpnListName = BAD_CAST ecuSwpnListItem->name;
													if (ecuSwpnListItem->children->content == NULL) {
														continue;
													}
													string content = (char*)ecuSwpnListItem->children->content;
													MyStringUtils::replace(content, "\n", "");
													MyStringUtils::replace(content, "\t", "");
													cJSON_AddStringToObject(objEcuSwpnList, (char*)itemEcuSwpnListName, content.c_str());
												}
												cJSON_AddItemToArray(arrayEcuSpwnList, objEcuSwpnList);
											}
											continue;
										}
										string content = (char*)ecuItem->children->content;
										MyStringUtils::replace(content, "\n", "");
										MyStringUtils::replace(content, "\t", "");
										cJSON_AddStringToObject(objEcuListItem, (char*)itemName, content.c_str());
									}

									cJSON_AddItemToObject(objEcuListItem, "ecuSwpnList", arrayEcuSpwnList);
									cJSON_AddItemToArray(arrayEcuList, objEcuListItem);
								}

								continue;
							}
							string content = (char*)childData->children->content;
							MyStringUtils::replace(content, "\n", "");
							MyStringUtils::replace(content, "\t", "");
							cJSON_AddStringToObject(objData, (char*)childDataName, content.c_str());
						}
						cJSON_AddItemToObject(objData, "ecuList", arrayEcuList);
						cJSON_AddItemToObject(objRoot, "data", objData);
					}
					else {
						cJSON_AddStringToObject(objRoot, (char*)childName, (char*)child->children->content);
					}
				}

				char* temp = cJSON_Print(objRoot);
				jsonString.assign(temp);
				MyStringUtils::replace(jsonString, "\n", "");
				MyStringUtils::replace(jsonString, "\t", "");
				cJSON_free(temp);
				cJSON_Delete(objRoot);
			}

			flag = true;
		}
		xmlXPathFreeContext(xpathCtx);
		xmlFreeDoc(xmldoc);
	}
	else {
		Tracer::error("can't find xml", xmlPath);
	}
	xmlKeepBlanksDefault(true);

	return flag;
}

JiduClient* JiduClient::instance;
JiduClient::JiduClient()
{
	loadEnvirment();
	loadParam();
}

JiduClient::~JiduClient()
{

}

void JiduClient::init()
{
	if (!EnvConfig::getInstance()->checkEnvironment())
	{
		this->keyPem.clear();
		loadEnvirment();
		loadParam();
	}
}

inline bool file_exists(const std::string& filepath) {
	if (FILE* file = fopen(filepath.c_str(), "r")) {
		fclose(file);
		return true;
	}
	else {
		return false;
	}
}

int  JiduClient::parsed(string& response) {

	int ret = -1;
	cJSON* objRoot = cJSON_Parse(response.c_str());
	if (objRoot != NULL) {
		int ackCode = -1;
		cJSON* objCode = cJSON_GetObjectItem(objRoot, "code");
		if (cJSON_IsString(objCode)) {
			ackCode = atoi(cJSON_GetStringValue(objCode));
			cJSON_ReplaceItemInObject(objRoot, "code", cJSON_CreateNumber(ackCode));
		}
		else if (cJSON_IsNumber(objCode)) {
			ackCode = objCode->valueint;
		}

		ret = ackCode;

		if (ackCode == 0 || ackCode == 200) {
			cJSON* objData = cJSON_GetObjectItem(objRoot, "data");
			if (cJSON_IsObject(objData) && cJSON_HasObjectItem(objData, "data")) {
				char* temp = cJSON_PrintUnformatted(objData);
				response = temp;
				cJSON_free(temp);
				cJSON_Delete(objRoot);
				return parsed(response);
			}
		}
		else {
			cJSON* objMsg = NULL;
			if (cJSON_HasObjectItem(objRoot, "message")) {
				objMsg = cJSON_GetObjectItem(objRoot, "message");
			}
			else if (cJSON_HasObjectItem(objRoot, "msg")) {
				objMsg = cJSON_GetObjectItem(objRoot, "msg");
			}

			if (objMsg != NULL && cJSON_IsString(objMsg))
			{
				DataCenter::getInstance()->errMsg = objMsg->valuestring;
			}
		}

		char* temp = cJSON_PrintUnformatted(objRoot);
		response = temp;
		cJSON_free(temp);
		cJSON_Delete(objRoot);
	}

	return ret;
}



static std::mutex mLock;
int JiduClient::callServer(int iType, string inParams, char* outBuffer, unsigned int outBufferSize)
{
	std::lock_guard<std::mutex> lock(mLock);
	DataCenter::m_callServerRecord[iType].response.clear();
	init();
	Tracer::logger("callServer.interface", to_string(iType));
	callServer_preHandler(iType, inParams);

	string url;
	string body;
	string response;
	if (vtable[iType].host == "diag" || vtable[iType].host == "cfg") {

		//获取Token
		string token;
		if (!getAccessToken(token)) {
			Tracer::error("miss token", "no login");
			return -1;
		}
		this->setToken(token);

		cJSON* objProxy = cJSON_CreateObject();

		if (vtable[iType].host == "diag") {
			url = this->diagHost + "/api/business/apiProxy/invoke" + "?lang=" + DataCenter::getInstance()->language;

			//TODO pki接口要添加powerType
			if (MyStringUtils::startWith(vtable[iType].url, "/vehicle/cert")) {
				add_powerType(inParams);
				add_carType(inParams);
			}
		}
		else if (vtable[iType].host == "cfg") {
			url = this->cfgHost + "/business/apiProxy/invoke";
			cJSON_AddBoolToObject(objProxy, "asynchronous", true);
		}

		//TODO 更新DeviceSN
		if (!DataCenter::m_deviceSN.empty() && !this->deviceSn._Equal(DataCenter::m_deviceSN)) {
			this->deviceSn = DataCenter::m_deviceSN;
		}

		string serviceName = "diagnostic-adapter-service";
		cJSON_AddStringToObject(objProxy, "serviceName", serviceName.c_str());
		cJSON_AddStringToObject(objProxy, "method", vtable[iType].method.c_str());
		cJSON_AddStringToObject(objProxy, "contentType", "application/json");
		cJSON_AddStringToObject(objProxy, "invoke", vtable[iType].url.c_str());

		cJSON_AddStringToObject(objProxy, "content", inParams.c_str());
		string timeStamp = std::to_string(get_currentTimeStamp() / 1000);
		cJSON_AddStringToObject(objProxy, "timestamp", timeStamp.c_str());

		string signature;
		string plainMsg = inParams + vtable[iType].url + vtable[iType].method + serviceName + timeStamp;
		ecdsa_signature(plainMsg, this->keyPem, signature);

		cJSON_AddStringToObject(objProxy, "signature", signature.c_str());
		cJSON_AddStringToObject(objProxy, "serialNo", this->deviceSn.c_str());
		char* pBuffer = cJSON_PrintUnformatted(objProxy);
		body.assign(inParams);
		post(url, pBuffer, response);
		cJSON_Delete(objProxy);
		cJSON_free(pBuffer);
	}
	else if (vtable[iType].host == "eol")
	{
		url = this->eolHost + vtable[iType].url;
		//TODO 判断是否为集成测试环境
		if (IsIntegrationTesting()) {
			if (vtable[iType].method == "GET") {
				if (!inParams.empty()) {
					url = url + "?" + inParams;
				}
				Tracer::logger("GET", url);
			}
			else if (vtable[iType].method == "POST") {
				string bodyParams = inParams;
				Tracer::logger("POST", url);
				Tracer::logger("Body", inParams);
			}

			string appPath = EnvConfig::getInstance()->getAppPath();
			string tempUrl = vtable[iType].url;
			tempUrl = tempUrl.substr(string("/open/diagnosis/").length());
			string format = "json";
			if (!getMockDataFormat(format)) {
				Tracer::error(__FUNCTION__, "invalid mockData format");
			}
			if (format._Equal("json")) {
				string fileName = MyStringUtils::replace(tempUrl, "/", "_") + ".json";
				string filepath = appPath + "EolServerMockData\\" + fileName;
				Tracer::warn("mockFile", filepath);

				FILE* fp = fopen(filepath.c_str(), "r");
				if (fp != NULL) {
					fseek(fp, 0, SEEK_END);
					int fileLen = ftell(fp);
					fseek(fp, 0, SEEK_SET);
					char* fBuffer = (char*)malloc(fileLen + 1);
					fread(fBuffer, 1, fileLen, fp);
					fclose(fp);
					response.assign(fBuffer);
					free(fBuffer);
				}
				else {
					Tracer::error("invalid mock data", filepath);
					return 0;
				}
			}
			else if (format._Equal("xml")) {
				string fileName = MyStringUtils::replace(tempUrl, "/", "_") + ".xml";
				string filepath = appPath + "EolServerMockData\\" + fileName;
				Tracer::warn("mockFile", filepath);

				if (!mockDataXml2Json(filepath, response)) {
					Tracer::error("invalid mock data", filepath);
					return 0;
				}
			}
		}
		else {
			url = this->eolHost + vtable[iType].url;
			if (vtable[iType].method == "GET") {
				if (!inParams.empty()) {
					url = url + "?" + inParams;
				}
				get(url, response);
			}
			else if (vtable[iType].method == "POST") {
				string bodyParams = inParams;
				post(url, bodyParams, response);
			}
		}
	}
	else if (vtable[iType].host == "pki") {
		url = this->pkiHost + vtable[iType].url;

		setClientCert(this->certPem);
		setClientKey(this->keyPem);

		if (vtable[iType].method == "GET") {
			if (!inParams.empty()) {
				url = url + "?" + inParams;
			}
			get(url, response);
		}
		else if (vtable[iType].method == "POST") {
			add_powerType(inParams);
			post(url, inParams, response);
			body.assign(inParams);
		}
	}
	else {
		Tracer::error("invalid host", vtable[iType].host.c_str());
		return -3;
	}

	DataCenter::m_callServerRecord[iType].host = vtable[iType].host;
	DataCenter::m_callServerRecord[iType].uri = vtable[iType].url;
	DataCenter::m_callServerRecord[iType].body = body;
	DataCenter::m_callServerRecord[iType].method = vtable[iType].method;

	DataCenter::getInstance()->errMsg.clear();
	if (response.empty()) {
		DataCenter::getInstance()->errMsg = vtable[iType].url + "\n接口数据为空";
		Tracer::error(vtable[iType].url, "接口没有获取到数据");
	}
	else {
		int ackCode = parsed(response);
		if (ackCode == 0 || ackCode == 200) {
			//TODO 打印日志
			Tracer::logger("callServer.res.len", to_string(response.length()));
			cJSON* objRoot = cJSON_Parse(response.c_str());
			if (vtable[iType].host == "pki") {
				desensitize(objRoot);
				Tracer::json("callServer.response", objRoot);
			}
			else if (iType != 28) {
				Tracer::json("callServer.response", objRoot);
			}
			cJSON_Delete(objRoot);

			int retCode = callServer_affterHandler(iType, inParams, response);
			if (retCode < 0) {
				DataCenter::getInstance()->errMsg = vtable[iType].host + "服务器数据错误";
				Tracer::error(vtable[iType].url, "服务器数据错误,缺少必要项");
				return retCode;
			}

			if (0 == outBufferSize) {
				return (int)response.length();
			}
			if (outBufferSize < response.length()) {
				Tracer::error("callServer", "buffer size too small");
				return -1;
			}
			memset(outBuffer, 0, outBufferSize);
			memcpy(outBuffer, response.c_str(), response.length());
			return (int)response.length();
		}
		else if (ackCode == -1) {
			DataCenter::getInstance()->errMsg = "接口没有获取到数据";
		}
		else {
			Tracer::error("response", response);
			if ((iType == 21 || iType == 55) && (ackCode == 9002 || ackCode == 9004 || ackCode == 9005)) {
				char keyBuffer[128] = { 0 };
				base64_encode((uint8_t*)"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF", 16, keyBuffer, 128);
				DataCenter::m_aesKey["ACU"] = keyBuffer;
				DataCenter::m_aesKey["BGM"] = keyBuffer;
				DataCenter::m_aesKey["CDC"] = keyBuffer;
				DataCenter::m_aesKey["TCAM"] = keyBuffer;
				return 0;
			}
			else {
				DataCenter::getInstance()->errMsg = DataCenter::getInstance()->errMsg;
			}
		}
	}

	return -2;
}
/***************************************************************
* 函数:
* 参数:
* 参数：
* 返回:
/***************************************************************/
bool JiduClient::loadParam(void)
{
	if (this->certPem.empty() || this->keyPem.empty()) {

		string appPath = EnvConfig::getInstance()->getAppPath();
		string pverPath = appPath.append("pver");
		FILE* fp = fopen(pverPath.c_str(), "r");
		if (fp == NULL) {
			Tracer::error("pver文件打开失败, errno", to_string(errno));
			/*system("pause");*/
			return false;
		}

		fseek(fp, 0, SEEK_END);
		int fileSize = ftell(fp);
		fseek(fp, 0, SEEK_SET);
		char* fileBuff = (char*)malloc(fileSize + 1);
		fread(fileBuff, 1, fileSize, fp);
		fclose(fp);

		cJSON* objRoot = cJSON_Parse(fileBuff);
		if (objRoot == NULL) {
			Tracer::error(__FUNCTION__, "pver json parse err.");
			cJSON_Delete(objRoot);
			return false;
		}

		cJSON* objItem = cJSON_GetObjectItem(objRoot, "deviceID");
		if (!cJSON_IsNull(objItem))
		{
			this->deviceSn = objItem->valuestring;
		}

		objItem = cJSON_GetObjectItem(objRoot, "certPwd");
		if (objItem == NULL) {
			Tracer::error(__FUNCTION__, "certPwd json parse err.");
			cJSON_Delete(objRoot);
			return false;
		}

		int environmentCode = EnvConfig::getInstance()->getEnvironment();
		if (DataCenter::getInstance()->factory._Equal("DMA")) {
			environmentCode += 6;
		}

		cJSON* item_certPwd = cJSON_GetObjectItem(objItem, to_string(environmentCode).c_str());
		if (cJSON_IsNull(item_certPwd)) {
			Tracer::error(__FUNCTION__, "certPwd decrypted err.");
			cJSON_Delete(objRoot);
			return false;
		}
		unsigned char data[64] = { 0 };
		char* tempString = cJSON_GetStringValue(item_certPwd);
		if (tempString == NULL) {
			Tracer::error(__FUNCTION__, "certPwd is null.");
			cJSON_Delete(objRoot);
			return false;
		}
		int bLen = base64_decode(tempString, (int)strlen(tempString), data, 64);
		char certPwd[64] = { 0 };
		int rLen = des_cbc_pkcs5_decrypt(data, bLen, (char*)"siuhuali", certPwd, 64);
		if (rLen < 0) {
			Tracer::error(__FUNCTION__, "certPwd decrypted err.");
			cJSON_Delete(objRoot);
			return false;
		}

		objItem = cJSON_GetObjectItem(objRoot, "certName");
		if (objItem == NULL) {
			Tracer::error(__FUNCTION__, "certName json parse err.");
			cJSON_Delete(objRoot);
			return false;
		}
		cJSON* item_certName = cJSON_GetObjectItem(objItem, to_string(environmentCode).c_str());
		string certName = cJSON_GetStringValue(item_certName);
		string certPath = this->certDir + certName;
		gen_pem(certPath, certPwd, this->certPem, this->keyPem);

		cJSON_Delete(objRoot);
		if (this->deviceSn.empty() && !DataCenter::getInstance()->m_deviceSN.empty()) {
			this->deviceSn = DataCenter::getInstance()->m_deviceSN;
		}

		if (DataCenter::getInstance()->m_deviceSN.empty() && !this->deviceSn.empty()) {
			DataCenter::getInstance()->m_deviceSN = this->deviceSn;
		}

		Tracer::debug("deviceSn", this->deviceSn);
		Tracer::debug("certPath", certPath);
		Tracer::debug("certPwd", certPwd);
		return true;
	}

	return true;
}
/***************************************************************
* 函数:
* 参数:
* 参数：
* 返回:
/***************************************************************/
bool JiduClient::loadEnvirment()
{
	string appPath = EnvConfig::getInstance()->getAppPath();
	int currentEnvironment = EnvConfig::getInstance()->getEnvironment();

	if (DataCenter::getInstance()->factory._Equal("PMA")) {
		switch (currentEnvironment)
		{
		case App_Env_Dev: {
			this->certDir = appPath + "pkiCertificate/PMA/Dev/";
			this->eolHost = "https://eol-server-service-dev.jiduauto.com/eol-server";
			this->pkiHost = "https://pki-thirdparty.jidudev.com/thirdparty";
			this->cfgHost = "https://diagnostic-test.jiduauto.com/workshopbms/api";
			this->diagHost = "https://diagnostic-service.jidudev.com/api/diagnostic-service";
			break;
		}
		case App_Env_Test: {
			this->certDir = appPath + "pkiCertificate/PMA/Test/";
			this->eolHost = "https://eol-server-service.jidupmatest.com/eol-server";
			this->pkiHost = "https://pma-pki-thirdparty.jidupmatest.com";
			this->cfgHost = "https://diagnostic.jidupmatest.com/workshopbms/api";
			this->diagHost = "https://diagnostic-service.jidutest.com/api/diagnostic-service";
			break;
		}
		case App_Env_Staging: {
			this->certDir = appPath + "pkiCertificate/PMA/Staging/";
			this->eolHost = "https://eol-server-service-staging.jiduauto.com/eol-server";
			this->pkiHost = "https://pma-pki-thirdparty.jidupmastaging.com";
			this->cfgHost = "https://diagnostic-factory-service.jidustaging.com/api/diagnostic-factory-service/api";
			this->diagHost = "https://diagnostic-service.jidustaging.com/api/diagnostic-service";

			if (staging_2_prod())
			{
				this->eolHost = "https://eol-server-service.jidudma.com/eol-server";
			}
			break;
		}

		case App_Env_Prod: {
			this->certDir = appPath + "pkiCertificate/PMA/Prod/";
			this->eolHost = "https://eol-server-service.jidupma.com/eol-server";
			this->pkiHost = "https://pma-pki-thirdparty.jidupma.com";
			this->cfgHost = "https://diagnostic.jidupma.com/workshopbms/api";
			this->diagHost = "https://diagnostic-service.jiduprod.com/api/diagnostic-service";
			break;
		}

		default: {
			break;
		}
		}
	}
	else if (DataCenter::getInstance()->factory._Equal("DMA")) {
		switch (currentEnvironment)
		{
		case App_Env_Dev: {
			this->certDir = appPath + "pkiCertificate/DMA/Dev/";
			this->eolHost = "https://eol-server-service-dev.jiduauto.com/eol-server";
			this->pkiHost = "https://pki-thirdparty.jidudev.com/thirdparty";
			this->cfgHost = "https://diagnostic-dma-factory-service.jidudev.com/api/diagnostic-factory-service/api";
			this->diagHost = "https://diagnostic-service.jidudev.com/api/diagnostic-service";
			break;
		}
		case App_Env_Test: {
			this->certDir = appPath + "pkiCertificate/DMA/Test/";
			this->eolHost = "https://eol-server-service.jidudmatest.com/eol-server";
			this->pkiHost = "https://dma-pki-thirdparty.jidudmatest.com";
			this->cfgHost = "https://diagnostic.jidudmatest.com/api/diagnostic-factory-service/api";
			this->diagHost = "https://diagnostic-service.jidutest.com/api/diagnostic-service";
			break;
		}
		case App_Env_Staging: {
			this->certDir = appPath + "pkiCertificate/DMA/Staging/";
			this->eolHost = "https://eol-server-service-staging.jiduauto.com/eol-server";
			this->pkiHost = "https://dma-pki-thirdparty.jidudmastaging.com";
			this->cfgHost = "https://diagnostic-dma-factory-service.jidustaging.com/api/diagnostic-factory-service/api";
			this->diagHost = "https://diagnostic-service.jidustaging.com/api/diagnostic-service";

			if (staging_2_prod())
			{
				this->eolHost = "https://eol-server-service.jidudma.com/eol-server";
			}
			break;
		}
		case App_Env_Prod: {
			this->certDir = appPath + "pkiCertificate/DMA/Prod/";
			this->eolHost = "https://eol-server-service.jidudma.com/eol-server";
			this->pkiHost = "https://dma-pki-thirdparty.jidudma.com";
			this->cfgHost = "https://diagnostic.jidudma.com/api/diagnostic-factory-service/api";
			this->diagHost = "https://diagnostic-service.jiduprod.com/api/diagnostic-service";
			break;
		}
		default: {
			break;
		}
		}
	}
	else {//TODO 售后或者工程
		switch (currentEnvironment)
		{
		case App_Env_Dev: {
			this->certDir = appPath + "pkiCertificate/Dev/";
			this->diagHost = "https://diagnostic-service.jidudev.com/api/diagnostic-service";
			this->cfgHost = "https://diagnostic-service.jidudev.com/api/diagnostic-service/api";
			break;
		}
		case App_Env_Test: {
			this->certDir = appPath + "pkiCertificate/Test/";
			this->diagHost = "https://diagnostic-service.jidutest.com/api/diagnostic-service";
			this->cfgHost = "https://diagnostic-service.jidutest.com/api/diagnostic-service/api";
			break;
		}
		case App_Env_Staging: {
			this->certDir = appPath + "pkiCertificate/Staging/";
			this->diagHost = "https://diagnostic-service.jidustaging.com/api/diagnostic-service";
			this->cfgHost = "https://diagnostic-service.jidustaging.com/api/diagnostic-service/api";
			break;
		}
		case App_Env_Prod: {
			this->certDir = appPath + "pkiCertificate/Prod/";
			this->diagHost = "https://diagnostic-service.jiduprod.com/api/diagnostic-service";
			this->cfgHost = "https://diagnostic-service.jiduprod.com/api/diagnostic-service/api";
			break;
		}
		default: {
			this->certDir = appPath + "pkiCertificate/Prod/";
			this->diagHost = "https://diagnostic-service.jiduprod.com/api/diagnostic-service";
			break;
		}
		}
	}

	//TODO 配置文件加载host
	string webApiPath = appPath + "WebApi.json";
	FILE* fp = fopen(webApiPath.c_str(), "r");
	if (fp != NULL)
	{
		fseek(fp, 0, SEEK_END);
		int fLen = ftell(fp);
		fseek(fp, 0, SEEK_SET);
		char* fBuffer = (char*)malloc(fLen + 1);
		fread(fBuffer, 1, fLen, fp);
		fclose(fp);

		cJSON* objRoot = cJSON_Parse(fBuffer);
		free(fBuffer);
		if (objRoot != NULL && cJSON_HasObjectItem(objRoot, "DomainName")) {
			cJSON* objDomainName = cJSON_GetObjectItem(objRoot, "DomainName");

			cJSON* objFactory = NULL;
			if (DataCenter::getInstance()->factory._Equal("DMA")) {
				if (cJSON_HasObjectItem(objDomainName, "DMA")) {
					objFactory = cJSON_GetObjectItem(objDomainName, "DMA");
				}
			}
			else if (DataCenter::getInstance()->factory._Equal("PMA")) {
				if (cJSON_HasObjectItem(objDomainName, "PMA")) {
					objFactory = cJSON_GetObjectItem(objDomainName, "PMA");
				}
			}

			if (objFactory != NULL) {
				cJSON* objEnv = NULL;

				switch (currentEnvironment)
				{
				case App_Env_Dev: {
					if (cJSON_HasObjectItem(objFactory, "Dev")) {
						objEnv = cJSON_GetObjectItem(objFactory, "Dev");
					}
					break;
				}
				case App_Env_Test: {
					if (cJSON_HasObjectItem(objFactory, "Test")) {
						objEnv = cJSON_GetObjectItem(objFactory, "Test");
					}
					break;
				}
				case App_Env_Staging: {
					if (staging_2_prod()) {
						if (cJSON_HasObjectItem(objFactory, "Prod")) {
							objEnv = cJSON_GetObjectItem(objFactory, "Prod");

							cJSON* objStaging = cJSON_GetObjectItem(objFactory, "Staging");
							string tempString = cJSON_GetObjectItem(objStaging, "PKI")->valuestring;
							cJSON_ReplaceItemInObject(objEnv, "PKI", cJSON_CreateString(tempString.c_str()));
							tempString = cJSON_GetObjectItem(objStaging, "Config")->valuestring;
							cJSON_ReplaceItemInObject(objEnv, "Config", cJSON_CreateString(tempString.c_str()));
						}
					}
					else if (cJSON_HasObjectItem(objFactory, "Staging")) {
						objEnv = cJSON_GetObjectItem(objFactory, "Staging");
					}
					break;
				}
				case App_Env_Prod: {
					if (cJSON_HasObjectItem(objFactory, "Prod")) {
						objEnv = cJSON_GetObjectItem(objFactory, "Prod");
					}
					break;
				}
				}

				if (objEnv != NULL) {
					this->eolHost = cJSON_GetObjectItem(objEnv, "EOL")->valuestring;
					this->pkiHost = cJSON_GetObjectItem(objEnv, "PKI")->valuestring;
					this->cfgHost = cJSON_GetObjectItem(objEnv, "Config")->valuestring;
				}
			}
		}

		cJSON_Delete(objRoot);
	}

	Tracer::debug("eolHost", this->eolHost);
	Tracer::debug("pkiHost", this->pkiHost);
	Tracer::debug("diagHost", this->diagHost);
	Tracer::debug("certDir", this->certDir);
	return true;
}
/***************************************************************
* 函数: 从P12证书中解析私钥key和client证书
* 参数: p12Path p12文件路径
* 参数: pemCertBuffer 用于接收证书
* 参数: pemKeyBuffer p12用于接收私钥
* 参数: passwd 私钥密码
* 返回:
/***************************************************************/
void JiduClient::gen_pem(string p12Path, string passwd, string& pemCertBuffer, string& pemKeyBuffer)
{
	char tempCertBuff[1024] = { 0 };
	char tempKeyBuff[1024] = { 0 };
	parse_cert_p12((char*)p12Path.c_str(), (char*)passwd.substr(0, 16).c_str(), tempCertBuff, tempKeyBuff);

	pemCertBuffer = tempCertBuff;
	pemKeyBuffer = tempKeyBuff;
}
/***************************************************************
* 函数:
* 参数:
* 参数：
* 返回:
/***************************************************************/
void JiduClient::add_powerType(string& inParams) {

	int powerType = DataCenter::m_vehicleInfo.powerType;
	if (powerType == 0x02) powerType = 0x01;

	cJSON* obj = cJSON_Parse(inParams.c_str());
	if (NULL == obj) {
		if (inParams.find("powerType") == string::npos)
			inParams.append("&powerType=").append(MyStringUtils::toString(powerType, 10));
	}
	else if (cJSON_IsObject(obj))
	{
		if (!cJSON_HasObjectItem(obj, "powerType")) {
			cJSON_AddNumberToObject(obj, "powerType", powerType);
			char* temp = cJSON_PrintUnformatted(obj);
			inParams.assign(temp);
			cJSON_free(temp);
		}
	}
	cJSON_Delete(obj);
}
/***************************************************************
* 函数:
* 参数:
* 参数：
* 返回:
/***************************************************************/
void JiduClient::add_carType(string& inParams) {
	int carType = DataCenter::m_vehicleInfo.carTypeId;

	cJSON* obj = cJSON_Parse(inParams.c_str());
	if (NULL == obj) {

		if (inParams.find("carType") == string::npos)
			inParams.append("&carType=").append(MyStringUtils::toString(carType, 10));
		else {
			vector<string> vecParams;
			MyStringUtils::split(vecParams, inParams, "&");

			string tempString;
			for (string param : vecParams) {
				if (param.find("carType=") == string::npos) {
					tempString.append("&").append(param);
				}
				else {
					tempString.append("&carType=").append(MyStringUtils::toString(carType, 10));
				}
			}
			inParams = tempString.substr(1);
		}
	}
	else if (cJSON_IsObject(obj))
	{
		if (!cJSON_HasObjectItem(obj, "carType")) {
			cJSON_AddNumberToObject(obj, "carType", carType);
		}
		else {
			cJSON_ReplaceItemInObject(obj, "carType", cJSON_CreateNumber(carType));
		}

		char* temp = cJSON_PrintUnformatted(obj);
		inParams.assign(temp);
		cJSON_free(temp);
	}
	cJSON_Delete(obj);
}

int JiduClient::callServer_preHandler(int iType, string& inParams)
{
	switch (iType)
	{
	case 4: {
		DataCenter::m_VehicleOrderInfo.strTpmsId.clear();
		DataCenter::m_VehicleOrderInfo.strTpmsSupplierId = "00000000";
		break;
	}

	case 6:
	case 59: {
		DataCenter::getInstance()->m_EcuSafetyConstant.clear();
		break;
	}

	case 19:
	case 58: {
		DataCenter::m_EolKey.immoKeyEcm.clear();
		DataCenter::m_EolKey.immoKeyIem.clear();
		DataCenter::m_EolKey.immoKeyMgm.clear();
		DataCenter::m_EolKey.immoKeyRemote.clear();
		DataCenter::m_EolKey.dkBncmBgm.clear();
		DataCenter::m_EolKey.powerRootKey.clear();
		DataCenter::m_EolKey.powerRootKeyId.clear();
		break;
	}

	case 20:
	case 56: {
		DataCenter::m_EcuCertInfo.cls_strVid.clear();
		DataCenter::m_EcuCertInfo.cls_strEcuCa.clear();
		DataCenter::m_EcuCertInfo.ecuCertInfo.clear();
		break;
	}

	case 21:
	case 55: {
		DataCenter::m_aesKey.clear();
		break;
	}
	case 26: {
		JD_VEHICLE_ORDER_t vehicleOrderInfo = DataCenter::getInstance()->m_VehicleOrderInfo;
		vehicleOrderInfo.strSwpn.clear();
		vehicleOrderInfo.strCCPCode.clear();
		vehicleOrderInfo.strVehicleType.clear();
		vehicleOrderInfo.vecListEcu.clear();
		DataCenter::getInstance()->m_VehicleOrderInfo = vehicleOrderInfo;
		break;
	}
	case 27: {
		DataCenter::m_OtaCert.caCert.clear();
		DataCenter::m_OtaCert.clientCert.clear();
		break;
	}
	case 51: {
		JD_VEHICLE_ORDER_t vehicleOrderInfo = DataCenter::getInstance()->m_VehicleOrderInfo;
		vehicleOrderInfo.strSwpn.clear();
		break;
	}
	case 54: {
		JD_VEHICLE_ORDER_t vehicleOrderInfo = DataCenter::getInstance()->m_VehicleOrderInfo;
		vehicleOrderInfo.vecListEcu.clear();
		DataCenter::getInstance()->m_VehicleOrderInfo = vehicleOrderInfo;
		break;
	}
	case 79: {
		DataCenter::getInstance()->m_vecEbocInfo.clear();
		break;
	}
	case 88: {
		DataCenter::getInstance()->m_VehicleOrderInfo.vecListEcuNew.clear();
		break;
	}
	case 89: {
		break;
	}
	default:
		DataCenter::m_callServerRecord[iType].response.clear();
		break;
	}

	return -1;
}

/***************************************************************
* 函数:
* 参数:
* 参数：
* 返回:
/***************************************************************/
int JiduClient::callServer_affterHandler(int iType, string inParams, string& response)
{
	DataCenter::m_callServerRecord[iType].response = response;

	int retCode = -1;
	cJSON* objRoot = cJSON_Parse(response.c_str());
	if (cJSON_HasObjectItem(objRoot, "code")) {
		cJSON* objCode = cJSON_GetObjectItem(objRoot, "code");
		if (objCode->type == cJSON_Number && (objCode->valueint == 0 || objCode->valueint == 200)) {
			retCode = 0;
			cJSON* objData = cJSON_GetObjectItem(objRoot, "data");

			switch (iType)
			{
			case 1: {
				if (cJSON_HasObjectItem(objData, "ccpCode")) {
					DataCenter::m_VehicleOrderInfo.strCCPCode = cJSON_GetObjectItem(objData, "ccpCode")->valuestring;
				}
				else if (cJSON_HasObjectItem(objData, "vehicleType")) {
					DataCenter::m_VehicleOrderInfo.strVehicleType = cJSON_GetObjectItem(objData, "vehicleType")->valuestring;
				}
				break;
			}
			case 4: {
				if (0 == strcmp("Pass", cJSON_GetStringValue(cJSON_GetObjectItem(objData, "status")))) {
					if (cJSON_HasObjectItem(objData, "val"))
						DataCenter::m_VehicleOrderInfo.strTpmsId = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "val"));
				}
				if (cJSON_HasObjectItem(objData, "supplierId"))
				{
					cJSON* objSupplierId = cJSON_GetObjectItem(objData, "supplierId");
					if (cJSON_IsString(objSupplierId))
						DataCenter::m_VehicleOrderInfo.strTpmsSupplierId = cJSON_GetStringValue(objSupplierId);
					else
						DataCenter::m_VehicleOrderInfo.strTpmsSupplierId.clear();
				}
				break;
			}

			case 6:
			case 59: {
				map<string, string> swdlMap, immpMap, salMap, commonMap;

				cJSON* objSwdl = cJSON_GetObjectItem(objData, "swdl");
				cJSON* objImmo = cJSON_GetObjectItem(objData, "immo");
				cJSON* objSal = cJSON_GetObjectItem(objData, "sal");
				cJSON* objCommon = cJSON_GetObjectItem(objData, "common");

				for (int i = 0; i < cJSON_GetArraySize(objSwdl); i++) {
					swdlMap[cJSON_GetArrayItem(objSwdl, i)->string] = cJSON_GetArrayItem(objSwdl, i)->valuestring;
				}
				for (int i = 0; i < cJSON_GetArraySize(objImmo); i++) {
					immpMap[cJSON_GetArrayItem(objImmo, i)->string] = cJSON_GetArrayItem(objImmo, i)->valuestring;
				}
				for (int i = 0; i < cJSON_GetArraySize(objSal); i++) {
					salMap[cJSON_GetArrayItem(objSal, i)->string] = cJSON_GetArrayItem(objSal, i)->valuestring;
				}
				for (int i = 0; i < cJSON_GetArraySize(objCommon); i++) {
					commonMap[cJSON_GetArrayItem(objCommon, i)->string] = cJSON_GetArrayItem(objCommon, i)->valuestring;
				}

				for (int i = 0; i < cJSON_GetArraySize(objSwdl); i++) {
					string ecuName = cJSON_GetArrayItem(objSwdl, i)->string;
					JD_ECU_SAFETY_CONSTANT_t safetyConstant;
					safetyConstant.keySwdl = swdlMap.at(ecuName);
					safetyConstant.keyImmo = immpMap.at(ecuName);
					safetyConstant.keySal = salMap.at(ecuName);
					safetyConstant.keyCommon = commonMap.at(ecuName);
					DataCenter::getInstance()->setEcuSafetyConstant(ecuName, safetyConstant);
				}
				break;
			}

			case 11:
			case 19:
			case 57:
			case 58: {
				if (cJSON_HasObjectItem(objData, "immoKeyEcm"))
					DataCenter::m_EolKey.immoKeyEcm = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "immoKeyEcm"));
				if (cJSON_HasObjectItem(objData, "immoKeyIem"))
					DataCenter::m_EolKey.immoKeyIem = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "immoKeyIem"));
				if (cJSON_HasObjectItem(objData, "immoKeyMgm"))
					DataCenter::m_EolKey.immoKeyMgm = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "immoKeyMgm"));
				if (cJSON_HasObjectItem(objData, "immoKeyRemote"))
					DataCenter::m_EolKey.immoKeyRemote = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "immoKeyRemote"));
				if (cJSON_HasObjectItem(objData, "dkBncmBgm"))
					DataCenter::m_EolKey.dkBncmBgm = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "dkBncmBgm"));
				if (cJSON_HasObjectItem(objData, "powerRootKey"))
					DataCenter::m_EolKey.powerRootKey = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "powerRootKey"));
				if (cJSON_HasObjectItem(objData, "powerRootKeyId"))
					DataCenter::m_EolKey.powerRootKeyId = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "powerRootKeyId"));
				break;
			}

			case 20:
			case 23:
			case 56:
			case 65: {
				map<string, string> dvcMap;
				cJSON* dvcKeyArray = cJSON_GetObjectItem(objData, "dvcKey");
				for (int i = 0; i < cJSON_GetArraySize(dvcKeyArray); i++) {
					cJSON* item = cJSON_GetArrayItem(dvcKeyArray, i);
					dvcMap[item->string] = item->valuestring == NULL ? ("") : (item->valuestring);
				}

				map<string, JD_EcuCertItem_t> ecuCertInfo;
				cJSON* certListArray = cJSON_GetObjectItem(objData, "certList");
				for (int i = 0; i < cJSON_GetArraySize(certListArray); i++) {
					cJSON* item = cJSON_GetArrayItem(certListArray, i);

					JD_EcuCertItem_t certListItem;
					if (cJSON_HasObjectItem(item, "p12"))
						certListItem.cls_strP12 = cJSON_GetStringValue(cJSON_GetObjectItem(item, "p12"));
					if (cJSON_HasObjectItem(item, "aesKey"))
						certListItem.cls_strAESKey = cJSON_GetStringValue(cJSON_GetObjectItem(item, "aesKey"));
					if (cJSON_HasObjectItem(item, "p12Key"))
						certListItem.cls_strP12Key = cJSON_GetStringValue(cJSON_GetObjectItem(item, "p12Key"));
					if (cJSON_HasObjectItem(item, "soaKey"))
						certListItem.cls_strSOAKey = cJSON_GetStringValue(cJSON_GetObjectItem(item, "soaKey"));

					if (cJSON_HasObjectItem(item, "ecuType"))
					{
						string ecuType = cJSON_GetStringValue(cJSON_GetObjectItem(item, "ecuType"));
						certListItem.ecuType = ecuType;
						certListItem.cls_strDvcKey = dvcMap[ecuType];
						ecuCertInfo[ecuType] = certListItem;
					}
				}

				if (cJSON_HasObjectItem(objData, "vid"))
					DataCenter::m_EcuCertInfo.cls_strVid = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "vid"));
				if (cJSON_HasObjectItem(objData, "ecuCa"))
					DataCenter::m_EcuCertInfo.cls_strEcuCa = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "ecuCa"));
				DataCenter::m_EcuCertInfo.ecuCertInfo = ecuCertInfo;
				break;
			}

			case 21:
			case 55: {
				for (int i = 0; i < cJSON_GetArraySize(objData); i++) {
					cJSON* tempObj = cJSON_GetArrayItem(objData, i);
					if (cJSON_IsString(tempObj))
					{
						DataCenter::m_aesKey[tempObj->string] = tempObj->valuestring;
					}
					else {
						Tracer::error("invalid obj", tempObj->string);
					}
				}

				break;
			}
			case 26: {

				clearDataCenterCache();

				JD_VEHICLE_ORDER_t vehicleOrderInfo;

				if (cJSON_HasObjectItem(objData, "vin") && cJSON_IsString(cJSON_GetObjectItem(objData, "vin")))
					vehicleOrderInfo.strVin = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "vin"));
				if (cJSON_HasObjectItem(objData, "powerType"))
					DataCenter::m_vehicleInfo.powerType = cJSON_GetObjectItem(objData, "powerType")->valueint;
				if (cJSON_HasObjectItem(objData, "mixNo") && cJSON_IsString(cJSON_GetObjectItem(objData, "mixNo")))
					vehicleOrderInfo.strMixNo = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "mixNo"));
				if (cJSON_HasObjectItem(objData, "ccpCode") && cJSON_IsString(cJSON_GetObjectItem(objData, "ccpCode")))
					vehicleOrderInfo.strCCPCode = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "ccpCode"));
				if (cJSON_HasObjectItem(objData, "vehicleType") && cJSON_IsString(cJSON_GetObjectItem(objData, "vehicleType")))
					vehicleOrderInfo.strVehicleType = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "vehicleType"));
				if (cJSON_HasObjectItem(objData, "eboc") && cJSON_IsString(cJSON_GetObjectItem(objData, "eboc")))
					vehicleOrderInfo.strEBOC = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "eboc"));
				if (cJSON_HasObjectItem(objData, "baseLine") && cJSON_IsString(cJSON_GetObjectItem(objData, "baseLine")))
					vehicleOrderInfo.strBaseLine = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "baseLine"));
				if (cJSON_HasObjectItem(objData, "displayVersion") && cJSON_IsString(cJSON_GetObjectItem(objData, "displayVersion")))
					vehicleOrderInfo.strDisplayVersion = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "displayVersion"));
				if (cJSON_HasObjectItem(objData, "swpn") && cJSON_IsString(cJSON_GetObjectItem(objData, "swpn")))
					vehicleOrderInfo.strSwpn = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "swpn"));
				if (cJSON_HasObjectItem(objData, "vehicleEnvironment") && cJSON_IsString(cJSON_GetObjectItem(objData, "vehicleEnvironment")))
				{
					string tempString = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "vehicleEnvironment"));
					vehicleOrderInfo.iVehicleEnvironment = MyStringUtils::toLong(tempString);
				}
				if (cJSON_HasObjectItem(objData, "vehicleEnvironment") && cJSON_IsNumber(cJSON_GetObjectItem(objData, "vehicleEnvironment")))
					vehicleOrderInfo.iVehicleEnvironment = cJSON_GetNumberValue(cJSON_GetObjectItem(objData, "vehicleEnvironment"));


				cJSON* ecuListArray = cJSON_GetObjectItem(objData, "ecuList");
				int ecuCount = cJSON_GetArraySize(ecuListArray);
				if (ecuCount == 0) {
					Tracer::error(__FUNCTION__, "no obj: ecuList");
					retCode = -1;
				}
				for (int i = 0; i < ecuCount; i++) {
					JD_ECU_INFO_t ecuInfo;
					cJSON* ecuItem = cJSON_GetArrayItem(ecuListArray, i);

					ecuInfo.nEcuId = std::stoi(cJSON_GetStringValue(cJSON_GetObjectItem(ecuItem, "ecuId")), nullptr, 16);
					ecuInfo.strEcuName = cJSON_GetStringValue(cJSON_GetObjectItem(ecuItem, "ecuName"));
					ecuInfo.strEcuHwpn = cJSON_GetStringValue(cJSON_GetObjectItem(ecuItem, "ecuHwpn"));
					ecuInfo.strEcuDn = cJSON_GetStringValue(cJSON_GetObjectItem(ecuItem, "ecuDn"));
					if (ecuInfo.strEcuName._Equal("ETCM")) {
						continue;
					}

					cJSON* ecuSwpnArray = cJSON_GetObjectItem(ecuItem, "ecuSwpnList");
					for (int j = 0; j < cJSON_GetArraySize(ecuSwpnArray); j++) {
						cJSON* swpnItem = cJSON_GetArrayItem(ecuSwpnArray, j);
						JD_ECU_SWPN_INFO_t spanInfo;
						spanInfo.strPackageType = cJSON_GetStringValue(cJSON_GetObjectItem(swpnItem, "packageType"));
						spanInfo.strEcuSwpn = cJSON_GetStringValue(cJSON_GetObjectItem(swpnItem, "ecuSwpn"));
						ecuInfo.vecEcuSwpnList.push_back(spanInfo);
					}
					vehicleOrderInfo.vecListEcu.push_back(ecuInfo);
				}

				DataCenter::getInstance()->m_VehicleOrderInfo = vehicleOrderInfo;
				break;
			}
			case 64:
			case 27: {
				DataCenter::m_OtaCert.caCert = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "serviceCa"));
				DataCenter::m_OtaCert.clientCert = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "otaCert"));
				break;
			}
			case 28: {
				DataCenter::m_summaryData.testData.clear();
				if (cJSON_HasObjectItem(objData, "mixNo") && cJSON_IsString(cJSON_GetObjectItem(objData, "mixNo")))
					DataCenter::m_summaryData.mixNo = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "mixNo"));
				if (cJSON_HasObjectItem(objData, "vehicleType") && cJSON_IsString(cJSON_GetObjectItem(objData, "vehicleType")))
					DataCenter::m_summaryData.vehicleType = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "vehicleType"));
				if (cJSON_HasObjectItem(objData, "vin") && cJSON_IsString(cJSON_GetObjectItem(objData, "vin")))
					DataCenter::m_summaryData.vin = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "vin"));
				if (cJSON_HasObjectItem(objData, "station") && cJSON_IsString(cJSON_GetObjectItem(objData, "station")))
					DataCenter::m_summaryData.station = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "station"));
				if (cJSON_HasObjectItem(objData, "cell") && cJSON_IsString(cJSON_GetObjectItem(objData, "cell")))
					DataCenter::m_summaryData.cell = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "cell"));
				if (cJSON_HasObjectItem(objData, "testTimeUtc") && cJSON_IsString(cJSON_GetObjectItem(objData, "testTimeUtc")))
					DataCenter::m_summaryData.testTimeUtc = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "testTimeUtc"));
				if (cJSON_HasObjectItem(objData, "executionTimeUtc") && cJSON_IsString(cJSON_GetObjectItem(objData, "executionTimeUtc")))
					DataCenter::m_summaryData.executionTimeUtc = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "executionTimeUtc"));
				if (cJSON_HasObjectItem(objData, "overallResult") && cJSON_IsString(cJSON_GetObjectItem(objData, "overallResult")))
					DataCenter::m_summaryData.overallResult = cJSON_GetStringValue(cJSON_GetObjectItem(objData, "overallResult"));

				cJSON* testDataArray = cJSON_GetObjectItem(objData, "testData");
				for (int i = 0; i < cJSON_GetArraySize(testDataArray); i++) {
					cJSON* testDataItem = cJSON_GetArrayItem(testDataArray, i);

					JD_SummaryData_TestData_t  testData;
					testData.testBlockName = cJSON_GetStringValue(cJSON_GetObjectItem(testDataItem, "testBlockName"));
					testData.testBlockId = cJSON_GetStringValue(cJSON_GetObjectItem(testDataItem, "testBlockId"));
					testData.testBlockResult = cJSON_GetStringValue(cJSON_GetObjectItem(testDataItem, "testBlockResult"));

					cJSON* testItemListArray = cJSON_GetObjectItem(testDataItem, "testItemList");
					for (int j = 0; j < cJSON_GetArraySize(testItemListArray); j++) {
						cJSON* testItemListItem = cJSON_GetArrayItem(testItemListArray, j);

						JD_SummaryData_TestItemList_t testItemList;
						testItemList.testItemName = cJSON_GetStringValue(cJSON_GetObjectItem(testItemListItem, "testItemName"));
						testItemList.testItemId = cJSON_GetStringValue(cJSON_GetObjectItem(testItemListItem, "testItemId"));
						testItemList.testItemResult = cJSON_GetStringValue(cJSON_GetObjectItem(testItemListItem, "testItemResult"));

						cJSON* testItemArray = cJSON_GetObjectItem(testItemListItem, "testItem");
						for (int k = 0; k < cJSON_GetArraySize(testItemArray); k++) {
							cJSON* testItem = cJSON_GetArrayItem(testItemArray, k);
							JD_SummaryData_TestItem_t item;
							item.ecuName = cJSON_GetStringValue(cJSON_GetObjectItem(testItem, "ecuName"));
							item.ecuAddress = cJSON_GetStringValue(cJSON_GetObjectItem(testItem, "ecuAddress"));
							item.serverId = cJSON_GetStringValue(cJSON_GetObjectItem(testItem, "serverId"));
							item.did = cJSON_GetStringValue(cJSON_GetObjectItem(testItem, "did"));
							item.resultData = cJSON_GetStringValue(cJSON_GetObjectItem(testItem, "resultData"));
							item.value = cJSON_GetStringValue(cJSON_GetObjectItem(testItem, "value"));
							item.expectData = cJSON_GetStringValue(cJSON_GetObjectItem(testItem, "expectData"));
							item.number = cJSON_GetStringValue(cJSON_GetObjectItem(testItem, "number"));
							testItemList.testItem.push_back(item);
						}

						testData.testItemList.push_back(testItemList);
					}

					DataCenter::m_summaryData.testData.push_back(testData);
				}
				break;
			}
			case 51: {
				JD_VEHICLE_ORDER_t vehicleOrderInfo = DataCenter::getInstance()->m_VehicleOrderInfo;

				vehicleOrderInfo.strSwpn = cJSON_GetObjectItem(objData, "vehicleSoftwareVer")->valuestring;
				DataCenter::getInstance()->m_VehicleOrderInfo = vehicleOrderInfo;
				break;
			}
			case 53: {
				if (cJSON_IsString(objData))
				{
					string strCCPCode = objData->valuestring;
					DataCenter::getInstance()->m_VehicleOrderInfo.strCCPCode = strCCPCode;
				}

				break;
			}
			case 54: {
				JD_VEHICLE_ORDER_t vehicleOrderInfo = DataCenter::getInstance()->m_VehicleOrderInfo;
				vehicleOrderInfo.vecListEcu.clear();
				cJSON* ecuListArray = cJSON_GetObjectItem(objData, "ecuList");
				for (int i = 0; i < cJSON_GetArraySize(ecuListArray); i++) {
					JD_ECU_INFO_t ecuInfo;
					cJSON* ecuItem = cJSON_GetArrayItem(ecuListArray, i);
					ecuInfo.nEcuId = std::stoi(cJSON_GetStringValue(cJSON_GetObjectItem(ecuItem, "ecuId")), nullptr, 16);
					ecuInfo.strEcuName = cJSON_GetStringValue(cJSON_GetObjectItem(ecuItem, "ecuName"));
					if (ecuInfo.strEcuName._Equal("ETCM")) {
						continue;
					}

					if (ecuInfo.nEcuId == 0x5051)
					{
						ecuInfo.strEcuName = "BECM1_75";
					}
					else if (ecuInfo.nEcuId == 0x5052)
					{
						ecuInfo.strEcuName = "BECM1_102";
					}
					else if (ecuInfo.nEcuId == 0x5054)
					{
						ecuInfo.strEcuName = "BECM1_76.5";
					}
					else if (ecuInfo.nEcuId == 0x5055)
					{
						ecuInfo.strEcuName = "BECM1_98";
					}
					else if (ecuInfo.nEcuId == 0x5071)
					{
						ecuInfo.strEcuName = "IEM_IGBT";
					}
					else if (ecuInfo.nEcuId == 0x5072)
					{
						ecuInfo.strEcuName = "IEM_SIC";
					}
					else if (ecuInfo.nEcuId == 0x5073)
					{
						ecuInfo.strEcuName = "IEM2";
					}

					ecuInfo.strEcuHwpn = cJSON_GetStringValue(cJSON_GetObjectItem(ecuItem, "hwPn"));
					ecuInfo.strEcuDn = cJSON_GetStringValue(cJSON_GetObjectItem(ecuItem, "sn"));

					string tempString = cJSON_GetStringValue(cJSON_GetObjectItem(ecuItem, "swPn"));
					vector<string> vecSpan;
					MyStringUtils::split(vecSpan, tempString, ",");
					for (string span : vecSpan) {
						JD_ECU_SWPN_INFO_t spanInfo;
						spanInfo.strEcuSwpn = MyStringUtils::trim(span);
						ecuInfo.vecEcuSwpnList.push_back(spanInfo);
					}
					vehicleOrderInfo.vecListEcu.push_back(ecuInfo);
				}

				DataCenter::getInstance()->m_VehicleOrderInfo = vehicleOrderInfo;
				break;
			}
			case 68: {
				if (cJSON_HasObjectItem(objData, "ccpValue")) {
					cJSON* objCCP = cJSON_GetObjectItem(objData, "ccpValue");
					if (cJSON_IsString(objCCP))
					{
						string strCCPCode = objCCP->valuestring;
						DataCenter::getInstance()->m_VehicleOrderInfo.strCCPCode = strCCPCode;
					}
				}
				break;
			}
			case 79: {
				if (cJSON_IsArray(objData)) {
					DataCenter::getInstance()->m_vecEbocInfo.clear();

					for (int i = 0; i < cJSON_GetArraySize(objData); i++) {
						cJSON* objEboc = cJSON_GetArrayItem(objData, i);
						EbocInfo eboc;

						if (cJSON_HasObjectItem(objEboc, "creator"))
							eboc.creator = cJSON_GetObjectItem(objEboc, "creator")->valuestring;
						if (cJSON_HasObjectItem(objEboc, "featureCode"))
							eboc.featureCode = cJSON_GetObjectItem(objEboc, "featureCode")->valuestring;
						if (cJSON_HasObjectItem(objEboc, "featureName"))
							eboc.featureName = cJSON_GetObjectItem(objEboc, "featureName")->valuestring;
						if (cJSON_HasObjectItem(objEboc, "featureFamilyName"))
							eboc.featureFamilyName = cJSON_GetObjectItem(objEboc, "featureFamilyName")->valuestring;
						if (cJSON_HasObjectItem(objEboc, "createTime"))
							eboc.createTime = cJSON_GetObjectItem(objEboc, "createTime")->valuedouble / 1000;
						if (cJSON_HasObjectItem(objEboc, "featureFamilyCname"))
							eboc.featureFamilyCname = cJSON_IsNull(cJSON_GetObjectItem(objEboc, "featureFamilyCname")) ? "null" : cJSON_GetObjectItem(objEboc, "featureFamilyCname")->valuestring;
						if (cJSON_HasObjectItem(objEboc, "vin"))
							eboc.vin = cJSON_GetObjectItem(objEboc, "vin")->valuestring;
						if (cJSON_HasObjectItem(objEboc, "id"))
							eboc.id = cJSON_GetObjectItem(objEboc, "id")->valueint;
						if (cJSON_HasObjectItem(objEboc, "featureFamilyCode"))
							eboc.featureFamilyCode = cJSON_GetObjectItem(objEboc, "featureFamilyCode")->valuestring;
						if (cJSON_HasObjectItem(objEboc, "featureCname"))
							eboc.featureCname = cJSON_GetObjectItem(objEboc, "featureCname")->valuestring;
						DataCenter::getInstance()->m_vecEbocInfo.push_back(eboc);
					}
				}
				break;
			}

			case 88: {
				if (cJSON_HasObjectItem(objData, "ecusInfo")) {
					cJSON* ecuListArray = cJSON_GetObjectItem(objData, "ecusInfo");
					int ecuCount = cJSON_GetArraySize(ecuListArray);
					if (ecuCount == 0) {
						Tracer::error(__FUNCTION__, "no obj: ecuList");
						retCode = -1;
					}

					for (int i = 0; i < ecuCount; i++) {
						JD_ECU_INFO_t ecuInfo;
						cJSON* ecuItem = cJSON_GetArrayItem(ecuListArray, i);

						if (cJSON_HasObjectItem(ecuItem, "ecuId"))
							ecuInfo.nEcuId = std::stoi(cJSON_GetStringValue(cJSON_GetObjectItem(ecuItem, "ecuId")), nullptr, 16);
						if (cJSON_HasObjectItem(ecuItem, "ecuName"))
							ecuInfo.strEcuName = cJSON_GetStringValue(cJSON_GetObjectItem(ecuItem, "ecuName"));

						if (ecuInfo.nEcuId == 0x5051)
						{
							ecuInfo.strEcuName = "BECM1_75";
						}
						else if (ecuInfo.nEcuId == 0x5052)
						{
							ecuInfo.strEcuName = "BECM1_102";
						}
						else if (ecuInfo.nEcuId == 0x5054)
						{
							ecuInfo.strEcuName = "BECM2_76.5";
						}
						else if (ecuInfo.nEcuId == 0x5055)
						{
							ecuInfo.strEcuName = "BECM2_98";
						}
						else if (ecuInfo.nEcuId == 0x5071)
						{
							ecuInfo.strEcuName = "IEM_IGBT";
						}
						else if (ecuInfo.nEcuId == 0x5072)
						{
							ecuInfo.strEcuName = "IEM_SIC";
						}
						else if (ecuInfo.nEcuId == 0x5073)
						{
							ecuInfo.strEcuName = "IEM2";
						}

						if (cJSON_HasObjectItem(ecuItem, "ecuHWpn"))
							ecuInfo.strEcuHwpn = cJSON_GetStringValue(cJSON_GetObjectItem(ecuItem, "ecuHWpn"));

						if (cJSON_HasObjectItem(ecuItem, "orderList"))
						{
							cJSON* ecuSwpnArray = cJSON_GetObjectItem(ecuItem, "orderList");
							for (int j = 0; j < cJSON_GetArraySize(ecuSwpnArray); j++) {
								cJSON* ecuSwpn = cJSON_GetArrayItem(ecuSwpnArray, j);
								for (int k = 0; k < cJSON_GetArraySize(ecuSwpn); k++) {
									cJSON* swpnItem = cJSON_GetArrayItem(ecuSwpn, k);
									JD_ECU_SWPN_INFO_t spanInfo;
									if (cJSON_HasObjectItem(swpnItem, "fileType"))
										spanInfo.strPackageType = cJSON_GetStringValue(cJSON_GetObjectItem(swpnItem, "fileType"));
									if (cJSON_HasObjectItem(swpnItem, "dstVer"))
										spanInfo.strEcuSwpn = cJSON_GetStringValue(cJSON_GetObjectItem(swpnItem, "dstVer"));
									ecuInfo.vecEcuSwpnList.push_back(spanInfo);
								}
							}
						}

						DataCenter::m_VehicleOrderInfo.vecListEcuNew.push_back(ecuInfo);
					}
				}

				break;
			}
			default:
				break;
			}
		}
	}

	cJSON_Delete(objRoot);
	return retCode;
}

bool JiduClient::getAccessToken(string& token) {
	string filepath = CVehicleConfig::getInstance()->getDiagnosisDir();
	filepath.append("profile\\profile.json");
	FILE* fp = fopen(filepath.c_str(), "r");
	if (fp == NULL) {
		return false;
	}
	fseek(fp, 0, SEEK_END);
	int fileSize = ftell(fp);
	fseek(fp, 0, SEEK_SET);

	bool retFlag = false;
	char* pBuffer = (char*)malloc(fileSize);
	if (pBuffer)
	{
		fread(pBuffer, 1, fileSize, fp);
		cJSON* obj = cJSON_Parse(pBuffer);
		if (cJSON_IsObject(obj)) {
			if (cJSON_HasObjectItem(obj, "userProfile")) {
				cJSON* objUserProfile = cJSON_GetObjectItem(obj, "userProfile");
				if (cJSON_HasObjectItem(objUserProfile, "WuLingUser")) {
					cJSON* objUser = cJSON_GetObjectItem(objUserProfile, "WuLingUser");
					if (cJSON_HasObjectItem(objUser, "UserToken")) {

						cJSON* objToken = cJSON_GetObjectItem(objUser, "UserToken");
						if (cJSON_IsString(objToken)) {
							token = cJSON_GetObjectItem(objUser, "UserToken")->valuestring;
							retFlag = true;
						}
					}
				}
			}
		}
		cJSON_Delete(obj);
	}
	fclose(fp);
	free(pBuffer);

	return retFlag;
}

void JiduClient::desensitize(cJSON* obj)
{
	if (cJSON_IsObject(obj) || cJSON_IsArray(obj))
	{
		for (int i = 0; i < cJSON_GetArraySize(obj); i++) {
			cJSON* objDataItem = cJSON_GetArrayItem(obj, i);

			if (cJSON_IsString(objDataItem)) {
				string srcString = objDataItem->valuestring;
				MyStringUtils::desensitize(srcString);
				cJSON_ReplaceItemInObject(obj, objDataItem->string, cJSON_CreateString(srcString.c_str()));
			}
			else if (cJSON_IsObject(objDataItem) || cJSON_IsArray(objDataItem)) {
				for (int j = 0; j < cJSON_GetArraySize(objDataItem); j++) {
					cJSON* objChildtem = cJSON_GetArrayItem(objDataItem, j);
					if (cJSON_IsString(objChildtem)) {
						string srcString = objChildtem->valuestring;
						MyStringUtils::desensitize(srcString);
						cJSON_ReplaceItemInObject(objDataItem, objChildtem->string, cJSON_CreateString(srcString.c_str()));
					}
					else {
						desensitize(objChildtem);
					}
				}
			}
		}
	}
}
