#include <time.h>
#include "global.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

wstring stows(string scText)
{
	int iSize = MultiByteToWideChar(CP_ACP, 0, scText.c_str(), -1, 0, 0);
	wchar_t *wszText = new wchar_t[iSize];
	MultiByteToWideChar(CP_ACP, 0, scText.c_str(), -1, wszText, iSize);
	wstring wscRet = wszText;
	delete[] wszText;
	return wscRet;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

string wstos(wstring wscText)
{
	uint iLen = (uint)wscText.length() + 1;
	char *szBuf = new char[iLen];
	WideCharToMultiByte(CP_ACP, 0, wscText.c_str(), -1, szBuf, iLen, 0, 0);
	string scRet = szBuf;
	delete[] szBuf;
	return scRet;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

string itos(int i)
{
	char szBuf[16];
	sprintf(szBuf, "%d", i);
	return szBuf;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

wstring ToLower(wstring wscStr)
{
	for(uint i = 0; (i < wscStr.length()); i++)
		wscStr[i] = towlower(wscStr[i]);

	return wscStr;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

string ToLower(string scStr)
{
	for(uint i = 0; (i < scStr.length()); i++)
		scStr[i] = tolower(scStr[i]);

	return scStr;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

int ToInt(wstring wscStr)
{
	return _wtoi(wscStr.c_str());
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

float ToFloat(wstring wscStr)
{
	return (float)atof(wstos(wscStr).c_str());
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 999.999.999

wstring ToMoneyStr(int iCash)
{
	int iMillions = iCash / 1000000;
	int iThousands = (iCash % 1000000) / 1000;
	int iRest = (iCash % 1000);
	wchar_t wszBuf[32];
	
	if(iMillions)
		swprintf(wszBuf, L"%d.%.3d.%.3d", iMillions, iThousands, iRest);
	else if(iThousands)
		swprintf(wszBuf, L"%d.%.3d", iThousands, iRest);
	else
		swprintf(wszBuf, L"%d", iRest);

	return wszBuf;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

string IniGetS(string scFile, string scApp, string scKey, string scDefault)
{
	char szRet[2048];
	GetPrivateProfileString(scApp.c_str(), scKey.c_str(), scDefault.c_str(), szRet, sizeof(szRet), scFile.c_str());
	return szRet;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

int IniGetI(string scFile, string scApp, string scKey, int iDefault)
{
	return GetPrivateProfileInt(scApp.c_str(), scKey.c_str(), iDefault, scFile.c_str());
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

float IniGetF(string scFile, string scApp, string scKey, float fDefault)
{
	char szRet[2048];
	char szDefault[16];
	sprintf(szDefault, "%f", fDefault);
	GetPrivateProfileString(scApp.c_str(), scKey.c_str(), szDefault, szRet, sizeof(szRet), scFile.c_str());
	return (float)atof(szRet);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

bool IniGetB(string scFile, string scApp, string scKey, bool bDefault)
{
	return ToLower(IniGetS(scFile, scApp, scKey, bDefault ? "yes" : "no")).compare("yes") == 0 ? true : false;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

void IniWrite(string scFile, string scApp, string scKey, string scValue)
{
	WritePrivateProfileString(scApp.c_str(), scKey.c_str(), scValue.c_str(), scFile.c_str());
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

void IniWriteW(string scFile, string scApp, string scKey, wstring wscValue)
{
	string scValue = "";
	for(uint i = 0; (i < wscValue.length()); i++)
	{
		char cHiByte = wscValue[i] >> 8;
		char cLoByte = wscValue[i] & 0xFF;
		char szBuf[8];
		sprintf(szBuf, "%02X%02X", ((uint)cHiByte) & 0xFF, ((uint)cLoByte) & 0xFF);
		scValue += szBuf;
	}
	WritePrivateProfileString(scApp.c_str(), scKey.c_str(), scValue.c_str(), scFile.c_str());
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

wstring IniGetWS(string scFile, string scApp, string scKey, wstring wscDefault)
{
	char szRet[2048];
	GetPrivateProfileString(scApp.c_str(), scKey.c_str(), "", szRet, sizeof(szRet), scFile.c_str());
	string scValue = szRet;
	if(!scValue.length())
		return wscDefault;

	wstring wscValue = L"";
	long lHiByte;
	long lLoByte;
	while(sscanf(scValue.c_str(), "%02X%02X", &lHiByte, &lLoByte) == 2)
	{
		scValue = scValue.substr(4);
		wchar_t wChar = (wchar_t)((lHiByte << 8) | lLoByte);
		wscValue.append(1, wChar);
	}

	return wscValue;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

void IniDelSection(string scFile, string scApp)
{
	WritePrivateProfileSection(scApp.c_str(), "", scFile.c_str());
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

void IniGetSection(string scFile, string scApp, list<INISECTIONVALUE> &lstValues)
{
	lstValues.clear();
	char szBuf[0xFFFF];
	GetPrivateProfileSection(scApp.c_str(), szBuf, sizeof(szBuf), scFile.c_str());
	char *szNext = szBuf;
	while(strlen(szNext) > 0)
	{
		INISECTIONVALUE isv;
		char szKey[0xFFFF] = "";
		char szValue[0xFFFF] = "";
		sscanf(szNext, "%[^=]=%[^\n]", szKey, szValue);
		isv.scKey = szKey;
		isv.scValue = szValue;
		lstValues.push_back(isv);

		szNext += strlen(szNext) + 1;
	}
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

wstring XMLText(wstring wscText)
{
	wstring wscRet;
	for(uint i = 0; (i < wscText.length()); i++)
	{
		if(wscText[i] == '<')
			wscRet.append(L"&#60;");
		else if(wscText[i] == '>')
			wscRet.append(L"&#62;");
		else if(wscText[i] == '&')
			wscRet.append(L"&#38;");
		else
			wscRet.append(1, wscText[i]);
	}

	return wscRet;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

void WriteProcMem(void *pAddress, void *pMem, int iSize)
{
	HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
	DWORD dwOld;
	VirtualProtectEx(hProc, pAddress, iSize, PAGE_EXECUTE_READWRITE, &dwOld);
	WriteProcessMemory(hProc, pAddress, pMem, iSize, 0);
	CloseHandle(hProc);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

void ReadProcMem(void *pAddress, void *pMem, int iSize)
{
	HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
	DWORD dwOld;
	VirtualProtectEx(hProc, pAddress, iSize, PAGE_EXECUTE_READWRITE, &dwOld);
	ReadProcessMemory(hProc, pAddress, pMem, iSize, 0);
	CloseHandle(hProc);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

void AddLog(const char *szString, ...)
{
	char szBufString[1024];
	va_list marker;
	va_start(marker, szString);
	_vsnprintf(szBufString, sizeof(szBufString)-1, szString, marker);

	char szBuf[64];
	time_t tNow = time(0);
	struct tm *t = localtime(&tNow);
	strftime(szBuf, sizeof(szBuf), "%d.%m.%Y %H:%M:%S", t);
	fprintf(fLog, "[%s] %s\n", szBuf, szBufString);
	fflush(fLog);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

wstring GetParam(wstring wscLine, wchar_t wcSplitChar, uint iPos)
{
	uint i = 0, j = 0;
 
	wstring wscResult = L"";
	for(i = 0, j = 0; (i <= iPos) && (j < wscLine.length()); j++)
	{
		if(wscLine[j] == wcSplitChar)
		{
			while(((j + 1) < wscLine.length()) && (wscLine[j+1] == wcSplitChar))
				j++; // skip "whitechar"

			i++;
			continue;
		}
 
		if(i == iPos)
			wscResult += wscLine[j];
	}
 
	return wscResult;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

wstring ReplaceStr(wstring wscSource, wstring wscSearchFor, wstring wscReplaceWith)
{
	uint lPos, sPos = 0;

	while((lPos = (uint)wscSource.find(wscSearchFor, sPos)) != -1)
	{
		wscSource.replace(lPos, wscSearchFor.length(), wscReplaceWith);
		sPos = lPos + wscReplaceWith.length();
	}

	return wscSource;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

mstime timeInMS()
{
	mstime iCount;
	QueryPerformanceCounter((LARGE_INTEGER*)&iCount);
	mstime iFreq;
	QueryPerformanceFrequency((LARGE_INTEGER*)&iFreq);
	return iCount / (iFreq / 1000);
}