﻿#include "jidu_vehicleConfig.h"
#include "jidu_envConfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tracer.h"
#include "FileUtils.h"
#include "FlashFileUtils.h"
#include "MyStringUtils.h"
#include "jidu_client.h"
#include "vbf/VBFParserSmall.h"
#include "jidu_dataCenter.h"
#include "jidu.h"


CVehicleConfig* CVehicleConfig::instance = nullptr;
std::string CVehicleConfig::m_strVehicleSoftVer;
std::string CVehicleConfig::m_strVehicleType = "MarsOne";
vector<std::string> CVehicleConfig::m_vecVehicleSoftVer;
JD_VEHICLE_CONFIG_t CVehicleConfig::m_vehicleConfig;



CVehicleConfig* CVehicleConfig::getInstance()
{
	if (instance == nullptr) {
		instance = new CVehicleConfig();
	}
	return instance;
}

CVehicleConfig::CVehicleConfig()
{
#if _DEBUG
	DiagnosisDir = "D:\\JIDUDIAG_S_OTX\\Diagnosis\\";
#else
	string appPath = EnvConfig::getInstance()->getAppPath();
	DiagnosisDir = appPath + "Diagnosis\\";
#endif

	DiagnosisEcuFilesDir = DiagnosisDir + "ECU_DATA\\JIDUECUFILES\\";
	DiagnosisBridgeEcuFilesDir = DiagnosisDir + "ECU_DATA\\JIDUECUBRIDGEFILES\\";

	//reloadLoacalPkg();
	//reloadConfig();
}

//TODO 车型列表目录
string CVehicleConfig::getVehicleTypeFileDir()
{
	string dirPath = DiagnosisEcuFilesDir;
	string factory = DataCenter::getInstance()->factory;
	if (factory._Equal("DMA") || factory._Equal("PMA")) {
		dirPath.append(factory).append("\\").append(EnvConfig::getInstance()->getEnvPath());
	}
	else {
		dirPath.append(EnvConfig::getInstance()->getEnvPath());
	}

	Tracer::debug("vechileTypeDir", dirPath);
	return dirPath;
}

//TODO 整车包列表目录
string CVehicleConfig::getPkgFileDir()
{
	string dirPath = DiagnosisEcuFilesDir;
	string factory = DataCenter::getInstance()->factory;
	if (factory._Equal("DMA") || factory._Equal("PMA")) {
		dirPath.append(factory).append("\\").append(EnvConfig::getInstance()->getEnvPath()).append("\\").append(m_strVehicleType);
	}
	else {
		dirPath.append(EnvConfig::getInstance()->getEnvPath()).append("\\").append(m_strVehicleType);
	}

	Tracer::debug("vechileTypeDir", dirPath);
	return dirPath;
}

//TODO 刷写文件目录
string CVehicleConfig::getFlashFileDir()
{
	string dirPath = DiagnosisEcuFilesDir;
	string factory = DataCenter::getInstance()->factory;
	if (factory._Equal("DMA") || factory._Equal("PMA")) {
		dirPath.append(factory).append("\\").append(EnvConfig::getInstance()->getEnvPath()).append("\\").append(m_strVehicleType).append("\\").append(m_strVehicleSoftVer);
	}
	else {
		dirPath.append(EnvConfig::getInstance()->getEnvPath()).append("\\").append(m_strVehicleType).append("\\").append(m_strVehicleSoftVer);
	}
	return dirPath;
}

string CVehicleConfig::getBridgeFileDir(int bridgeId)
{
	string dirPath = DiagnosisBridgeEcuFilesDir;
	string factory = DataCenter::getInstance()->factory;
	if (factory._Equal("DMA") || factory._Equal("PMA")) {
		dirPath.append(factory).append("\\").append(EnvConfig::getInstance()->getEnvPath()).append("\\").append("EcuBridge").append("\\").append(to_string(bridgeId));
	}
	else {
		dirPath.append(EnvConfig::getInstance()->getEnvPath()).append("\\").append("EcuBridge").append("\\").append(to_string(bridgeId));
	}
	return dirPath;
}


//TODO 刷写证书目录
string CVehicleConfig::getCertFilepath()
{
	string certPath = DiagnosisDir + "certificate\\DiagnosticData.bin";
	FILE* fp = fopen(certPath.c_str(), "r");
	if (fp == NULL) {
		certPath = DiagnosisDir + "certificate\\";
		certPath.append(EnvConfig::getInstance()->getEnvPath())
			.append("\\").append(m_strVehicleType)
			.append("\\DiagnosticData.bin");
	}
	else {
		fclose(fp);
	}
	return certPath;
}

uint16_t CVehicleConfig::getEcuId(uint16_t ecuId, string ecuHwpn) {
	for (int i = 0; i < m_vehicleConfig.vecListEcu.size(); i++) {
		JD_ECU_CONFIG_t ecuCfg = m_vehicleConfig.vecListEcu.at(i);
		if ((ecuCfg.nEcuId & 0xFFF0) == (ecuId & 0xFFF0)) {
			for (JD_MAPPING_CONFIG_t ecuMapping : ecuCfg.vecMapping) {
				if (ecuMapping.strHwpn._Equal(ecuHwpn)) {
					char tempBuffer[32] = { 0 };
					Tracer::debug(__FUNCTION__, string("ecuId: ") + _itoa(ecuId, tempBuffer, 16) + "; ecuHwpn: " + ecuHwpn + "; ret: " + _itoa(ecuCfg.nEcuId, tempBuffer, 16));

					return ecuCfg.nEcuId;
				}
			}
		}
	}

	return ecuId;
}


