// stdafx.cpp : ֻ������׼�����ļ���Դ�ļ�
// Demo.pch ����ΪԤ����ͷ
// stdafx.obj ������Ԥ����������Ϣ

#include "stdafx.h"

// TODO: �� STDAFX.H ��
// �����κ�����ĸ���ͷ�ļ����������ڴ��ļ�������

bool parse_key(std::string &RetValue, std::string strLine, TCHAR *lpszText)
{
	TCHAR szText[MAX_PATH] = {0};
	TCHAR szValue[MAX_PATH] = {0};
	// ȥ���ո�;
#if _MSC_VER > 1900
	strLine.erase(std::remove_if(strLine.begin(), strLine.end(), [](unsigned char x) {return std::isspace(x); }), strLine.end()); //C++17
#else
	for (std::string::iterator it = strLine.begin(); it != strLine.end();)	{
		!isspace(*it) ? it++ : it = it = strLine.erase(it);
	}
#endif

#if _MSC_VER >= 1200 && _MSC_VER < 1500 // VC6.0~8.0
	if ( 2 == sscanf(strLine.c_str(), _T("%[^=]=%s"), szText, MAX_PATH, szValue, MAX_PATH) )
#else
	if ( 2 == _stscanf_s(strLine.c_str(), _T("%[^=]=%s"), szText, MAX_PATH, szValue, MAX_PATH) )
#endif
	{
		if ( _tcsstr(szText, lpszText) )
		{
			RetValue = szValue;
			return true;
		}
	}

	return false;
}

// ����ʱ��;
// ��: 100ms 100m 100s
int pares_time_value(std::string strTime)
{
	int nTimes = 0;
#if _MSC_VER >= 1200 && _MSC_VER < 1500
	if ( strstr(strTime.c_str(), _T("ms")) || strstr(strTime.c_str(), _T("MS")))
	{
		nTimes = atol(strTime.c_str());
	}
	else if (strstr(strTime.c_str(), _T("s")) || strstr(strTime.c_str(), _T("S")))
	{
		nTimes = atol(strTime.c_str()) * 1000;
	}
	else if (strstr(strTime.c_str(), _T("m")) || strstr(strTime.c_str(), _T("M")))
	{
		nTimes = atol(strTime.c_str()) * 6000;
	}
	else
	{
		// ������λ��������,Ĭ��ms;
		nTimes = atol(strTime.c_str());
	}
#elif _MSC_VER >= 1500
	if ( _tcsstr(strTime.c_str(), _T("ms")) || _tcsstr(strTime.c_str(), _T("MS")))
	{
		nTimes = _tstol(strTime.c_str());
	}
	else if (_tcsstr(strTime.c_str(), _T("s")) || _tcsstr(strTime.c_str(), _T("S")))
	{
		nTimes = _tstol(strTime.c_str()) * 1000;
	}
	else if (_tcsstr(strTime.c_str(), _T("m")) || _tcsstr(strTime.c_str(), _T("M")))
	{
		nTimes = _tstol(strTime.c_str()) * 6000;
	}
	else
	{
		// ������λ��������,Ĭ��ms;
		nTimes = _tstol(strTime.c_str());
	}
#endif

	return nTimes;
}

