UINT AutomateThread(LPVOID pParam)
{
	CString strLog;
	try
	{
		CoInitialize(NULL);

		// Add specific code here

		while (TRUE)
		{
			if (_Module.m_bStop)
			{
				break;
			}
			Sleep(200);

		} // Main loop

	}
	catch (...)
	{
		strLog.Format(_T("EXCEPTION: Arrêt du service"));
		//_Module.LogEvent(strLog);
	}

	CoUninitialize();
	return 0;
}

TheServer::TheServer(std::wstring url) : m_listener(url)
{
	std::function<void(http_request)> fnGet = &TheServer::handle_get;
	m_listener.support(methods::GET, fnGet);
	std::function<void(http_request)> fnPost = &TheServer::handle_post;
	m_listener.support(methods::POST, fnPost);
	std::function<void(http_request)> fnDel = &TheServer::handle_del;
	m_listener.support(methods::DEL, fnDel);
	std::function<void(http_request)> fnPut = &TheServer::handle_put;
	m_listener.support(methods::PUT, fnPut);

	this->_url = url;
}

DWORD AutomateThread(LPVOID pParam)
{
	CString strLog;
	try
	{
		CoInitialize(NULL);

		std::wstring port = Constants::MasterNodePort;
		std::wstring ip = ServerHelper::GetIP();
		std::wstring url = ServerHelper::BuildURL(ip, port);
		http::uri uri = http::uri(url);
		std::wstring address = uri.to_string();
		std::wstring name = _T("Master");

		TCHAR sz[255];
		_stprintf_s(sz, _T("Node_%s_%s.log"), port.c_str(), name.c_str());
		g_Logger.Init(sz);
		g_Logger.WriteLog(_T("Init Node..."));

		//
		// Create the server node instance
		//

		_stprintf_s(sz, _T("IP : %s"), ip.c_str());
		g_Logger.WriteLog(sz);

		TheServer client(address);
		client._server = ip;
		client._port = port;
		client._name = name;
		client.Init();
		_stprintf_s(sz, _T("Worker node %s"), address.c_str());
		g_Logger.WriteLog(sz);

		while (TRUE)
		// …{

void TheServer::handle_get(http_request message)
{
	g_Logger.WriteLog(_T("handle_get"));

	PrintRequest(message);

	// http://192.168.175.241:7001/MyServer/LMDB/?request=set-data&key=toto0&value=toto1&name=cache2
	// http://192.168.175.241:7001/MyServer/LMDB/?request=get-data&key=toto2_k&name=cache3

	std::wstring request = ServerHelper::FindParameter(message, _T("request"));

	if (request == Constants::VerbPing)
	{
		RequestVerbPing(message);
		return;
	}

	if (request == Constants::VerbGetData)
	{
		RequestVerbGetData(message);
		return;
	}

	if (request == Constants::VerbSetData)
	{
		RequestVerbSetData(message);
		return;
	}

	message.reply(status_codes::OK);
}

std::wstring ServerHelper::FindParameterInQuery(std::map<std::wstring, std::wstring>query, std::wstring var)
{
	auto it = query.find(var);
	std::wstring value;
	if (it != query.end())
	{
		value = it->second;
		std::wcout << _T("Extracted param ") << var << _T(": ") << value << std::endl;
	}
	return value;
}

std::wstring ServerHelper::FindParameter(http_request message, std::wstring var)
{
	auto query = uri::split_query(uri::decode(message.relative_uri().query()));
	std::wstring value = ServerHelper::FindParameterInQuery(query, var);
	return value;
}

void TheServer::RequestVerbGetData(http_request message)
{
	USES_CONVERSION;
	CLMDBWrapper lmdb;

	g_Logger.WriteLog(Constants::VerbGetData.c_str());

	std::wstring key = ServerHelper::FindParameter(message, _T("key"));
	std::wstring dbNameW = ServerHelper::FindParameter(message, _T("name"));
	std::string dbName(dbNameW.begin(), dbNameW.end());

	if (lmdb.Init((LPSTR)dbName.c_str()) == false)
	{
		g_Logger.WriteLog(_T("LMDB Init not done !"));
		message.reply(status_codes::OK);
		return;
	}

	char szKey[255];
	LPSTR lpszValue;

	strcpy_s(szKey, W2A(key.c_str()));

	if (lmdb.GetData((LPSTR)szKey, &lpszValue) == true)
	{
		Data data;
		data.key = key;
		data.value = std::wstring((A2W(lpszValue)));

		free(lpszValue);

		TCHAR sz[255];
		_stprintf_s(sz, _T("Get Key:%s Value:%s"), data.key.c_str(), data.value.c_str());
		g_Logger.WriteLog(sz);

		std::wstring response = data.AsJSON().serialize();
		g_Logger.WriteLog(response.c_str());

		message.reply(status_codes::OK, data.AsJSON());
	}
	else
	{
		message.reply(status_codes::OK);
	}

	lmdb.Uninit((LPSTR)dbName.c_str());
}

void TheServer::RequestVerbSetData(http_request message)
{
	USES_CONVERSION;
	CLMDBWrapper lmdb;
	g_Logger.WriteLog(Constants::VerbSetData.c_str());

	std::wstring key = ServerHelper::FindParameter(message, _T("key"));
	std::wstring value = ServerHelper::FindParameter(message, _T("value"));
	std::wstring dbNameW = ServerHelper::FindParameter(message, _T("name"));
	std::string dbName(dbNameW.begin(), dbNameW.end());

	if (lmdb.Init((LPSTR)dbName.c_str()) == false)
	{
		g_Logger.WriteLog(_T("LMDB Init not done !"));
		message.reply(status_codes::OK);
		return;
	}

	LPSTR lpszKey = W2A(key.c_str());
	LPSTR lpszValue = W2A(value.c_str());
	lmdb.SetData(lpszKey, lpszValue);

	char sz[255];
	sprintf_s(sz, "Set Key:%s Value:%s", lpszKey, lpszValue);
	g_Logger.WriteLog(A2W(sz));

	Data data;
	data.key = A2W(lpszKey);
	data.value = A2W(lpszValue);

	std::wstring response = data.AsJSON().serialize();
	g_Logger.WriteLog(response.c_str());

	message.reply(status_codes::OK, data.AsJSON());

	lmdb.Uninit((LPSTR)dbName.c_str());
}