uint64_t CVehicleConfig::GetFlashFileSize(int ecuId, string ecuName, string ecuHwpn, string ecuSwpn) {

	if (m_vehicleConfig.strBaseLine.empty()) {
		reloadConfig();
	}

	ecuSwpn.erase(std::remove(ecuSwpn.begin(), ecuSwpn.end(), ' '), ecuSwpn.end());

	string boomEcuName = ecuName;
	for (JD_ECU_CONFIG_t ecuConfig : m_vehicleConfig.vecListEcu) {
		//if (ecuConfig.nEcuId == ecuId) {
		if ((ecuConfig.nEcuId & 0xFFF0) == (ecuId & 0xFFF0)) {
			boomEcuName = ecuConfig.strBoomEcuName;
			break;
		}
	}

	string strFilePath = getFlashFileDir();
	strFilePath.append("\\").append(boomEcuName)
		.append("\\").append(ecuHwpn)
		.append("\\").append(ecuSwpn).append(".json");

	CFlashFileUtils FileUtil;
	std::string strConfig;
	bool bRet = FileUtil.LoadConfig(strConfig, strFilePath);
	if (bRet)
	{
		cJSON* objRoot = cJSON_Parse(strConfig.c_str());
		if (cJSON_IsObject(objRoot)) {
			cJSON* objInfo = cJSON_GetObjectItem(objRoot, "diagnoseEncryptionInfo");
			uint64_t fSize = (uint64_t)cJSON_GetObjectItem(objInfo, "size")->valuedouble;
			Tracer::debug("flashFileSize:" + ecuName, to_string(fSize));
			cJSON_Delete(objRoot);
			return fSize;
		}
		else {
			cJSON_Delete(objRoot);
		}
	}
	else {
		Tracer::error("GetFlashFileSize", strFilePath);
	}

	return 0;
}

bool CVehicleConfig::GetFlashFileInfo(int ecuId, string ecuName, string ecuHwpn, string ecuSwpn, JD_VSP_FLASH_CONFIG_t& oneFlashInfo)
{
	if (m_vehicleConfig.strBaseLine.empty()) {
		reloadConfig();
	}

	ecuSwpn.erase(std::remove(ecuSwpn.begin(), ecuSwpn.end(), ' '), ecuSwpn.end());

	string boomEcuName = ecuName;
	for (JD_ECU_CONFIG_t ecuConfig : m_vehicleConfig.vecListEcu) {
		//if (ecuConfig.nEcuId == ecuId) {
		if ((ecuConfig.nEcuId & 0xFFF0) == (ecuId & 0xFFF0)) {
			boomEcuName = ecuConfig.strBoomEcuName;
			break;
		}
	}

	string strFilePath = getFlashFileDir();
	strFilePath.append("\\").append(boomEcuName)
		.append("\\").append(ecuHwpn)
		.append("\\").append(ecuSwpn).append(".json");

	CFlashFileUtils FileUtil;
	std::string strConfig;
	bool bRet = FileUtil.LoadConfig(strConfig, strFilePath);
	if (bRet)
	{
		Tracer::debug(strFilePath, strConfig);
		cJSON* objRoot = cJSON_Parse(strConfig.c_str());
		if (cJSON_IsObject(objRoot)) {
			oneFlashInfo.strFileType = cJSON_GetObjectItem(objRoot, "fileType")->valuestring;
			oneFlashInfo.strFileName = cJSON_GetObjectItem(objRoot, "fileName")->valuestring;
			auto element = cJSON_GetObjectItem(objRoot, "version");
			if (element != NULL) {
				oneFlashInfo.strVersion = element->valuestring;
			}
			else {
				element = cJSON_GetObjectItem(objRoot, "softName");
				if (element != NULL) {
					oneFlashInfo.strVersion = element->valuestring;
				}
			}

			cJSON* encInfo = cJSON_GetObjectItem(objRoot, "diagnoseEncryptionInfo");
			oneFlashInfo.nFlashFileSize = (uint64_t)cJSON_GetObjectItem(encInfo, "size")->valuedouble;
			oneFlashInfo.strLocalPath = cJSON_GetObjectItem(encInfo, "localPath")->valuestring;
			oneFlashInfo.strkeyId = cJSON_GetObjectItem(encInfo, "keyId")->valuestring;
			oneFlashInfo.strKeyInfo = cJSON_GetObjectItem(encInfo, "keyInfo")->valuestring;
			oneFlashInfo.strSignature = cJSON_GetObjectItem(encInfo, "signature")->valuestring;

			string binFilePath = getDiagnosisDir();
			binFilePath.append(oneFlashInfo.strLocalPath);

			string strRSAPrivateKeyFileName = getCertFilepath();
			string strKeyInfo = cJSON_GetObjectItem(encInfo, "keyInfo")->valuestring;
			cJSON_Delete(objRoot);

			if (ecuName._Equal("TCAM") || ecuName._Equal("BGM") || ecuName._Equal("CDC") || ecuName._Equal("ACU")) {
				return true;
			}

			if (oneFlashInfo.pVBFParser == NULL) {
				oneFlashInfo.pVBFParser = new VBFParserSmall();
			}
			return oneFlashInfo.pVBFParser->ParseVBFFile(binFilePath, strRSAPrivateKeyFileName, strKeyInfo);
		}
		else {
			cJSON_Delete(objRoot);
		}
	}
	else {
		Tracer::error("GetFlashFileInfo", strFilePath);
	}

	return false;
}

void CVehicleConfig::setCurrentVehicleType(string vehicleType)
{
	this->m_strVehicleType = vehicleType;
}

string CVehicleConfig::getCurrentVehicleType(void)
{
	return this->m_strVehicleType;
}

bool CVehicleConfig::setCurrentVehicleSoftVer(const std::string& strVehicleSoftVer)
{
	return setCurrentVehicleSoftVer(this->m_strVehicleType, strVehicleSoftVer);
}