int parse_cmd_param_from_file(TCHAR *file_name, std::vector<CommandParam> &vtCommandParams)
{
	TCHAR buf[MAX_PATH] = {0};
	TCHAR name[MAX_PATH] = {0};
	TCHAR option[MAX_PATH] = {0};
	TCHAR head[MAX_PATH] = {0};
	TCHAR code[MAX_PATH] = {0};
	TCHAR param[MAX_PATH] = {0};
	TCHAR multicode[MAX_PATH] = {0};
	TCHAR cmd_wait_time[MAX_PATH] = {0};
	TCHAR read_wait_time[MAX_PATH] = {0};

	int ret = -1;
	FILE *fp = NULL;

	if(!file_name || file_name[0] == '\0' )
		return ret;

	fp = fopen(file_name, "r");
	if(!fp)
		goto EXIT;

	while((fgets((char*)buf, MAX_PATH, fp) != NULL)) {
		int tmp_len = 0;
		unsigned short keycode = 0;
		unsigned int protocol = 0;
		unsigned int scancode = 0;

		tmp_len = _tcslen(buf);
		if(tmp_len >= 1) {
			if (buf[tmp_len - 1] == '\r' || buf[tmp_len - 1] == '\n')
				buf[tmp_len - 1] = 0;
			if(tmp_len >= 2) {
				if(buf[tmp_len - 2] == '\r' || buf[tmp_len - 2] == '\n')
					buf[tmp_len - 2] = 0;
			} 
		}

#if _MSC_VER >= 1200 && _MSC_VER < 1500 // VC6.0~8.0 
		if ( sscanf(buf, "%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^;]", name, option, head, code, param, multicode, read_wait_time, cmd_wait_time) == 8)
#elif _MSC_VER >= 1500 
		//if ( _stscanf_s(buf, "%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^;]", name, MAX_PATH, option, MAX_PATH, head, MAX_PATH, code, MAX_PATH, param, MAX_PATH, multicode, MAX_PATH, read_wait_time, MAX_PATH, cmd_wait_time, MAX_PATH) == 8) // �ȼ�����;
		if ( _stscanf_s(buf, "%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%s", name, MAX_PATH, option, MAX_PATH, head, MAX_PATH, code, MAX_PATH, param, MAX_PATH, multicode, MAX_PATH, read_wait_time, MAX_PATH, cmd_wait_time, MAX_PATH) == 8)
#endif
		{
			CommandParam cp;
			parse_key(cp.name, name, _T("Name"));
			parse_key(cp.head, head, _T("HeadCode"));
			parse_key(cp.code, code, _T("Command"));
			parse_key(cp.param, param, _T("CMDParam"));

			std::string value;
			parse_key(value, option, _T("Option"));
			if ( !_tcsicmp(value.c_str(), _T("None")) )
				cp.nOption = 0;
			else if (!_tcsicmp(value.c_str(), _T("Get")))
				cp.nOption = 1;
			else if (!_tcsicmp(value.c_str(), _T("Set")))
				cp.nOption = 2;

			parse_key(value, multicode, _T("MultiParams"));
			cp.bMulticode = !_tcsicmp(value.c_str(), _T("true")) ? true : false;

			parse_key(value, read_wait_time, _T("ReadWaitTime"));
			cp.read_wait_time = pares_time_value(value.c_str());

			parse_key(value, cmd_wait_time, _T("CMDWaitTime"));
			cp.cmd_wait_time = pares_time_value(value.c_str());

			vtCommandParams.push_back(cp);
		}
	}

	ret = 0;
EXIT:
	if(fp)
		fclose(fp);
	return ret;
}

unsigned char TwoHexCharToInteger(char high, char low)
{
	std::string str = "0123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
	if ( str.find_first_of(high) == std::string::npos || str.find_first_of(low) == std::string::npos )
	{
		return 0;
	}

	char Numb1 = high >= 'A' ? (toupper(high) - '0' - 7) * 16 : (high - '0') * 16;
	char Numb2 = low >= 'A' ? (toupper(low) - '0' - 7) : (low - '0');

	return (Numb1 + Numb2);
}

const unsigned short CRC16_TABLE[16] = {
	0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
	0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF
};

unsigned short CRC16Calculate(byte *pBuffer, unsigned int wordLength)
{
	byte byteTemp(0);
	unsigned short wordCRC(0);

	wordCRC = 0xFFFF;
	while (wordLength--) {
		byteTemp = (byte)(wordCRC >> 0x0C);
		wordCRC <<= 4;
		wordCRC ^= CRC16_TABLE[byteTemp ^ ((*pBuffer) >> 0x04)];
		byteTemp = (byte)(wordCRC >> 0x0C);
		wordCRC <<= 4;
		wordCRC ^= CRC16_TABLE[byteTemp ^ ((*pBuffer) & 0x0F)];
		pBuffer++;
	}

	return wordCRC;
}

std::string HexStringToBytes(std::string strHex, const int &len /* = 3 */)
{
	byte value = 0;
	std::string strBytes;
	int nSize = strHex.size();
	for (int i = 0; i < nSize; i += len)
	{
#if _MSC_VER >=1200 && _MSC_VER < 1500
		strBytes.append((char)TwoHexCharToInteger(strHex[i], strHex[i + 1]),1);
#elif _MSC_VER >=1500
		strBytes.push_back((char)TwoHexCharToInteger(strHex[i], strHex[i + 1]));
#endif
	}

	return strBytes;
}

