﻿#include <stdlib.h>
#include <string.h>
#include "cJSON.h"
#include "jidu_client.h"
#include "tracer.h"
#include "algorithm.h"
#include "otxproxy.h"
#include "Dateformat.h"
#include "MyStringUtils.h"
#include <mutex>


static std::mutex mLock;
using namespace std;
int loadFirst() {
	char tempBuffer[128] = { 0 };
	sprintf(tempBuffer, "%s %s", __DATE__, __TIME__);
	Tracer::logger("@compiled", tempBuffer);

	return 0;
}
static int version = loadFirst();

int jsonValue(char* jsonString, char* key, char* outBuffer, unsigned int outBufferSize) {
	if (key == nullptr || strlen(key) == 0) {
		return -1;
	}

	cJSON* objRoot = cJSON_Parse(jsonString);
	if (objRoot == nullptr) {
		cJSON_Delete(objRoot);
		return -4;
	}

	std::vector<std::string> levelKeys;
	std::string keyStr(key);
	size_t prevPos = 0, pos = 0;
	while ((pos = keyStr.find('.', prevPos)) != std::string::npos) {
		levelKeys.push_back(keyStr.substr(prevPos, pos - prevPos));
		prevPos = pos + 1;
	}
	levelKeys.push_back(keyStr.substr(prevPos));

	cJSON* objLevel = objRoot;
	for (const auto& levelKey : levelKeys) {
		size_t pos = levelKey.find('[');
		std::string tempKey = levelKey.substr(0, pos);

		if (pos != std::string::npos) {
			int index = std::stoi(levelKey.substr(pos + 1, levelKey.find(']', pos) - pos - 1));
			objLevel = cJSON_GetObjectItemCaseSensitive(objLevel, tempKey.c_str());
			if (objLevel == nullptr || !cJSON_IsArray(objLevel)) {
				cJSON_Delete(objRoot);
				return -2;
			}

			if (index >= cJSON_GetArraySize(objLevel)) {
				cJSON_Delete(objRoot);
				return -1;
			}

			objLevel = cJSON_GetArrayItem(objLevel, index);
		}
		else {
			objLevel = cJSON_GetObjectItemCaseSensitive(objLevel, tempKey.c_str());
		}

		if (objLevel == nullptr) {
			cJSON_Delete(objRoot);
			return -1;
		}
	}

	if (cJSON_IsString(objLevel)) {
		size_t len = strlen(objLevel->valuestring);
		if (outBufferSize < len + 1) {
			cJSON_Delete(objRoot);
			return -1;
		}
		strcpy(outBuffer, objLevel->valuestring);
	}
	else {
		char* temp = cJSON_Print(objLevel);
		size_t len = strlen(temp);
		if (outBufferSize < len + 1) {
			cJSON_free(temp);
			cJSON_Delete(objRoot);
			return -1;
		}
		strcpy(outBuffer, temp);
		cJSON_free(temp);
	}

	cJSON_Delete(objRoot);
	return (int)strlen(outBuffer);
}