bool CVehicleConfig::setCurrentVehicleSoftVer(const std::string& strVehicleType, const std::string& strVehicleSoftVer)
{
	this->m_strVehicleType = strVehicleType;
	Tracer::debug(__FUNCTION__, strVehicleType + ";" + strVehicleSoftVer);

	m_vehicleConfig.strBaseLine.clear();
	if (m_mapVehicleType.find(strVehicleType) == m_mapVehicleType.end())
	{
		Tracer::error("load vehicleType pkg", strVehicleType.c_str());

		//未找到当前vehicleType,重新加载整车包
		if (!reloadLoacalPkg()) {
			return false;
		}
		else if (m_mapVehicleType.find(strVehicleType) == m_mapVehicleType.end()) {
			Tracer::error("reload vehicleType pkg", strVehicleType.c_str());
			return false;
		}
	}

	this->m_vecVehicleSoftVer = m_mapVehicleType[strVehicleType];

	//未找到当前vehicleSoftVer,重新加载整车包
	if (this->m_vecVehicleSoftVer.end() == find(this->m_vecVehicleSoftVer.begin(), this->m_vecVehicleSoftVer.end(), strVehicleSoftVer)) {
		if (reloadLoacalPkg()) {
			this->m_vecVehicleSoftVer = m_mapVehicleType[strVehicleType];
			if (this->m_vecVehicleSoftVer.end() != find(this->m_vecVehicleSoftVer.begin(), this->m_vecVehicleSoftVer.end(), strVehicleSoftVer)) {
				this->m_strVehicleSoftVer = strVehicleSoftVer;
				reloadConfig();
				return this->reorder();
			}
		}

		//未找到当前vehicleSoftVer,提示用户下载
		Tracer::error("invalid vehicleSoftVer pkg", strVehicleSoftVer);
		return false;
	}

	this->m_strVehicleSoftVer = strVehicleSoftVer;
	reloadConfig();
	return this->reorder();
}

string CVehicleConfig::getCurrentVehicleSoftVer(void)
{
	return m_strVehicleSoftVer;
}

string CVehicleConfig::getDiagnosisDir()
{
	return this->DiagnosisDir;
}

string CVehicleConfig::getDiagnosisEcuFilesDir()
{
	return this->DiagnosisEcuFilesDir;
}

bool CVehicleConfig::reloadLoacalPkg()
{
	m_mapVehicleType.clear();
	m_vecVehicleSoftVer.clear();
	m_vehicleConfig.vecListEcu.clear();
	//TODO 获取整车包列表
	string vehicleTypesDir = getPkgFileDir();

	vector<string> vecDirs;
	bool bFlag = FileUtils::subdirectory(vehicleTypesDir, vecDirs);
	if (!bFlag) {
		Tracer::error("load vehicleType err", vehicleTypesDir);
		return false;
	}

	m_mapVehicleType[m_strVehicleType] = vecDirs;
	this->m_vecVehicleSoftVer = vecDirs;

	return true;
}

bool CVehicleConfig::reloadConfig()
{
	if (this->m_strVehicleSoftVer.empty()) {
		return false;
	}

	//TODO 解析整车包
	string cfgFilepath = getFlashFileDir() + "\\config.json";
	Tracer::debug("cfgFilepath", cfgFilepath);

	CFlashFileUtils FileUtil;
	std::string strConfig;
	bool bRet = FileUtil.LoadConfig(strConfig, cfgFilepath);
	if (bRet == true) {
		Tracer::debug("strConfig", strConfig);
		cJSON* obj = cJSON_Parse(strConfig.c_str());
		if (NULL == obj) {
			Tracer::error("LoadConfig err", "config.json parsed err.");
			return false;
		}
		if (obj->type == cJSON_Object) {
			if (cJSON_HasObjectItem(obj, "baseLine"))
				this->m_vehicleConfig.strBaseLine = cJSON_GetStringValue(cJSON_GetObjectItem(obj, "baseLine"));
			if (cJSON_HasObjectItem(obj, "displayVersion"))
				this->m_vehicleConfig.strDisplayBaseLine = cJSON_GetStringValue(cJSON_GetObjectItem(obj, "displayVersion"));
			if (cJSON_HasObjectItem(obj, "baseLineVer"))
				this->m_vehicleConfig.strBaseLineVer = cJSON_GetStringValue(cJSON_GetObjectItem(obj, "baseLineVer"));

			cJSON* ecuList = cJSON_GetObjectItem(obj, "ecu");
			GetEcuList(ecuList, this->m_vehicleConfig.vecListEcu);
			cJSON_Delete(obj);
		}
		else {
			cJSON_Delete(obj);
			Tracer::error("LoadConfig err", "config.json parsed err.");
			return false;
		}
	}
	else {
		Tracer::error("Load config.json err", cfgFilepath);
		return false;
	}

	return true;
}

bool CVehicleConfig::reorder()
{
	JD_VEHICLE_ORDER_t vehicleOrderInfo = DataCenter::getInstance()->m_VehicleOrderInfo;
	if (!vehicleOrderInfo.vecListEcu.empty()) {
		//TODO 排序:整车版本移到首位
		for (int i = 1; i < this->m_vecVehicleSoftVer.size(); i++) {
			if (this->m_vecVehicleSoftVer.at(i)._Equal(m_strVehicleSoftVer)) {
				swap(this->m_vecVehicleSoftVer.at(0), this->m_vecVehicleSoftVer.at(i));
			}
		}

		if (m_vehicleConfig.strBaseLine.empty()) {
			if (!reloadConfig()) {
				return false;
			}
		}

		//TODO 对订单EcuList排序
		vector<JD_ECU_INFO_t> vecListEcu;
		map<string, int>ecuGroup;
		for (JD_ECU_CONFIG_t cfgInfo : m_vehicleConfig.vecListEcu) {
			ecuGroup[cfgInfo.strEcuName] = cfgInfo.nEcuGroup;
		}
		for (int gIndex = 0; ; gIndex++) {
			for (JD_ECU_INFO_t ecuInfo : vehicleOrderInfo.vecListEcu) {
				string ecuName = ecuInfo.strEcuName;
				if (ecuGroup[ecuName] == gIndex) {
					vecListEcu.push_back(ecuInfo);
				}
			}
			if (vecListEcu.size() >= vehicleOrderInfo.vecListEcu.size()) {
				vehicleOrderInfo.vecListEcu = vecListEcu;
				DataCenter::getInstance()->m_VehicleOrderInfo = vehicleOrderInfo;
				break;
			}
		}

		return true;
	}

	return false;
}

