#include "SmallSocket.h"

SmallSocket::SmallSocket(int socket_type)
{
	int realPortNumber = PORT_NUMBER;

	if (socket_type == SmallSocket::SERVER) {
		this->socketType = SmallSocket::SERVER;
	} else {
		this->socketType = SmallSocket::CLIENT;
	}

	/*
	The WSADATA structure (wsaData) contains information about the Windows Sockets implementation. 
	The MAKEWORD(2,2) parameter of WSAStartup makes a request for the version of Winsock on the system, 
	and sets the passed version as the highest version of Windows Sockets support that the caller can use.
	 */
	int iResult = WSAStartup( MAKEWORD(2,2), &wsaData ); 

	if ( iResult != NO_ERROR )
		printf("Error at WSAStartup()\n");

	m_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); // should be parameterized

	if ( m_socket == INVALID_SOCKET ) {
		printf( "Error at socket(): %ld\n", WSAGetLastError() );
		WSACleanup();
		return;
	}

	if (this->socketType == SmallSocket::SERVER)
	{
		service.sin_family = AF_INET;
		service.sin_addr.s_addr = inet_addr( "127.0.0.1" );
		//service.sin_addr.s_addr = inet_addr("134.173.200.XX");  //wireless connection
		// here is the port...
		service.sin_port = htons( realPortNumber );

		while ( bind( m_socket, (SOCKADDR*) &service, sizeof(service) ) == SOCKET_ERROR ) {
			printf( "bind() failed at port #d.\n", realPortNumber );
			realPortNumber++;
			if (realPortNumber < PORT_NUMBER + 1000)
			{
				service.sin_port = htons( realPortNumber );
			}
			else
			{
				closesocket(m_socket);
				return;
			}
		}

		if ( listen( m_socket, 1 ) == SOCKET_ERROR )
			printf( "Error listening on socket.\n");

		// wait for connection

		printf("*****************\n\nBinding succeeded at PORT = %d.\n\n*****************\n", realPortNumber);

		SOCKET AcceptSocket;

		printf( "Waiting for a client to connect...\n" );
		while (1) {
			AcceptSocket = SOCKET_ERROR;
			while ( AcceptSocket == SOCKET_ERROR ) {
				AcceptSocket = accept( m_socket, NULL, NULL );
			}

			printf( "Client Connected.\n");
			m_socket = AcceptSocket;  
			break;
		}
	} // end if SERVER

	if (this->socketType == SmallSocket::CLIENT)
	{
		clientService.sin_family = AF_INET;
		clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
		clientService.sin_port = htons( 5001 );

		if ( connect( m_socket, (SOCKADDR*) &clientService, sizeof(clientService) ) == SOCKET_ERROR) {
			printf( "Failed to connect.\n" );
			WSACleanup();
			return;
		}
	} // end if CLIENT
}


int SmallSocket::receive(char* bufferToReceive, int charsToReceive)
{
	int bytesRecv = SOCKET_ERROR;
	bytesRecv = recv( m_socket, bufferToReceive, charsToReceive, 0 );
	for (int i=bytesRecv ; i<charsToReceive ; ++i)
		bufferToReceive[i] = 0;
	//printf( "Bytes Recv: %ld\n", bytesRecv );
	return bytesRecv;

	/* this was code from the Windows documentation...
		while( bytesRecv == SOCKET_ERROR ) {
			bytesRecv = recv( m_socket, recvbuf, 32, 0 );
			if ( bytesRecv == 0 || bytesRecv == WSAECONNRESET ) {
				printf( "Connection Closed.\n");
				break;
			}
			if (bytesRecv < 0)
				return;
			printf( "Bytes Recv: %ld\n", bytesRecv );
	}
	*/
}

int SmallSocket::sendout(const char* bufferToSend, int charsToSend)
{
	int length = SmallSocket::BUFFER_SIZE;

	if (charsToSend == 0) {
		// 0-terminated with max of SmallSocket::BUFFER_SIZE
		length = (int)(strlen(bufferToSend));
		if (length <= 0 || length > SmallSocket::BUFFER_SIZE)
			length = SmallSocket::BUFFER_SIZE;
	} else if (charsToSend > SmallSocket::BUFFER_SIZE ||
			charsToSend < 0)
		length = SmallSocket::BUFFER_SIZE;
	else 
		length = charsToSend;

	int bytesSent = send( m_socket, bufferToSend, length, 0 );
	//printf( "Bytes Sent: %ld\n", bytesSent );
	return bytesSent;
}



SmallSocket::~SmallSocket(void)
{
	WSACleanup();
}
