/*******************************************************************************
 * Copyright (c) 2011 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/


#include "stdafx.h"
#include "WindowsSocketConnection.h"

/* initialize statics */
std::map<HWND, WindowsSocketConnection*>* WindowsSocketConnection::s_connections = new std::map<HWND, WindowsSocketConnection*>; /* leaked */

WindowsSocketConnection::WindowsSocketConnection(CrossfireServer* server) {
	m_clientSocket = INVALID_SOCKET;
	m_server = server;
	m_hWnd = NULL;
	m_listenSocket = INVALID_SOCKET;	
}

WindowsSocketConnection::~WindowsSocketConnection() {
}

bool WindowsSocketConnection::acceptConnection() {
	int rc = WSAAsyncSelect(m_listenSocket, m_hWnd, EW_SOCKET_MSG, FD_ACCEPT);
	if (rc != 0) {
		Logger::error("WindowsSocketConnection.acceptConnection(): WSAAsyncSelect() failed", rc);
		return false;
	}
	return true;
}

bool WindowsSocketConnection::close() {
	deregisterConnection(m_hWnd);
	closesocket(m_clientSocket);
	closesocket(m_listenSocket);
	m_clientSocket = m_listenSocket = INVALID_SOCKET;
	return true;
}

void WindowsSocketConnection::handleSocketAccept() {
	m_clientSocket = accept(m_listenSocket, NULL, NULL);
	if (m_clientSocket == INVALID_SOCKET) {
		Logger::error("WindowsSocketConnection.handleSocketAccept(): accept() failed", WSAGetLastError());
		return;
	}

	int rc = WSAAsyncSelect(m_clientSocket, m_hWnd, EW_SOCKET_MSG, FD_READ | FD_CLOSE);
	if (rc == SOCKET_ERROR) {
		closesocket(m_clientSocket);
		m_clientSocket = INVALID_SOCKET;
		Logger::error("WindowsSocketConnection.handleSocketAccept(): WSAAsyncSelect() failed", WSAGetLastError());
		return;
	}

	/* remove the listenSocket listener */
	WSAAsyncSelect(m_listenSocket, m_hWnd, EW_SOCKET_MSG, 0);
}

void WindowsSocketConnection::handleSocketClose() {
	m_server->disconnected();
}

void WindowsSocketConnection::handleSocketRead() {
	const int LENGTH_BUFFER = 4096;
	char buffer[LENGTH_BUFFER];
	ZeroMemory(buffer, LENGTH_BUFFER);

	int length = recv(m_clientSocket, buffer, LENGTH_BUFFER, 0);
	if (length == SOCKET_ERROR) {
		Logger::error("WindowsSocketConnection.handleSocketRead(): recv() failed", errno);
		return;
	}
	if (length == 0) {
		/* connection closed */
		Logger::log("WindowsSocketConnection.handleSocketRead(): recv() length 0, implies socket closed");
		PostQuitMessage(0);
		return;
	}

	length = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buffer, -1, NULL, 0);
	wchar_t* content = new wchar_t[length];
	MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buffer, -1, content, length);
//Logger::log("-----\nReceived:");
//Logger::log(content);
	m_server->received(content);
	delete[] content;
}