bool CVehicleConfig::IsCompleted(const std::string vehicleType, const std::string vehicleSoftVer)
{
	bool ret = false;

	string filepath;
	string oldVehicleSoftVer = this->m_strVehicleSoftVer;
	if (vehicleSoftVer._Equal(this->m_strVehicleSoftVer)) {
		filepath = getFlashFileDir() + "\\ecu.txt";
	}
	else {
		setCurrentVehicleSoftVer(vehicleSoftVer);
		filepath = getFlashFileDir() + "\\ecu.txt";
		setCurrentVehicleSoftVer(oldVehicleSoftVer);
	}

	std::fstream fin(filepath);
	if (!fin.is_open())
	{
		return ret;
	}
	std::string content;
	std::string line;
	while (std::getline(fin, line))
	{
		content += line;
	}
	content.erase(0, 3); // UTF-8 BOM 需要去掉前3个字节

	cJSON* obj = cJSON_Parse(content.c_str());
	if (cJSON_IsObject(obj)) {

		if (cJSON_HasObjectItem(obj, "IsCompleted"))
		{
			ret = cJSON_GetObjectItem(obj, "IsCompleted")->valueint;
		}
	}

	cJSON_Delete(obj);
	return ret;
}

bool CVehicleConfig::IsCompleted(uint16_t bridgeId)
{
	bool ret = false;

	string filepath = getBridgeFileDir(bridgeId) + "\\ecu.txt";
	std::fstream fin(filepath);
	if (!fin.is_open())
	{
		Tracer::error("BridgeFileDir Open Fail", filepath);
		return ret;
	}
	std::string content;
	std::string line;
	while (std::getline(fin, line))
	{
		content += line;
	}
	content.erase(0, 3); // UTF-8 BOM 需要去掉前3个字节

	cJSON* obj = cJSON_Parse(content.c_str());
	if (cJSON_IsObject(obj)) {

		if (cJSON_HasObjectItem(obj, "IsCompleted"))
		{
			ret = cJSON_GetObjectItem(obj, "IsCompleted")->valueint;
		}
	}

	cJSON_Delete(obj);
	return ret;
}

bool CVehicleConfig::IsLatestBatch(const std::string vehicleType, const std::string vehicleSoftVer)
{
	bool ret = false;

	string filepath;
	string oldVehicleSoftVer = this->m_strVehicleSoftVer;
	if (vehicleSoftVer._Equal(this->m_strVehicleSoftVer)) {
		filepath = getFlashFileDir() + "\\ecu.txt";
	}
	else {
		setCurrentVehicleSoftVer(vehicleSoftVer);
		filepath = getFlashFileDir() + "\\ecu.txt";
		setCurrentVehicleSoftVer(oldVehicleSoftVer);
	}

	std::fstream fin(filepath);
	if (!fin.is_open())
	{
		return ret;
	}
	std::string content;
	std::string line;
	while (std::getline(fin, line))
	{
		content += line;
	}
	content.erase(0, 3); // UTF-8 BOM 需要去掉前3个字节

	cJSON* obj = cJSON_Parse(content.c_str());
	if (cJSON_IsObject(obj)) {

		if (cJSON_HasObjectItem(obj, "isLastVersion"))
		{
			ret = cJSON_GetObjectItem(obj, "isLastVersion")->valueint;
		}
	}

	cJSON_Delete(obj);
	return ret;
}


bool FlashFolderFilter(std::string strFilePath)
{
	std::string strECU = "";

	FILE* fp = fopen(strFilePath.c_str(), "rb");
	if (fp == NULL)
	{
		return false;
	}
	fseek(fp, 0, SEEK_END);
	size_t datasize = ftell(fp);
	fseek(fp, 0, SEEK_SET);
	uint8_t* pBuffer = (uint8_t*)malloc(datasize + 1);
	if (pBuffer == NULL) {
		return false;
	}
	else {
		memset(pBuffer, 0, datasize + 1);
		fread(pBuffer, 1, datasize, fp);
		strECU.assign((char*)pBuffer, datasize);
		free(pBuffer);
	}

	fclose(fp);

	cJSON* root = cJSON_Parse(strECU.c_str());
	cJSON* isCompleted = cJSON_GetObjectItem(root, "isCompleted");
	if (NULL != isCompleted && isCompleted->type != NULL)
	{
		if (isCompleted->valueint)
		{
			cJSON_Delete(root);
			return 1;
		}
		else
		{
			cJSON_Delete(root);
			return 0;
		}
	}
	cJSON_Delete(root);
	return 1;
}