std::string BytesToHexString(const unsigned char *pbuffer, int nLen, char chSpace)
{
	std::string hex;
	char szhex[5] = {0};
	for (int i = 0; i < nLen; i++)
	{
		memset(szhex, 0, 5);
#if _MSC_VER >= 1200 && _MSC_VER < 1500
		sprintf(szhex, "%02X%c", pbuffer[i], chSpace);
#elif _MSC_VER >= 1500
		_stprintf_s(szhex, "%02X%c", pbuffer[i], chSpace);
#endif
		hex.append(szhex);
	}

	return hex.substr(0, hex.size() - 1);
}

std::string BytesToHexString(const unsigned char *pbuffer, int nLen)
{
	std::string hex;
	char szhex[5] = {0};
	for (int i = 0; i < nLen; i++)
	{
		memset(szhex, 0, 5);

#if _MSC_VER >= 1200 && _MSC_VER < 1500
		sprintf(szhex, "%02X", pbuffer[i]);
#elif _MSC_VER >= 1500
		_stprintf_s(szhex, "%02X", pbuffer[i]);
#endif
		hex.append(szhex);
	}

	return hex;
}

BOOL IsValidString(LPCTSTR lpszString)
{
	if (lpszString == NULL)
		return FALSE;

	do {
		// ASCII����ʾ���ַ�;
		if (*lpszString < 32 || *lpszString > 126) {
			return FALSE;
		}
	} while (*++lpszString);

	return TRUE;
}

// ȥ���ո�;
std::string &trim(std::string &str)
{
#if 0
	int nIndex = 0;
	while ((nIndex = str.find_first_of(' ')) != std::string::npos)
		str.erase(nIndex, 1);

	return str;
#endif

#if _MSC_VER >= 1200 && _MSC_VER < 1600
	for (std::string::iterator it = str.begin(); it != str.end();)	{
		!isspace(*it) ? it++ : it = it = str.erase(it);
	}
#elif _MSC_VER >= 1600
	str.erase(std::remove_if(str.begin(), str.end(), [](unsigned char x) {return std::isspace(x); }), str.end()); //C++17
#endif
	return str;
}

std::string PackingCommand(CommandParam &cmdPara, std::string data, const int &dataLen)
{
	std::string command;
	// ����ͷ��ʶλ;
	command.append(HexStringToBytes(cmdPara.head, 2).c_str(), cmdPara.head.size() / 2);
	// ������;
	command.append(HexStringToBytes(cmdPara.code, 2).c_str(), cmdPara.code.size() / 2);
	// ���������;
	command.append(HexStringToBytes(cmdPara.param, 2).c_str(), cmdPara.param.size() / 2);
	// ���ӵ�����;
	if ( dataLen > 0)
		command.append(data.c_str(), dataLen);

	int len(0);
	// ���ȣ�����1�ֽڱ�ʾ������255��2�ֽڱ�ʾ;
	byte szlen[2] = {0};
	//if ((byte)command[1] == 0xFE)
	//if ( cmdPara.head.size() >= 4 && cmdPara.head.find("FE", 2, 2) != std::string::npos )
	if ( _tcsicmp(_T("AAFE"), cmdPara.head.c_str()) == 0 )
	{// ���ȳ���255,��Ҫ2�ֽڱ�ʾ;
		len = command.size() + 4;	// 2λcrc + 2λ����;
		szlen[0] = (len >> 8) & 0xFF;
		szlen[1] = len & 0xFF;
		command.insert(2, (char *)szlen, 2);
	} else {
		// 2λcrc + 1λ����;
		len = command.size() + 3;	
		//if ( _tcsicmp(cmdPara.code.c_str(), "99 00") == 0 )
		//	len -= 2;

		if ( len > 255 ) {// ���ȳ���255����һ��ռλ��;
			++len;
			szlen[0] = (len >> 8) & 0xFF;
			szlen[1] = len  & 0xFF;
			command.insert(1, (char *)szlen, 2);
		} else {
			szlen[0] = len & 0xFF;
			command.insert(1, (char *)szlen, 1);
		}
	}

	// crc��;
	byte szcrc[2] = {0};
	WORD usCRCValue = CRC16Calculate((byte *)command.c_str(), command.size()); // �����0�Ͽ���Σ��;
	//WORD usCRCValue = CRC16Calculate((byte *)command.c_str(), len - 2);
	szcrc[0] = (usCRCValue >> 8) & 0xFF;
	szcrc[1] = usCRCValue & 0xFF;
	command.append((char *)szcrc, 2);

	return command;
}