int jsonNum(char* jsonString, char* key, char* outBuffer, unsigned int outBufferSize)
{
	memset(outBuffer, 0, outBufferSize);

	if (key == NULL || key == "") {
		Tracer::error("无效的参数", "key");
		return -1;
	}
	cJSON* objRoot = cJSON_Parse(jsonString);
	if (NULL == objRoot)
	{
		Tracer::error("couldn't parsed to json", jsonString);
		cJSON_Delete(objRoot);
		return -4;
	}

	//TODO 通过字符串[.]分割JSON层级
	string levelKey[10]; size_t level = 0;
	char* strc = new char[strlen(key) + 1];
	strcpy(strc, key);
	char* temp = strtok(strc, ".");
	for (int i = 0; i < 10; i++, level++)
	{
		if (temp == NULL) {
			break;
		}
		levelKey[i] = temp;
		temp = strtok(NULL, ".");
	}
	delete[] strc;

	//TODO 每一层级JSON数组特殊处理
	cJSON* objLevel = objRoot;
	for (unsigned int i = 0; i < level; i++)
	{
		int pos = (int)levelKey[i].find("[", 0);
		string tempKey = levelKey[i].substr(0, pos);

		if (pos >= 0) {
			int index = atoi(levelKey[i].substr(pos + 1).c_str());
			objLevel = cJSON_GetObjectItem(objLevel, tempKey.c_str());
			if (objLevel == NULL) {
				Tracer::error("no this key in your json", tempKey.c_str());
				cJSON_Delete(objRoot);
				return -2;
			}

			int arraySize = cJSON_GetArraySize(objLevel);
			if (index + 1 > arraySize) {
				cJSON_Delete(objRoot);
				return -1;
			}
			objLevel = cJSON_GetArrayItem(objLevel, index);
		}
		else
		{
			objLevel = cJSON_GetObjectItem(objLevel, tempKey.c_str());
		}
	}

	if (cJSON_IsNumber(objLevel)) {
		int value = (int)cJSON_GetNumberValue(objLevel);
		cJSON_Delete(objRoot);

		string tempString = std::to_string(value);
		if (outBufferSize > tempString.length()) {
			memcpy(outBuffer, tempString.c_str(), tempString.length());
			return tempString.size();
		}
	}

	Tracer::error("json type", "not number");
	return -1;
}

int addJsonKey(char* rawString, char* key, char* value, char* outBuffer, unsigned int outBufferSize)
{
	//memset(outBuffer, 0, outBufferSize);
	cJSON* objRoot;
	if (rawString != NULL && strlen(rawString) > 0) {
		objRoot = cJSON_Parse(rawString);
		if (objRoot == NULL) {
			Tracer::info("raw", rawString);
			Tracer::error(__FUNCTION__, "your string cann't parsed to json");
			cJSON_Delete(objRoot);
			return -1;
		}
	}
	else {
		objRoot = cJSON_CreateObject();
	}

	//TODO 通过字符串[.]分割JSON层级
	string levelKey[10]; size_t level = 0;
	char* strc = new char[strlen(key) + 1];
	strcpy(strc, key);
	char* temp = strtok(strc, ".");
	for (int i = 0; i < 10; i++)
	{
		if (temp == NULL) {
			break;
		}
		levelKey[i] = temp;
		temp = strtok(NULL, ".");
		level++;
	}
	delete[] strc;

	//TODO 每一层级JSON数组特殊处理
	//TODO addJsonKey(obj, (char*)"testData[0].testItemList[0].testItemName", (char*)"Mode_Control", obj, 4096);
	cJSON* objLevel = objRoot;
	for (unsigned int i = 0; i < level; i++)
	{
		int pos = (int)levelKey[i].find("[", 0);
		string tempKey = levelKey[i].substr(0, pos);

		if (pos >= 0) {
			int index = atoi(levelKey[i].substr(pos + 1).c_str());
			if (!cJSON_HasObjectItem(objLevel, tempKey.c_str())) {
				cJSON_AddArrayToObject(objLevel, tempKey.c_str());
				objLevel = cJSON_GetObjectItem(objLevel, tempKey.c_str());
				cJSON_AddItemToArray(objLevel, cJSON_CreateObject());
				objLevel = cJSON_GetArrayItem(objLevel, index);
			}
			else {
				objLevel = cJSON_GetObjectItem(objLevel, tempKey.c_str());
				int arraySize = cJSON_GetArraySize(objLevel);
				for (int i = arraySize; i <= index; i++) {
					cJSON_AddItemToArray(objLevel, cJSON_CreateObject());
				}
				objLevel = cJSON_GetArrayItem(objLevel, index);
			}
		}
		else if (i < level - 1)
		{
			if (!cJSON_HasObjectItem(objLevel, tempKey.c_str())) {
				cJSON_AddObjectToObject(objLevel, tempKey.c_str());
			}

			objLevel = cJSON_GetObjectItem(objLevel, tempKey.c_str());
		}
		else {
			cJSON_AddStringToObject(objLevel, tempKey.c_str(), value);
		}
	}

	char* tempBuff = cJSON_PrintBuffered(objRoot, 40960, false);
	size_t len = strlen(tempBuff);
	cJSON_Delete(objRoot);

	if (outBufferSize < len) {
		cJSON_free(tempBuff);
		return -1;
	}
	else {
		memcpy(outBuffer, tempBuff, len);
		cJSON_free(tempBuff);
		return (int)len;
	}

	return -1;
}