bool CVehicleConfig::GetEcuList(cJSON* ecuList, vector<JD_ECU_CONFIG_t>& vecListEcu) {

	vecListEcu.clear();
	int arraySize = cJSON_GetArraySize(ecuList);
	for (int i = 0; i < arraySize; i++)
	{
		JD_ECU_CONFIG_t ecuConfig;
		cJSON* ecuItem = cJSON_GetArrayItem(ecuList, i);
		if (cJSON_IsNull(ecuItem)) {
			Tracer::error("GetEcuList", "null ecuItem");
			continue;
		}

		int nccpId = -100;
		if (cJSON_HasObjectItem(ecuItem, "ccpId"))
		{
			if (cJSON_IsNumber(cJSON_GetObjectItem(ecuItem, "ccpId")))
			{
				nccpId = cJSON_GetObjectItem(ecuItem, "ccpId")->valueint;
			}
		}


		if ((nccpId > 0) && cJSON_HasObjectItem(ecuItem, "ccpCode"))
		{
			cJSON* obj_ccpCode = cJSON_GetObjectItem(ecuItem, "ccpCode");
			if (cJSON_IsString(obj_ccpCode))
			{
				std::string ccpCode = obj_ccpCode->valuestring;
				if (!ccpCode.empty()) {
					int nccpCode = MyStringUtils::toLong(ccpCode);
					if (DataCenter::m_vehicleInfo.binCCP.GetSize() > nccpId)
					{
						int nccpCode_vehicle = DataCenter::m_vehicleInfo.binCCP.GetAt(nccpId - 1);
						if (nccpCode != nccpCode_vehicle)
						{
							continue;
						}
					}
				}
			}
		}


		if (cJSON_HasObjectItem(ecuItem, "doipAddr"))
		{
			std::string strDoipAddr = cJSON_GetObjectItem(ecuItem, "doipAddr")->valuestring;
			ecuConfig.nDoipAddr = MyStringUtils::toLong(strDoipAddr, 16);
		}
		if (cJSON_HasObjectItem(ecuItem, "ecuGroup"))
		{
			ecuConfig.nEcuGroup = cJSON_GetObjectItem(ecuItem, "ecuGroup")->valueint;
		}
		if (cJSON_HasObjectItem(ecuItem, "ecuId"))
		{
			std::string strDoipAddr = cJSON_GetObjectItem(ecuItem, "ecuId")->valuestring;
			ecuConfig.nEcuId = MyStringUtils::toLong(strDoipAddr, 16);
		}
		if (cJSON_HasObjectItem(ecuItem, "bomEcuName"))
		{
			ecuConfig.strBoomEcuName = cJSON_GetObjectItem(ecuItem, "bomEcuName")->valuestring;
		}
		if (cJSON_HasObjectItem(ecuItem, "ecuName"))
		{
			ecuConfig.strEcuName = cJSON_GetObjectItem(ecuItem, "ecuName")->valuestring;
		}
		if (cJSON_HasObjectItem(ecuItem, "ecuOrder"))
		{
			ecuConfig.nEcuOrder = cJSON_GetObjectItem(ecuItem, "ecuOrder")->valueint;
		}

		if (cJSON_HasObjectItem(ecuItem, "mapping"))
		{
			cJSON* mappingArray = cJSON_GetObjectItem(ecuItem, "mapping");
			for (int j = 0; j < cJSON_GetArraySize(mappingArray); j++)
			{
				JD_MAPPING_CONFIG_t mapping;
				cJSON* mappingItem = cJSON_GetArrayItem(mappingArray, j);

				mapping.strHwpn = cJSON_GetObjectItem(mappingItem, "hwpn")->valuestring;

				cJSON* appListArray = cJSON_GetObjectItem(mappingItem, "appList");
				GetList(appListArray, mapping.vecAppList);

				cJSON* dataListArray = cJSON_GetObjectItem(mappingItem, "dataList");
				GetList(dataListArray, mapping.vecDataList);

				cJSON* orderListArray = cJSON_GetObjectItem(mappingItem, "orderList");
				GetOderList(orderListArray, mapping.vecOderList);

				cJSON* sblListArray = cJSON_GetObjectItem(mappingItem, "sblList");
				GetList(sblListArray, mapping.vecSblList);

				ecuConfig.vecMapping.push_back(mapping);
			}
		}

		if (cJSON_HasObjectItem(ecuItem, "otherEcuHWCheck"))
		{
			cJSON* otherEcuHWCheck = cJSON_GetObjectItem(ecuItem, "otherEcuHWCheck");
			if (cJSON_GetArraySize(otherEcuHWCheck)) {
				char* temp = cJSON_PrintUnformatted(otherEcuHWCheck);
				Tracer::warn(ecuConfig.strEcuName, "otherEcuHWCheck");
				Tracer::info("otherEcuHWCheck", temp);
				cJSON_free(temp);
				GetOtherEcuHWCheck(otherEcuHWCheck, ecuConfig.vecPreconditionList);
			}
		}

		bool found = false;
		for (JD_ECU_CONFIG_t& vConfig : vecListEcu) {
			if (vConfig.nEcuId == ecuConfig.nEcuId) {
				for (JD_MAPPING_CONFIG_t mapping : ecuConfig.vecMapping) {
					bool foundHwpn = false;
					for (JD_MAPPING_CONFIG_t& vMapping : vConfig.vecMapping) {
						if (vMapping.strHwpn._Equal(mapping.strHwpn)) {
							foundHwpn = true;
							for (JD_VSP_FLASH_INFO_t vsp : mapping.vecOderList)
							{
								bool foundVsp = false;
								for (JD_VSP_FLASH_INFO_t vVsp : vMapping.vecOderList) {
									if (vVsp.strVersion._Equal(vsp.strVersion)) {
										foundVsp = true;
									}
								}
								if (!foundVsp)
								{
									vMapping.vecOderList.push_back(vsp);
								}
							}
						}
					}

					if (!foundHwpn) {
						vConfig.vecMapping.push_back(std::move(mapping));
					}
				}
				found = true;
				break;
			}
		}

		if (!found) {
			vecListEcu.push_back(ecuConfig);
		}
	}


	//TODO 排序 域控放在前面
	std::vector<std::string> domainEcuNames = { "TCAM", "BGM", "CDC", "ACU" };
	vector<JD_ECU_CONFIG_t> vecNew;
	for (JD_ECU_CONFIG_t ecuCfg : vecListEcu) {
		if (std::find(domainEcuNames.begin(), domainEcuNames.end(), ecuCfg.strEcuName) != domainEcuNames.end()) {
			vecNew.push_back(ecuCfg);
		}
	}
	for (JD_ECU_CONFIG_t ecuCfg : vecListEcu) {
		if (std::find(domainEcuNames.begin(), domainEcuNames.end(), ecuCfg.strEcuName) != domainEcuNames.end()) {
			continue;
		}
		vecNew.push_back(ecuCfg);
	}
	vecListEcu = vecNew;


	//TODO 打印整车包
	for (JD_ECU_CONFIG_t tempCfg : vecListEcu) {
		string strEcuHwpn;
		for (JD_MAPPING_CONFIG_t mappig : tempCfg.vecMapping)
		{
			strEcuHwpn.append(mappig.strHwpn).append(";");
		}
		Tracer::debug("pkgHwpn: " + tempCfg.strEcuName, strEcuHwpn);
	}

	return 0;
}

