#include "stdafx.h"
#ifdef MOD_FUNCTIONS
#include "emule.h"
#include "eMuleFuture.h" 
#include "Preferences.h" //for username/pw
#include "wininet.h" //for internet functionality
#include "otherfunctions.h" //for "GetErrorMessage()"
#include "./AntiLeech/Modname.h" //for the Modname used as agent
#include "log.h" //to enable logging
#include "emuleDlg.h"
#include "FriendList.h"
#include "TaskbarNotifier.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//WiZaRd: FiX for usernames with special chars
//it seems the only char we have to replace is the whitespace...
CString PrepareUsername(const CString& str)
{
	CString ret = L"";
	for(int i = 0; i != str.GetLength(); ++i)
	{
		if(str[i] == L' ')
			ret.Append(L"%20");
		else
			ret.AppendChar(str[i]);
	}
	return ret;
}

CString CallModFunction(const uint8 uiFuncType)
{
	CString strVerb = L"";
	CString strMore = L"";
	switch(uiFuncType)
	{
		case EMF_ID_CHECK:
			strVerb = L"ID";
			break;
		case EMF_PN_CHECK:
			strVerb = L"PN";
			break;
		case EMF_FRIEND_ENTRY:
			strVerb = L"UP";
			strMore.Format(L"&hash=%s", md4str(thePrefs.GetUserHash()));
			break;
		case EMF_FRIEND_REMOVE:
			strVerb = L"RM";
			break;
		case EMF_FRIEND_LOAD:
			strVerb = L"FL";
			break;		
		default:
			ASSERT(0);
			theApp.QueueDebugLogLineEx(LOG_ERROR, L"EMF: %hs failed - error: wrong verb");
			return L"ER"; //error?
	}

	HINTERNET m_hINet = NULL;
	HINTERNET m_hConnection = NULL;
	HINTERNET m_hData = NULL;
	CString read = L"";

	try
	{
		m_hINet = InternetOpen(MOD_VERSION, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, NULL); 
		if(!m_hINet) 
			throw GetLastError();

		m_hConnection = InternetConnect(m_hINet, L"www.emulefuture.eu", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, NULL, 0);
		if(!m_hConnection) 
			throw GetLastError();

		const CString& strUserName = PrepareUsername(thePrefs.GetUserName()); //WiZaRd: FiX for usernames with special chars
		const CString& strPassWord = thePrefs.GetUserPW();
		CString subpage;
		subpage.Format(L"emulefuture/modfunctions.php?act=%s&user=%s&pw=%s%s", strVerb, strUserName, strPassWord, strMore);
		m_hData = HttpOpenRequest(m_hConnection, L"GET", subpage, 0, 0, 0, INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_IGNORE_CERT_CN_INVALID | INTERNET_FLAG_IGNORE_CERT_DATE_INVALID | INTERNET_FLAG_PRAGMA_NOCACHE, 0); 
		if(!m_hData) 
			throw GetLastError();

		if(!HttpSendRequest(m_hData, 0, 0, 0, 0))
			throw GetLastError();

		DWORD dwBytesAvail = 0;
		while (InternetQueryDataAvailable(m_hData, &dwBytesAvail, 0, 0))
		{
			BYTE* pBuffer = new BYTE[dwBytesAvail+1];
			DWORD dwBytesRead = 0;
			if(!InternetReadFile(m_hData, pBuffer, dwBytesAvail, &dwBytesRead))
			{
				delete[] pBuffer;
				throw GetLastError();
			}
			if (dwBytesRead == 0)
			{
				delete[] pBuffer;
				break;	//eof
			}

			pBuffer[dwBytesRead] = '\0';
			read.Append(CString(pBuffer));
			delete[] pBuffer;
		}
	}
	catch(DWORD error)
	{
		theApp.QueueDebugLogLineEx(LOG_ERROR, L"EMF: %hs failed - error: %s", __FUNCTION__, GetErrorMessage(error));
		read = L"ER";
	}
	catch(CString err)
	{
		theApp.QueueDebugLogLineEx(LOG_ERROR, L"EMF: %hs failed - error: %s", __FUNCTION__, err);
		read = L"ER";
	}
	catch(...)
	{	
		theApp.QueueDebugLogLineEx(LOG_ERROR, L"EMF: %hs failed - unknown error", __FUNCTION__);		
		read = L"ER";
	}

	//close handles...
	InternetCloseHandle(m_hData); 
	InternetCloseHandle(m_hConnection); 
	InternetCloseHandle(m_hINet);

	if(read.IsEmpty() || read.Left(2) == L"ER")
		return L"ER"; //some error here... maybe unreachable host

	return read;
}

