#include "jidu_dataCenter.h"
#include "jidu.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstring>
#include "cJSON.h"
#include "tracer.h"
#include "algorithm.h"
#include "jidu_vehicleConfig.h"
#include "MyStringUtils.h"

using namespace std;
extern ecu_node_t ecutable[JD_EUC_COUNT];

static map<string, string> map_diagnosisId;
int get_jd_ecuName_byEcuId(uint16_t ecuId, char* outBuffer, uint32_t outBufferSize)
{
	memset(outBuffer, 0, outBufferSize);
	for (int i = 0; i < JD_EUC_COUNT; i++) {
		if ((ecutable[i].ecuId & 0xFFF0) == (ecuId & 0xFFF0)) {
			string ecuName = ecutable[i].ecuName;

			memcpy(outBuffer, ecuName.c_str(), ecuName.size());
			return (int)ecuName.size();
		}
	}

	return -1;
}

int get_jd_ecuName_byIpAddr(uint32_t ipAddr, char* outBuffer, uint32_t outBufferSize)
{
	if (ipAddr == 0x1002 || ipAddr == 0x1402 || ipAddr == 0x1202)
		ipAddr -= 1;

	memset(outBuffer, 0, outBufferSize);
	for (int i = 0; i < JD_EUC_COUNT; i++) {
		if (ecutable[i].doIp == ipAddr) {
			string ecuName = ecutable[i].ecuName;

			VehicleCfg vehicleCfg;
			if (DataCenter::getInstance()->factory._Equal("Project")) {
				uint8_t tempBuffer[4096];
				int rLen = radix_hex2Array(DataCenter::m_VehicleOrderInfo.strCCPCode.c_str(), DataCenter::m_VehicleOrderInfo.strCCPCode.length(), tempBuffer, 4096);
				CBinary binCCP(tempBuffer, rLen);

				if (DataCenter::getInstance()->getCarConfig(binCCP, vehicleCfg)) {
					if (MyStringUtils::startWith(ecuName, "BECM1")) {
						ecuName = (vehicleCfg.iBatteryCapacity == 102) ? "BECM1_102" : "BECM1_75";
					}
					else if (MyStringUtils::startWith(ecuName, "IEM")) {
						ecuName = vehicleCfg.strIemEcuName;
					}
					else if (ecuName._Equal("WPC")) {
						ecuName = vehicleCfg.strWpcEcuName;
					}
				}
			}
			else {
				if (DataCenter::getInstance()->getCarConfig(DataCenter::m_vehicleInfo.binCCP, vehicleCfg)) {
					if (MyStringUtils::startWith(ecuName, "BECM1")) {
						ecuName = (vehicleCfg.iBatteryCapacity == 102) ? "BECM1_102" : "BECM1_75";
					}
					else if (MyStringUtils::startWith(ecuName, "IEM")) {
						ecuName = vehicleCfg.strIemEcuName;
					}
					else if (ecuName._Equal("WPC")) {
						ecuName = vehicleCfg.strWpcEcuName;
					}
				}
			}

			if (outBufferSize > ecuName.size()) {
				memcpy(outBuffer, ecuName.c_str(), ecuName.size());
				return (int)ecuName.size();
			}
			else {
				return -1;
			}
		}
	}

	return -1;
}

int get_jd_doIp_byEcuName(const char* ecuName)
{
	for (int i = 0; i < JD_EUC_COUNT; i++) {
		if (ecutable[i].ecuName._Equal(ecuName)) {
			return ecutable[i].doIp;
		}
	}

	return 0;
}

int get_jd_doIp_byEcuId(uint16_t ecuId)
{
	for (int i = 0; i < JD_EUC_COUNT; i++) {
		if (ecutable[i].ecuId == ecuId) {
			return ecutable[i].doIp;
		}
	}

	return 0;
}

int get_jd_ccpTaskNum(const char* vid, const char* vin, int sceneType, char* outBuffer, uint32_t outBufferSize)
{
	cJSON* objReq = cJSON_CreateObject();

	cJSON_AddStringToObject(objReq, "vid", vid);
	cJSON_AddStringToObject(objReq, "vin", vin);
	cJSON_AddStringToObject(objReq, "deviceSn", DataCenter::getInstance()->m_deviceSN.c_str());
	cJSON_AddNumberToObject(objReq, "sceneType", sceneType);

	char* reqBuffer = (char*)malloc(1024);
	cJSON_PrintPreallocated(objReq, reqBuffer, 1024, 0);
	cJSON_Delete(objReq);

	char* resBuffer = (char*)malloc(4096);
	int retCode = callServer(68, reqBuffer, resBuffer, 4096);
	free(reqBuffer);
	if (retCode > 0) {
		retCode = -1;
		cJSON* objRes = cJSON_Parse(resBuffer);
		free(resBuffer);
		if (cJSON_HasObjectItem(objRes, "data"))
		{
			cJSON* objData = cJSON_GetObjectItem(objRes, "data");
			string tempString = cJSON_GetObjectItem(objData, "taskNumber")->valuestring;

			if (outBufferSize > tempString.length()) {
				memcpy(outBuffer, tempString.c_str(), tempString.length());

				retCode = tempString.length();
			}
		}

		cJSON_Delete(objRes);
	}

	return retCode;
}