bool CVehicleConfig::GetOtherEcuHWCheck(cJSON* otherEcuHWCheck, vector<JD_FLASH_PRECONDITION>& vecPreconditionList)
{
	vecPreconditionList.clear();

	if (cJSON_IsArray(otherEcuHWCheck))
	{
		for (int i = 0; i < cJSON_GetArraySize(otherEcuHWCheck); i++)
		{
			cJSON* ecuHWCheck = cJSON_GetArrayItem(otherEcuHWCheck, i);
			JD_FLASH_PRECONDITION oneCondition;
			if (cJSON_HasObjectItem(ecuHWCheck, "ecuId"))
			{
				std::string strEcuId = cJSON_GetObjectItem(ecuHWCheck, "ecuId")->valuestring;

				oneCondition.nEcuId = MyStringUtils::toLong(strEcuId, 16);
			}
			if (cJSON_HasObjectItem(ecuHWCheck, "ecuName"))
			{
				oneCondition.strEcuName = cJSON_GetObjectItem(ecuHWCheck, "ecuName")->valuestring;
			}
			if (cJSON_HasObjectItem(ecuHWCheck, "hwPn"))
			{
				cJSON* hwPnArray = cJSON_GetObjectItem(ecuHWCheck, "hwPn");
				if (cJSON_IsArray(hwPnArray))
				{
					for (int j = 0; j < cJSON_GetArraySize(hwPnArray); j++)
					{
						oneCondition.vecHwPn.push_back(cJSON_GetArrayItem(hwPnArray, j)->valuestring);
					}
				}
			}
			vecPreconditionList.push_back(oneCondition);
		}
	}
	return true;
}

string CVehicleConfig::getEcuName_byOrderEcuName(string orderName)
{
	for (JD_ECU_INFO_t orderInfo : DataCenter::m_VehicleOrderInfo.vecListEcu) {
		if (orderInfo.strEcuName._Equal(orderName)) {
			int ecuId = orderInfo.nEcuId;

			for (JD_ECU_CONFIG_t pkgInfo : m_vehicleConfig.vecListEcu) {
				if (pkgInfo.nEcuId == ecuId) {
					return pkgInfo.strEcuName;
				}
			}

			break;
		}
	}

	return orderName;
}

bool CVehicleConfig::GetList(cJSON* obj, vector<std::string>& vecList)
{
	bool bRet = false;

	vecList.clear();

	if (obj->type == cJSON_Array)
	{
		for (int i = 0; i < cJSON_GetArraySize(obj); i++)
		{
			cJSON* item = cJSON_GetArrayItem(obj, i);
			if (item->type == cJSON_String)
			{
				vecList.push_back(cJSON_GetStringValue(item));
			}
		}
	}

	bRet = true;
	return bRet;
}

bool CVehicleConfig::GetOderList(cJSON* oderList, vector<JD_VSP_FLASH_INFO_t>& vecList) {
	vecList.clear();
	if (oderList->type == cJSON_Array)
	{
		for (int i = 0; i < cJSON_GetArraySize(oderList); i++)
		{
			cJSON* tempArray = cJSON_GetArrayItem(oderList, i);

			if (tempArray->type == cJSON_Array)
			{
				for (int j = 0; j < cJSON_GetArraySize(tempArray); j++)
				{
					cJSON* item = cJSON_GetArrayItem(tempArray, j);

					JD_VSP_FLASH_INFO_t oneFlashOderInfo;

					if (cJSON_HasObjectItem(item, "fileName"))
					{
						oneFlashOderInfo.strFileName = cJSON_GetStringValue(cJSON_GetObjectItem(item, "fileName"));
					}

					if (cJSON_HasObjectItem(item, "fileType"))
					{
						oneFlashOderInfo.strFileType = cJSON_GetStringValue(cJSON_GetObjectItem(item, "fileType"));
					}

					if (cJSON_HasObjectItem(item, "version"))
					{
						oneFlashOderInfo.strVersion = cJSON_GetStringValue(cJSON_GetObjectItem(item, "version"));
					}

					vecList.push_back(oneFlashOderInfo);
				}
			}
		}
	}

	return 0;
}

bool CVehicleConfig::getEcuFileInfo(string ecuName, string ecuHwpn, vector<JD_VSP_FLASH_CONFIG_t>& vecFlash)
{
	if (m_vehicleConfig.vecListEcu.empty()) {
		Tracer::error("invalid pkg", m_strVehicleSoftVer);
		return false;
	}

	string pkgName = CVehicleConfig::getInstance()->getEcuName_byOrderEcuName(ecuName);
	for (int i = 0; i < m_vehicleConfig.vecListEcu.size(); i++) {
		JD_ECU_CONFIG_t tempEcuStruct = m_vehicleConfig.vecListEcu.at(i);

		string boomEcuName = tempEcuStruct.strBoomEcuName;

		if (pkgName._Equal(tempEcuStruct.strEcuName)) {
			int ecuId = tempEcuStruct.nEcuId;

			if (tempEcuStruct.vecMapping.size() == 0) {
				Tracer::error("getEcuFileInfo", "vecMapping.size=0");
			}

			Tracer::warn("vecMapping.size: " + pkgName, to_string(tempEcuStruct.vecMapping.size()));
			for (int j = 0; j < tempEcuStruct.vecMapping.size(); j++) {
				JD_MAPPING_CONFIG_t tempMap = tempEcuStruct.vecMapping.at(j);

				string temp1 = ecuHwpn;
				MyStringUtils::replace(temp1, " ", "");
				string temp2 = tempMap.strHwpn;
				MyStringUtils::replace(temp2, " ", "");
				if (temp1._Equal(temp2)) {
					vector<string> ecuSwpnInfoList;

					for (int k = 0; k < tempMap.vecOderList.size(); k++)
					{
						string ecuSwpn = tempMap.vecOderList.at(k).strVersion;
						ecuSwpnInfoList.push_back(ecuSwpn);
					}

					for (int k = 0; k < ecuSwpnInfoList.size(); k++) {
						JD_VSP_FLASH_CONFIG_t oneFlashInfo;
						string ecuSwpn = ecuSwpnInfoList.at(k);
						if (CVehicleConfig::getInstance()->GetFlashFileInfo(ecuId, boomEcuName, tempMap.strHwpn, ecuSwpn, oneFlashInfo))
						{
							vecFlash.push_back(oneFlashInfo);
						}
						else {
							Tracer::error("GetFlashFileInfo", boomEcuName);
							return false;
						}
					}

					return true;
				}
				else {
					Tracer::warn("mismatch hwpn: " + pkgName, tempMap.strHwpn + "|" + ecuHwpn);
				}
			}
		}
	}

	Tracer::error(pkgName, "invalid ecuName for fun(getEcuFileInfo)");
	return false;
}