bool	DoIDCheck()
{
	const CString ret = CallModFunction(EMF_ID_CHECK);
	CString msg;
	UINT nLogFlag = LOG_SUCCESS;
	if(ret == L"ER" || _tstoi(ret) == 0)
	{
		nLogFlag = LOG_ERROR;
		msg = GetResString(IDS_EMF_IDCHECK_FAILED);
	}
	else
		msg = GetResString(IDS_EMF_IDCHECK_OK);

	//no need to log/show if we're already authenticated!
	if(!thePrefs.IsAuthenticated() && theApp.emuledlg && theApp.emuledlg->m_wndTaskbarNotifier) //no pop-up on startup!
	{
		theApp.emuledlg->m_wndTaskbarNotifier->Show(msg, TBN_NULL, NULL);
		theApp.QueueLogLineEx(nLogFlag, msg);
	}

	return nLogFlag == LOG_SUCCESS;
}

void DoPNCheck()
{
	if(!thePrefs.IsCheckPNCount(false))
		return;

	const CString nCount = CallModFunction(EMF_PN_CHECK);		
	CString sMsg = L"";
	if(nCount == L"ER")
	{
		sMsg = GetResString(IDS_EMF_PNCHECK_FAILED);
		theApp.emuledlg->m_wndTaskbarNotifier->Show(sMsg, TBN_NULL, NULL);
		theApp.QueueLogLineEx(LOG_WARNING, sMsg);
	}
	else if(/*nCount != L"ER" &&*/ _tstoi(nCount) != 0)
	{
		const CString strURL = L"http://www.emulefuture.eu/forum/index.php?act=Msg";
		sMsg.Format(GetResString(IDS_EMF_PNCHECK), _tstoi(nCount));
		theApp.emuledlg->m_wndTaskbarNotifier->Show(sMsg, TBN_NULL, strURL);
		sMsg.AppendFormat(L": %s", strURL);
		theApp.QueueLogLineEx(LOG_WARNING, sMsg);
	}
}

bool	DoFriendListEntry(const bool bAdd)
{	
	//question: should we show some feedback for the friendlist entry?
	if(bAdd)
	{				
		const CString succ = CallModFunction(EMF_FRIEND_ENTRY);
		if(succ == L"ER")
		{
			theApp.QueueDebugLogLineEx(LOG_ERROR, GetResString(IDS_EMF_FRIENDLISTADDERROR));
			ASSERT(0); //should never happen!
			return false;
		}
		else
		{
			theApp.QueueDebugLogLineEx(LOG_SUCCESS, GetResString(IDS_EMF_FRIENDLISTADDSUCCESS));
			//success
			return true;
		}
	}
	else //remove
	{				
		const CString succ = CallModFunction(EMF_FRIEND_REMOVE);
		if(succ == L"ER")
		{
			theApp.QueueDebugLogLineEx(LOG_WARNING, GetResString(IDS_EMF_FRIENDLISTREMERROR));
			ASSERT(0); //should never happen!
			return false;
		}
		else
		{
			//success
			theApp.QueueDebugLogLineEx(LOG_SUCCESS, GetResString(IDS_EMF_FRIENDLISTREMSUCCESS));
			return true;
		}
	}
}

void DoFriendListUpdate()
{
	const CString list = CallModFunction(EMF_FRIEND_LOAD);
	if(list != L"ER")
		theApp.friendlist->LoadList(list);
	else
		theApp.QueueLogLineEx(LOG_ERROR, GetResString(IDS_EMF_FRIENDSFAILED));
}
#endif