int addJsonNum(char* rawString, char* key, long value, char* outBuffer, unsigned int outBufferSize)
{
	//memset(outBuffer, 0, outBufferSize);
	cJSON* objRoot;
	if (rawString != NULL && strlen(rawString) > 0) {
		objRoot = cJSON_Parse(rawString);
		if (objRoot == NULL) {
			Tracer::info("raw", rawString);
			Tracer::error(__FUNCTION__, "your string cann't parsed to json");
			cJSON_Delete(objRoot);
			return -1;
		}
	}
	else {
		objRoot = cJSON_CreateObject();
	}

	//TODO 通过字符串[.]分割JSON层级
	string levelKey[10]; size_t level = 0;
	char* strc = new char[strlen(key) + 1];
	strcpy(strc, key);
	char* temp = strtok(strc, ".");
	for (int i = 0; i < 10; i++)
	{
		if (temp == NULL) {
			break;
		}
		levelKey[i] = temp;
		temp = strtok(NULL, ".");
		level++;
	}
	delete[] strc;

	//TODO 每一层级JSON数组特殊处理
	cJSON* objLevel = objRoot;
	for (unsigned int i = 0; i < level; i++)
	{
		int pos = (int)levelKey[i].find("[", 0);
		string tempKey = levelKey[i].substr(0, pos);

		if (pos >= 0) {
			int index = atoi(levelKey[i].substr(pos + 1).c_str());
			if (!cJSON_HasObjectItem(objLevel, tempKey.c_str())) {
				cJSON_AddArrayToObject(objLevel, tempKey.c_str());
				objLevel = cJSON_GetObjectItem(objLevel, tempKey.c_str());
				cJSON_AddItemToArray(objLevel, cJSON_CreateObject());
				objLevel = cJSON_GetArrayItem(objLevel, index);
			}
			else {
				objLevel = cJSON_GetObjectItem(objLevel, tempKey.c_str());
				int arraySize = cJSON_GetArraySize(objLevel);
				for (int i = arraySize; i <= index; i++) {
					cJSON_AddItemToArray(objLevel, cJSON_CreateObject());
				}
				objLevel = cJSON_GetArrayItem(objLevel, index);
			}
		}
		else if (i < level - 1)
		{
			if (!cJSON_HasObjectItem(objLevel, tempKey.c_str())) {
				cJSON_AddObjectToObject(objLevel, tempKey.c_str());
			}

			objLevel = cJSON_GetObjectItem(objLevel, tempKey.c_str());
		}
		else {
			cJSON_AddNumberToObject(objLevel, tempKey.c_str(), value);
		}
	}

	temp = cJSON_PrintBuffered(objRoot, 4096, 0);
	size_t len = strlen(temp);
	cJSON_Delete(objRoot);

	if (outBufferSize < len) {
		cJSON_free(temp);
		return -1;
	}
	else {
		memcpy(outBuffer, temp, len);
		cJSON_free(temp);
		return (int)len;
	}
}

int jsonType(char* jsonString)
{
	cJSON* obj = cJSON_Parse(jsonString);
	int ret = 0;
	if (obj == NULL) {
		cJSON_Delete(obj);
		return -1;
	}
	else if (cJSON_IsNull(obj)) {
		ret = 2;
	}
	else if (cJSON_IsBool(obj)) {
		ret = 1;
	}
	else if (cJSON_IsObject(obj)) {
		ret = 6;
	}
	else if (cJSON_IsArray(obj)) {
		ret = 5;
	}
	else if (cJSON_IsString(obj)) {
		ret = 4;
	}
	else if (cJSON_IsNumber(obj)) {
		ret = 3;
	}

	cJSON_Delete(obj);
	return ret;
}