int get_jd_vehicleActiveStatus(const char* vin)
{
	cJSON* objReq = cJSON_CreateObject();
	cJSON_AddStringToObject(objReq, "vin", vin);

	char* reqBuffer = (char*)malloc(1024);
	cJSON_PrintPreallocated(objReq, reqBuffer, 1024, 0);
	cJSON_Delete(objReq);

	char* resBuffer = (char*)malloc(4096);
	int retCode = callServer(82, reqBuffer, resBuffer, 4096);
	free(reqBuffer);
	if (retCode > 0) {
		retCode = -1;
		cJSON* objRes = cJSON_Parse(resBuffer);
		free(resBuffer);
		if (cJSON_HasObjectItem(objRes, "data"))
		{
			cJSON* objData = cJSON_GetObjectItem(objRes, "data");
			if (cJSON_IsObject(objData) && cJSON_HasObjectItem(objData, "vehicleInfo")) {
				cJSON* objVehicleInfo = cJSON_GetObjectItem(objData, "vehicleInfo");
				int activeStatus = cJSON_GetObjectItem(objVehicleInfo, "vehicleActiveStatus")->valueint;
				retCode = activeStatus;
			}
		}

		cJSON_Delete(objRes);
	}

	return retCode;
}


int get_jd_orderInfo_vehicleActiveStatus()
{
	if (DataCenter::m_callServerRecord.find(82) == DataCenter::m_callServerRecord.end()) {
		return -1;
	}

	string response = DataCenter::m_callServerRecord.at(82).response;
	int vehicleActiveStatus = -1;
	cJSON* objRoot = cJSON_Parse(response.c_str());
	if (NULL != objRoot) {
		if (cJSON_HasObjectItem(objRoot, "code")) {
			cJSON* objCode = cJSON_GetObjectItem(objRoot, "code");
			if (objCode->type == cJSON_Number && (objCode->valueint == 0 || objCode->valueint == 200)) {
				cJSON* objData = cJSON_GetObjectItem(objRoot, "data");

				//{
				//	"vehicleInfo":  {
				//		"vehicleSoftwareVer":   "6100000140 BE",
				//			"bodyColor" : "ME81",
				//			"modelId" : 61,
				//			"vehicleActiveStatus" : 2,
				//			"vehicleActiveTime" : "2023-07-04T09:19:43.000+00:00",
				//			"vid" : "082ce339e36405cf741374ee2587bd81",
				//			"interiorColor" : "MG01",
				//			"nickname" : "极越01",
				//			"vin" : "L6T79P2N3PP002429",
				//			"vehicleStatus" : 2
				//	}
				//}
				if (cJSON_HasObjectItem(objData, "vehicleActiveStatus")) {
					vehicleActiveStatus = cJSON_GetObjectItem(objData, "vehicleActiveStatus")->valueint;
				}
				else if (cJSON_HasObjectItem(objData, "vehicleInfo")) {
					cJSON* objVehicleInfo = cJSON_GetObjectItem(objData, "vehicleInfo");
					if (cJSON_HasObjectItem(objVehicleInfo, "vehicleActiveStatus"))
						vehicleActiveStatus = cJSON_GetObjectItem(objVehicleInfo, "vehicleActiveStatus")->valueint;
				}
			}

			cJSON_Delete(objRoot);
		}
	}
	return vehicleActiveStatus;
}

int get_jd_vehicleEnvChangeWorkFlowStatus(const char* vin, int carType, const char* userName, int env, int action)
{
	cJSON* objReq = cJSON_CreateObject();
	cJSON_AddStringToObject(objReq, "vin", vin);
	cJSON_AddStringToObject(objReq, "userName", userName);
	cJSON_AddStringToObject(objReq, "deviceSn", DataCenter::m_deviceSN.c_str());
	cJSON_AddNumberToObject(objReq, "carType", carType);
	cJSON_AddNumberToObject(objReq, "env", env);
	cJSON_AddNumberToObject(objReq, "action", action);

	char* reqBuffer = (char*)malloc(1024);
	cJSON_PrintPreallocated(objReq, reqBuffer, 1024, 0);
	cJSON_Delete(objReq);

	char* resBuffer = (char*)malloc(4096);
	int retCode = callServer(87, reqBuffer, resBuffer, 4096);
	free(reqBuffer);
	if (retCode > 0) {
		retCode = -1;
		cJSON* objRes = cJSON_Parse(resBuffer);
		free(resBuffer);
		if (cJSON_HasObjectItem(objRes, "data"))
		{
			cJSON* objData = cJSON_GetObjectItem(objRes, "data");
			if (cJSON_IsObject(objData) && cJSON_HasObjectItem(objData, "status")) {
				int status = cJSON_GetObjectItem(objData, "status")->valueint;
				retCode = status;
			}
		}

		cJSON_Delete(objRes);
	}

	return retCode;
}