bool CVehicleConfig::getEcuFileInfo(uint16_t ecuId, string ecuHwpn, vector<JD_VSP_FLASH_CONFIG_t>& vecFlash)
{
	if (m_vehicleConfig.vecListEcu.empty()) {
		Tracer::error("invalid pkg", m_strVehicleSoftVer);
		return false;
	}

	char tempBuffer[32] = { 0 };
	string strEcuId = _itoa(ecuId, tempBuffer, 16);


	for (int i = 0; i < m_vehicleConfig.vecListEcu.size(); i++) {
		JD_ECU_CONFIG_t tempEcuStruct = m_vehicleConfig.vecListEcu.at(i);

		string boomEcuName = tempEcuStruct.strBoomEcuName;

		if ((ecuId & 0xFFF0) == (tempEcuStruct.nEcuId & 0xFFF0)) {
		//if (ecuId == tempEcuStruct.nEcuId) {
			int ecuId = tempEcuStruct.nEcuId;

			if (tempEcuStruct.vecMapping.size() == 0) {
				Tracer::error("getEcuFileInfo", "vecMapping.size=0");
			}

			for (int j = 0; j < tempEcuStruct.vecMapping.size(); j++) {
				JD_MAPPING_CONFIG_t tempMap = tempEcuStruct.vecMapping.at(j);

				string temp1 = ecuHwpn;
				MyStringUtils::replace(temp1, " ", "");
				string temp2 = tempMap.strHwpn;
				MyStringUtils::replace(temp2, " ", "");
				if (temp1._Equal(temp2)) {
					vector<string> ecuSwpnInfoList;

					for (int k = 0; k < tempMap.vecOderList.size(); k++)
					{
						string ecuSwpn = tempMap.vecOderList.at(k).strVersion;
						ecuSwpnInfoList.push_back(ecuSwpn);
					}

					for (int k = 0; k < ecuSwpnInfoList.size(); k++) {
						JD_VSP_FLASH_CONFIG_t oneFlashInfo;
						string ecuSwpn = ecuSwpnInfoList.at(k);
						if (CVehicleConfig::getInstance()->GetFlashFileInfo(ecuId, boomEcuName, tempMap.strHwpn, ecuSwpn, oneFlashInfo))
						{
							vecFlash.push_back(oneFlashInfo);
						}
						else {
							Tracer::error("GetFlashFileInfo", boomEcuName);
							return false;
						}
					}

					return true;
				}
				else {
					Tracer::warn(string("mismatch hwpn: ") + strEcuId, tempMap.strHwpn + "|" + ecuHwpn);
				}
			}
		}
	}

	Tracer::error("invalid ecuId for fun(getEcuFileInfo)", strEcuId);
	return false;
}

bool CVehicleConfig::getEcuConfig(string ecuName, JD_ECU_CONFIG_t& ecuConfig)
{
	if (m_vehicleConfig.vecListEcu.empty()) {
		Tracer::error("invalid pkg", m_strVehicleSoftVer);
		return false;
	}

	for (int i = 0; i < m_vehicleConfig.vecListEcu.size(); i++) {
		JD_ECU_CONFIG_t tempEcuStruct = m_vehicleConfig.vecListEcu.at(i);
		if (ecuName._Equal(tempEcuStruct.strEcuName)) {
			ecuConfig = tempEcuStruct;
			return true;
		}
	}

	return false;
}

bool CVehicleConfig::getEcuConfig(uint16_t ecuId, JD_ECU_CONFIG_t& ecuConfig)
{
	if (m_vehicleConfig.vecListEcu.empty()) {
		Tracer::error("invalid pkg", m_strVehicleSoftVer);
		return false;
	}

	for (int i = 0; i < m_vehicleConfig.vecListEcu.size(); i++) {
		JD_ECU_CONFIG_t tempEcuStruct = m_vehicleConfig.vecListEcu.at(i);
		if (ecuId == tempEcuStruct.nEcuId) {
			ecuConfig = tempEcuStruct;
			return true;
		}
	}

	return false;
}


bool CVehicleConfig::getBridgeFlashFileInfo(int bridgeId, string ecuName, string hwpn, string swpn, JD_VSP_FLASH_CONFIG_t& oneFlashInfo)
{
	string strFilePath = getBridgeFileDir(bridgeId);
	strFilePath.append("\\").append(ecuName).append("\\").append(hwpn).append("\\").append(swpn).append(".json");

	CFlashFileUtils FileUtil;
	std::string strConfig;
	bool bRet = FileUtil.LoadConfig(strConfig, strFilePath);
	if (bRet)
	{
		Tracer::debug(strFilePath, strConfig);
		cJSON* objRoot = cJSON_Parse(strConfig.c_str());
		if (cJSON_IsObject(objRoot)) {
			oneFlashInfo.strFileType = cJSON_GetObjectItem(objRoot, "fileType")->valuestring;
			oneFlashInfo.strFileName = cJSON_GetObjectItem(objRoot, "fileName")->valuestring;
			auto element = cJSON_GetObjectItem(objRoot, "version");
			if (element != NULL) {
				oneFlashInfo.strVersion = element->valuestring;
			}
			else {
				element = cJSON_GetObjectItem(objRoot, "softName");
				if (element != NULL) {
					oneFlashInfo.strVersion = element->valuestring;
				}
			}

			cJSON* encInfo = cJSON_GetObjectItem(objRoot, "diagnoseEncryptionInfo");
			oneFlashInfo.nFlashFileSize = (uint64_t)cJSON_GetObjectItem(encInfo, "size")->valuedouble;
			oneFlashInfo.strLocalPath = cJSON_GetObjectItem(encInfo, "localPath")->valuestring;
			oneFlashInfo.strkeyId = cJSON_GetObjectItem(encInfo, "keyId")->valuestring;
			oneFlashInfo.strKeyInfo = cJSON_GetObjectItem(encInfo, "keyInfo")->valuestring;
			oneFlashInfo.strSignature = cJSON_GetObjectItem(encInfo, "signature")->valuestring;
			oneFlashInfo.strFileName = cJSON_GetObjectItem(objRoot, "fileName")->valuestring;

			string binFilePath = getDiagnosisDir();
			binFilePath.append(oneFlashInfo.strLocalPath);

			string strRSAPrivateKeyFileName = getCertFilepath();
			string strKeyInfo = cJSON_GetObjectItem(encInfo, "keyInfo")->valuestring;
			cJSON_Delete(objRoot);

			if (ecuName._Equal("TCAM") || ecuName._Equal("BGM") || ecuName._Equal("CDC") || ecuName._Equal("ACU")) {
				return true;
			}

			if (oneFlashInfo.pVBFParser == NULL) {
				oneFlashInfo.pVBFParser = new VBFParserSmall();
			}
			return oneFlashInfo.pVBFParser->ParseVBFFile(binFilePath, strRSAPrivateKeyFileName, strKeyInfo);
		}
		else {
			cJSON_Delete(objRoot);
		}
	}
	else {
		Tracer::error("GetFlashFileInfo", strFilePath);

		return false;
	}

	return true;
}