int jsonArraySize(char* jsonString)
{
	cJSON* obj = cJSON_Parse(jsonString);
	if (obj == NULL) {
		cJSON_Delete(obj);
		return -1;
	}
	int len = 0;
	if (cJSON_IsArray(obj)) {
		len = cJSON_GetArraySize(obj);
		cJSON_Delete(obj);
		return len;
	}

	cJSON_Delete(obj);
	return len;
}

int jsonArrayValue(char* jsonString, int index, char* outBuffer, unsigned int outBufferSize)
{
	memset(outBuffer, 0, outBufferSize);
	cJSON* objRoot = cJSON_Parse(jsonString);
	if (objRoot == NULL) {
		Tracer::error(__FUNCTION__, "cann't parsed to json obj");
		cJSON_Delete(objRoot);
		return -1;
	}
	if (cJSON_IsArray(objRoot)) {
		if (cJSON_GetArraySize(objRoot) <= index) {
			Tracer::error(__FUNCTION__, "index must less than the size of jsonArray");
			cJSON_Delete(objRoot);
			return -2;
		}

		cJSON* tempObj = cJSON_GetArrayItem(objRoot, index);
		if (cJSON_IsString(tempObj)) {
			char* temp = cJSON_GetStringValue(tempObj);
			size_t len = strlen(temp);
			if (len > outBufferSize) {
				Tracer::error(__FUNCTION__, "your buffer isn't enough to recv the res.");
				cJSON_Delete(objRoot);
				return -2;
			}
			memcpy(outBuffer, temp, len);
			cJSON_Delete(objRoot);
			return (int)len;
		}
		else if (cJSON_IsObject(tempObj)) {
			char* temp = cJSON_PrintUnformatted(tempObj);
			size_t len = strlen(temp);
			if (len > outBufferSize) {
				Tracer::error(__FUNCTION__, "your buffer isn't enough to recv the res.");
				cJSON_Delete(objRoot);
				return -2;
			}
			memcpy(outBuffer, temp, len);
			cJSON_free(temp);
			cJSON_Delete(objRoot);
			return (int)len;
		}
		else if (cJSON_IsNull(tempObj)) {
			memcpy(outBuffer, "null", 4);
			cJSON_Delete(objRoot);
			return 0;
		}

		cJSON_Delete(objRoot);
	}
	else {
		Tracer::error(__FUNCTION__, "jsonString is not array");
		cJSON_Delete(objRoot);
		return -3;
	}

	return -1;
}

int strContains(char* str1, char* str2)
{
	if (str1 == NULL || str2 == NULL) {
		return -1;
	}

	char* temp = strstr(str1, str2);
	if (temp == NULL) {
		return -1;
	}

	return (int)(strlen(str1) - strlen(temp));
}

int isArabDigital(const char* str)
{
	while (*str) {
		if (!isdigit((unsigned char)*str)) {
			return 0;
		}
		str++;
	}
	return 1;
}

int isAlphanumeric(const char* str)
{
	while (*str) {
		if (!isalnum((unsigned char)*str)) {
			return 0;
		}
		str++;
	}

	return 1;
}

int isNumericWithSignAndDot(const char* str) {
	bool hasSign = false;
	bool hasDot = false;

	if (str == NULL || strlen(str) == 0) {
		return false;
	}

	for (int i = 0; str[i] != '\0'; i++) {
		if (isdigit(str[i])) {
			continue; // 是数字，继续下一个字符  
		}
		else if (str[i] == '-') {
			if (hasSign || i != 0) {
				return false; // 负号只能有一个，且必须在开头  
			}
			hasSign = true;
		}
		else if (str[i] == '.') {
			if (hasDot) {
				return false; // 小数点只能有一个  
			}
			hasDot = true;
		}
		else {
			return false; // 不是数字、负号或小数点，返回false  
		}
	}

	return true; // 所有字符都符合要求，返回true  
}