bool WindowsSocketConnection::init(unsigned int port) {
	WSADATA wsaData;
	int rc = WSAStartup(MAKEWORD(2,2), &wsaData);
	if (rc != 0) {
		Logger::error("WindowsSocketConnection.init(): WSAStartup() failed", rc);
		return false;
	}

	char portString[6];
	ZeroMemory(portString, 6);
	_ltoa_s(port, portString, 6, 10);
	struct addrinfo hints;
	ZeroMemory(&hints, sizeof(hints));
	hints.ai_flags = AI_PASSIVE;
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;
	struct addrinfo* result = NULL;
	rc = getaddrinfo(NULL, portString, &hints, &result);
	if (rc != 0) {
		WSACleanup();
		Logger::error("WindowsSocketConnection.init(): getaddrinfo() failed", rc);
		return false;
	}

	m_listenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
	if (m_listenSocket == INVALID_SOCKET) {
		freeaddrinfo(result);
		WSACleanup();
		Logger::error("WindowsSocketConnection.init(): socket() failed", WSAGetLastError());
		return false;
	}

	if (bind(m_listenSocket, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR) {
		closesocket(m_listenSocket);
		m_listenSocket = INVALID_SOCKET;
		freeaddrinfo(result);
		WSACleanup();
		Logger::error("WindowsSocketConnection.init(): bind() failed", WSAGetLastError());
		return false;
	}

	rc = listen(m_listenSocket, SOMAXCONN); 
	freeaddrinfo(result);
	if (rc == SOCKET_ERROR) {
		closesocket(m_listenSocket);
		m_listenSocket = INVALID_SOCKET;
		WSACleanup();
		Logger::error("WindowsSocketConnection.init(): listen() failed", WSAGetLastError());
		return false;
	}

	std::wstringstream stream;
	stream << "Listening for a connection on localhost:";
	stream << portString;
	Logger::log((wchar_t*)stream.str().c_str());

	static LPCWSTR s_windowClass = _T("CrossfireSocketConnection"); // TODO differentiate by port?
	HINSTANCE module = GetModuleHandle(NULL);
	WNDCLASS ex;
	ex.style = 0;
	ex.lpfnWndProc = WndProc;
	ex.cbClsExtra = 0;
	ex.cbWndExtra = 0;
	ex.hInstance = module;
	ex.hIcon = NULL;
	ex.hCursor = NULL;
	ex.hbrBackground = NULL;
	ex.lpszMenuName = NULL;
	ex.lpszClassName = s_windowClass;
	RegisterClass(&ex);
	m_hWnd = CreateWindow(s_windowClass, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, module, NULL);
	if (!m_hWnd) {
		Logger::error("WindowsSocketConnection.init(): CreateWindow() failed", GetLastError());
		return false;
	}
	WindowsSocketConnection::registerConnection(m_hWnd, this);
	return true;
}

bool WindowsSocketConnection::send(const wchar_t* msg) {
//Logger::log("-----\nSent:");
//Logger::log((wchar_t*)msg);
	int length = WideCharToMultiByte(CP_UTF8, 0, msg, -1, NULL, 0, NULL, NULL);
	char* content = new char[length];
	WideCharToMultiByte(CP_UTF8, 0, msg, -1, content, length, NULL, NULL);
	if (::send(m_clientSocket, content, length - 1, 0) == SOCKET_ERROR) { /* uses length - 1 to not send null terminator */
		Logger::error("WindowsSocketConnection.send(): send() failed", errno);
		return false;
	}
	return true;
}

bool WindowsSocketConnection::deregisterConnection(HWND hWnd) {
	std::map<HWND, WindowsSocketConnection*>::iterator iterator = s_connections->find(hWnd);
	if (iterator != s_connections->end()) {
		s_connections->erase(iterator);
		return true;
	}

	/* not found */
	return false;
}

WindowsSocketConnection* WindowsSocketConnection::getConnection(HWND hWnd) {
	std::map<HWND, WindowsSocketConnection*>::iterator iterator = s_connections->find(hWnd);
	if (iterator == s_connections->end()) {
		/* not found */
		return NULL;
	}
	return iterator->second;
}

void WindowsSocketConnection::registerConnection(HWND hWnd, WindowsSocketConnection* connection) {
	s_connections->insert(std::pair<HWND,WindowsSocketConnection*>(hWnd, connection));
}

LRESULT CALLBACK WindowsSocketConnection::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
	switch (message) {
		case EW_SOCKET_MSG: {
			WindowsSocketConnection* instance = WindowsSocketConnection::getConnection(hWnd);
			if (!instance) {
				Logger::error("WindowsSocketConnection:WndProc(): received EW_SOCKET_MSG for unregistered hWnd");
				break;
			}
			switch (WSAGETSELECTEVENT(lParam)) {
				case FD_READ: {
					instance->handleSocketRead();
					break;
				}
				case FD_ACCEPT: {
					instance->handleSocketAccept();
					break;
				}
				case FD_CLOSE: {
					instance->handleSocketClose();
					break;
				}
				default: {
					Logger::error("WindowsSocketConnection:WndProc(): received EW_SOCKET_MSG for unexpected event");
					break;
				}
			}
			break;
		}
		default: {
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
	}
	return 0;
}