int get_jd_orderInfo_vehicleEnvChangeWorkFlowStatus()
{
	if (DataCenter::m_callServerRecord.find(87) == DataCenter::m_callServerRecord.end()) {
		return -1;
	}

	string response = DataCenter::m_callServerRecord.at(87).response;
	int status = -1;
	cJSON* objRoot = cJSON_Parse(response.c_str());
	if (NULL != objRoot) {
		if (cJSON_HasObjectItem(objRoot, "code")) {
			cJSON* objCode = cJSON_GetObjectItem(objRoot, "code");
			if (objCode->type == cJSON_Number && (objCode->valueint == 0 || objCode->valueint == 200)) {
				cJSON* objData = cJSON_GetObjectItem(objRoot, "data");

				//{
				//	"vin": "DAGTEST0000000003",
				//	"status" : 5
				//}
				if (cJSON_HasObjectItem(objData, "status")) {
					status = cJSON_GetObjectItem(objData, "status")->valueint;
				}
			}

			cJSON_Delete(objRoot);
		}
	}
	return status;
}


int set_jd_calibration_uploadData(const char* vin, int carType, const char* ecuName, const char* ecuAddr, uint8_t* inParams, int inLen)
{
	cJSON* objReq = cJSON_CreateObject();

	string diagnosisId = "";
	if (map_diagnosisId.find(ecuName) != map_diagnosisId.end()) {
		diagnosisId = map_diagnosisId.at(ecuName);
	}

	char calibrationData[128] = { 0 };
	radix_array2Hex(inParams, inLen, calibrationData, 128);

	cJSON_AddStringToObject(objReq, "ecuType", ecuName);
	cJSON_AddStringToObject(objReq, "ecuAddress", ecuAddr);
	cJSON_AddStringToObject(objReq, "diagnosisId", diagnosisId.c_str());
	cJSON_AddStringToObject(objReq, "calibrationData", calibrationData);
	cJSON_AddStringToObject(objReq, "vin", vin);
	cJSON_AddStringToObject(objReq, "deviceSn", DataCenter::getInstance()->m_deviceSN.c_str());
	cJSON_AddNumberToObject(objReq, "carType", carType);

	char* reqBuffer = (char*)malloc(1024);
	cJSON_PrintPreallocated(objReq, reqBuffer, 1024, 0);
	cJSON_Delete(objReq);
	int retCode = callServer(74, reqBuffer, NULL, 0);
	free(reqBuffer);
	return retCode;
}

int get_jd_calibration_downloadData(const char* vin, int carType, const char* ecuName, const char* ecuAddr, uint8_t* outBuffer, uint32_t outBufferSize)
{
	cJSON* objReq = cJSON_CreateObject();

	cJSON_AddStringToObject(objReq, "ecuType", ecuName);
	cJSON_AddStringToObject(objReq, "ecuAddress", ecuAddr);
	cJSON_AddStringToObject(objReq, "vin", vin);
	cJSON_AddStringToObject(objReq, "deviceSn", DataCenter::getInstance()->m_deviceSN.c_str());
	cJSON_AddNumberToObject(objReq, "carType", carType);

	char* reqBuffer = (char*)malloc(1024);
	cJSON_PrintPreallocated(objReq, reqBuffer, 1024, 0);
	cJSON_Delete(objReq);

	char* resBuffer = (char*)malloc(40960);
	int retCode = callServer(75, reqBuffer, resBuffer, 40960);
	free(reqBuffer);
	if (retCode > 0) {
		retCode = -1;
		cJSON* objRes = cJSON_Parse(resBuffer);
		free(resBuffer);
		if (cJSON_HasObjectItem(objRes, "data"))
		{
			cJSON* objData = cJSON_GetObjectItem(objRes, "data");
			if (!cJSON_IsNull(objData))
			{
				string tempString = cJSON_GetObjectItem(objData, "calibrationData")->valuestring;
				map_diagnosisId[ecuName] = cJSON_GetObjectItem(objData, "diagnosisId")->valuestring;

				if (tempString.size() > outBufferSize) {
					retCode = -1;
				}
				else {
					retCode = radix_hex2Array(tempString.c_str(), tempString.length(), outBuffer, outBufferSize);
				}
			}
		}

		cJSON_Delete(objRes);
	}

	return retCode;
}