int get_currentTimeString(char* outBuffer, unsigned int outBufferSize, bool ms)
{
	memset(outBuffer, 0, outBufferSize);
	Dateformat dateformat;
	string tempString = ms ? dateformat.currentTimeString() : dateformat.currentTimeString("yyyy-MM-dd HH:mm:ss");
	if (outBufferSize > tempString.size())
	{
		memcpy(outBuffer, tempString.c_str(), tempString.size());
		return (int)tempString.size();
	}
	return -1;
}

int get_currentTimeStampString(char* outBuffer, unsigned int outBufferSize, bool ms)
{
	memset(outBuffer, 0, outBufferSize);
	Dateformat dateformat;
	uint64_t ts = dateformat.getTimestamp();
	ts = ms ? ts : ts / 1000;

	if (outBufferSize > 15)
	{
		sprintf(outBuffer, "%llu", ts);
		return (int)strlen(outBuffer);
	}
	return -1;
}

uint64_t get_currentTimeStamp()
{
	Dateformat dateformat;
	return dateformat.getTimestamp();
}

bool convert_secondsToString(uint32_t sec, char* hourBuffer, int hourSize, char* minuteBuffer, int minSize, char* secondBuffer, int secSize)
{
	std::lock_guard<std::mutex> lock(mLock);

	memset(hourBuffer, 0, hourSize);
	memset(minuteBuffer, 0, minSize);
	memset(secondBuffer, 0, secSize);

	int hours = (int)(sec / 3600);
	int minutes = (int)((sec % 3600) / 60);
	int seconds = (int)((sec % 60));

	string hourString = to_string(hours);
	string minString = to_string(minutes);
	string secString = to_string(seconds);

	if (hourSize < hourString.size() || minSize < minString.size() || secSize < secString.size()) {
		return false;
	}

	memcpy(hourBuffer, hourString.c_str(), hourString.size());
	memcpy(minuteBuffer, minString.c_str(), minString.size());
	memcpy(secondBuffer, secString.c_str(), secString.size());

	return true;
}
int32_t get_currentTimeZone()
{
	int32_t zone = 8;

	long offSeconds = 0;
	_get_timezone(&offSeconds);

	zone = offSeconds / 60 / 60;

	return zone;
}

void delay(uint32_t ms)
{
	std::this_thread::sleep_for(std::chrono::milliseconds(ms));
}

void logger(char* tag, char* msg)
{
	if (tag == NULL)tag = "";
	if (msg == NULL)msg = "";

	//TODO 如果tag是以"[]"包围的，则提升为level
	if (MyStringUtils::startWith(tag, "[") && MyStringUtils::endWith(tag, "]"))
		Tracer::logger("", msg, tag);
	else
		Tracer::logger(tag, msg);
}

void logger_num(char* tag, int number)
{
	if (MyStringUtils::startWith(tag, "[") && MyStringUtils::endWith(tag, "]"))
		Tracer::logger("", to_string(number), tag);
	else
		Tracer::logger(tag, to_string(number));
}

void logger_hex(char* tag, unsigned char* u8Buffer, int len)
{
	if (len <= 4096) {

		char* tempBuff = (char*)malloc(2 * len + 1);
		if (tempBuff != NULL) {
			for (int i = 0; i < len; i++)
			{
				if (len > 6 && (i > 3 && i < len - 3)) {
					sprintf(tempBuff + 2 * i, "%s", "**");
				}
				else {
					sprintf(tempBuff + 2 * i, "%02X", u8Buffer[i]);
				}
			}

			Tracer::logger(tag, tempBuff);
			free(tempBuff);
		}
	}
}

void setLoggerLevel(int level)
{
	Tracer::setTraceLevel(level);
}