bool CVehicleConfig::getBridgeEcuFileInfo(int bridgeId, string hwpn, vector<JD_VSP_FLASH_CONFIG_t>& vecFlash)
{
	string strFilePath = getBridgeFileDir(bridgeId);
	strFilePath.append("\\").append("config.json");

	CFlashFileUtils FileUtil;
	std::string strConfig;
	bool bRet = FileUtil.LoadConfig(strConfig, strFilePath);
	if (bRet)
	{
		Tracer::debug(strFilePath, strConfig);
		cJSON* objRoot = cJSON_Parse(strConfig.c_str());
		if (!cJSON_IsNull(objRoot)) {
			string ecuName;
			if (cJSON_HasObjectItem(objRoot, "ecuNameList")) {
				cJSON* arrayEcuNameList = cJSON_GetObjectItem(objRoot, "ecuNameList");
				if (cJSON_GetArraySize(arrayEcuNameList) >= 1) {
					ecuName = cJSON_GetArrayItem(arrayEcuNameList, 0)->valuestring;
				}
			}
			if (cJSON_HasObjectItem(objRoot, "mapping")) {
				cJSON* arrayMapping = cJSON_GetObjectItem(objRoot, "mapping");

				for (int i = 0; i < cJSON_GetArraySize(arrayMapping); i++) {
					cJSON* objMappingItem = cJSON_GetArrayItem(arrayMapping, i);
					if (cJSON_HasObjectItem(objMappingItem, "hwpn")) {
						string mappingHwpn = cJSON_GetObjectItem(objMappingItem, "hwpn")->valuestring;
						if (mappingHwpn._Equal(hwpn)) {
							if (cJSON_HasObjectItem(objMappingItem, "orderList")) {
								cJSON* arrayOrderList = cJSON_GetObjectItem(objMappingItem, "orderList");
								for (int i = 0; i < cJSON_GetArraySize(arrayOrderList); i++) {
									cJSON* objItem = cJSON_GetArrayItem(arrayOrderList, i);
									for (int j = 0; j < cJSON_GetArraySize(objItem); j++) {
										cJSON* objOrder = cJSON_GetArrayItem(objItem, i);
										string swpn = cJSON_GetObjectItem(objOrder, "version")->valuestring;
										MyStringUtils::replace(swpn, " ", "");

										JD_VSP_FLASH_CONFIG_t oneFlashInfo;
										getBridgeFlashFileInfo(bridgeId, ecuName, hwpn, swpn, oneFlashInfo);
										vecFlash.push_back(oneFlashInfo);
									}
								}
							}
							break;
						}
					}
				}
			}
		}
		cJSON_Delete(objRoot);

		return true;
	}
	return false;
}

string CVehicleConfig::getBridgeEcuName(int bridgeId)
{
	string strFilePath = getBridgeFileDir(bridgeId);
	strFilePath.append("\\").append("config.json");
	string ecuName;
	CFlashFileUtils FileUtil;
	std::string strConfig;
	bool bRet = FileUtil.LoadConfig(strConfig, strFilePath);
	if (bRet)
	{
		cJSON* objRoot = cJSON_Parse(strConfig.c_str());
		if (!cJSON_IsNull(objRoot)) {

			if (cJSON_HasObjectItem(objRoot, "ecuNameList")) {
				cJSON* arrayEcuNameList = cJSON_GetObjectItem(objRoot, "ecuNameList");
				if (cJSON_GetArraySize(arrayEcuNameList) >= 1) {
					ecuName = cJSON_GetArrayItem(arrayEcuNameList, 0)->valuestring;
				}
			}
		}
		cJSON_Delete(objRoot);
	}
	return ecuName;
}

uint16_t CVehicleConfig::getBridgeEcuId(int bridgeId)
{
	string strFilePath = getBridgeFileDir(bridgeId);
	strFilePath.append("\\").append("config.json");
	uint16_t ecuId;
	CFlashFileUtils FileUtil;
	std::string strConfig;
	bool bRet = FileUtil.LoadConfig(strConfig, strFilePath);
	if (bRet)
	{
		cJSON* objRoot = cJSON_Parse(strConfig.c_str());
		if (!cJSON_IsNull(objRoot)) {

			if (cJSON_HasObjectItem(objRoot, "ecuIdList")) {
				cJSON* arrayEcuNameList = cJSON_GetObjectItem(objRoot, "ecuIdList");
				if (cJSON_GetArraySize(arrayEcuNameList) >= 1) {
					string strEcuId = cJSON_GetArrayItem(arrayEcuNameList, 0)->valuestring;
					ecuId = MyStringUtils::toLong(strEcuId, 16);
				}
			}
		}
		cJSON_Delete(objRoot);
	}
	return ecuId;
}


