#include <stdio.h>
#include <winsock.h>

//
// Get ready to play a game. Initializing the LAN connection and waiting for game information.
//
int tcpip_init() {
	
	char str[256];
	int teban, agreed;
	
	//
	// Try to initialize the LAN connection
	//
	if(!initialize_socket()) {
		// Error: unable to initialize the socket
		return 0;
	}

	agreed = 0;

	while(!agreed) {
	    //
		// Send the "challenge" command to the server. Not necessary in the CSA tournament.
		//
		send_string_to_tcpip("CHALLENGE\n");
		for( ;; ) {
			get_string_from_tcpip(str);
			print_search_string(str);
			//
			// The information coming from the server is not checked in detail.
			// Only if we are supposed to play black or white and if the final line is as it is supposed to be
			//
			if(strstr(str,"Your_Turn:") != NULL) {
				if (*(str + 10) == '+') 
					teban = 0;	// Received challenge, we are black
				else
					teban = 1;	// Received challenge, we are white
			}
			if(strstr(str,"END Game_Summary") != NULL) 
				break;	// Received necessary info from the server
		}
		
		if(IDYES == MessageBox(hwnd, "Agree to these conditions?", "Condition check", MB_YESNO)) {
			send_string_to_tcpip("AGREE\n");		// Agree to the conditions sent by the server
			agreed = 1;
		}
		else {
			send_string_to_tcpip("REJECT\n");		// Reject the conditions sent by the server
		}
	}
	
	// After agreement the string "START:<GameID>\n" is coming from the server. Just receive this and ignore.
	get_string_from_tcpip(str);
	print_search_string(str);
	
	//
	// Setting black and white, this is program-dependent
	//
	if(teban == 0) {
		// Set program to play with black
	}
	else {
		// Set program to play with white
	}
		
    return 1;
}

//
// Initializing the socket
//
int initialize_socket()
{
	WSADATA WsaData;
	SOCKADDR_IN Addr;
	PHOSTENT host = NULL;			// Host information
	unsigned long addrIP;			// To change the IP address to a number 
	char str[256];
	int i;

	// WinSock initialization
	if ( WSAStartup(0x0101, &WsaData) != 0 ) {
		return 0;
	}

	// Setting up the socket
	Sock = socket(PF_INET, SOCK_STREAM, 0);
	if ( Sock == INVALID_SOCKET ) {
		return 0;
	}
	
	//
	// Program dependent dialog. This dialog is used to get the following info:
	//     sIP: string containing the address of the server
	//     nPort: an integer with the port number (default: 4081)
	//     login: string with the login id of the program
	//     pswd: string with the password for the program
	//
	if(DialogBox(hInst, "IDD_LANINFO", hwnd, LanInfoDlgProc) == FALSE) {
		return 0;
	}
	
	// Changing the IP address to a number
	addrIP = inet_addr(sIP);
	if ( addrIP == INADDR_NONE ) {
		host = gethostbyname(sIP);		// Find the IP address by host name
		if ( host == NULL ) {
//			printf("Error: gethostbyname(): \n");
			return 0;
		}
		addrIP = *((unsigned long *)((host->h_addr_list)[0]));
	} else {
//		host = gethostbyaddr((const char *)&addrIP, 4, AF_INET);	// Fail in the local environment. Not used in the CSA tournament
	}

	// Set the IP address of the server and the port
	memset(&Addr, 0, sizeof(Addr));
	Addr.sin_family      = AF_INET;
	Addr.sin_port        = htons(nPort);
	Addr.sin_addr.s_addr = addrIP;

	// Connect to the server	 
	if ( connect( Sock, (LPSOCKADDR)&Addr, sizeof(Addr) ) != 0 ) {
		return 0;
	}
	
	strcpy(str, "LOGIN ");
	strcat(str, login);
	strcat(str, " ");
	strcat(str, pswd);
	strcat(str, "\n");
	// Send login and password to the server (program dependent)
	send_string_to_tcpip(str);	

	// Receive the "Login: OK" message from the server. No check being done on this message.
	get_string_from_tcpip(str);
	print_search_string(str);
	
	for(i = 0; str[i] != '\n' && str[i] != '\0'; i++)
		;
	if(str[i-2] == 'O' && str[i-1] == 'K')
		return 1;
	else
		return 0;
}

//
// Get a move from the server
//
char *get_string_from_tcpip(char *tcpstr) {
	int sum, nRecv;
	char s[1];
	char rstr[256];
	sum = 0;

	for(;;) {
		// Read 1 byte at a time until '\n'
		nRecv = recv( Sock, s, 1, 0);
		if(nRecv == SOCKET_ERROR) { 
			print_search_string("recv() Error"); 
			stop_search = UNKNOWNERROR;
			break;
		}
		if(s[0] == '\n') 
			break;
		rstr[sum++] = s[0];
		if(sum > 255) { 
			print_search_string("Received string too long!"); 
			stop_search = UNKNOWNERROR;
			break;
		}
	}
	rstr[sum] = '\0';
	
	strcpy(tcpstr, rstr);	
	
	return tcpstr;
}

//
// Send move to the server
//
void send_string_to_tcpip(char *tcpstr) {
	int i, mvl;
	char mv[256];

	strcpy(tcpmvstr, tcpstr);

	mvl = strlen(tcpstr);
	
	send( Sock, tcpstr, mvl, 0);

	for(i = 0; tcpstr[i] != '\n' && tcpstr[i] != '\0'; i++)
		mv[i] = tcpstr[i];
	mv[i] = '\0';
}

//
// Close the LAN connection
//
void tcpip_close() {
	closesocket(Sock);
	WSACleanup();
}

//
// Dialog box to get the necessary info: sIP, nPort, login and pswd
//
BOOL CALLBACK LanInfoDlgProc (HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
	{
	char szText[100];
	HWND hwndCtrl;
    switch (iMsg) {
	case WM_INITDIALOG:
		hwndCtrl = GetDlgItem(hDlg, IDC_IPADDRESS);
		SetWindowText(hwndCtrl, DEFAULTIP);
		hwndCtrl = GetDlgItem(hDlg, IDC_PORTNO);
		SetWindowText(hwndCtrl, itoa(DEFAULTPORT, NumTxt, 10));
		hwndCtrl = GetDlgItem(hDlg, IDC_LOGIN);
		SetWindowText(hwndCtrl, DEFAULTLOGIN);
		hwndCtrl = GetDlgItem(hDlg, IDC_PASSWORD);
		SetWindowText(hwndCtrl, DEFAULTPSWD);
		return TRUE;

	case WM_COMMAND:
		switch(LOWORD (wParam)) {

		case IDOK: case VK_RETURN:
		
			hwndCtrl = GetDlgItem(hDlg, IDC_IPADDRESS);
			GetWindowText(hwndCtrl, szText, sizeof(szText));
			strcpy(sIP, szText);

			hwndCtrl = GetDlgItem(hDlg, IDC_PORTNO);
			GetWindowText(hwndCtrl, szText, sizeof(szText));
			nPort = atoi(szText);

			hwndCtrl = GetDlgItem(hDlg, IDC_LOGIN);
			GetWindowText(hwndCtrl, szText, sizeof(szText));
			strcpy(login, szText);

			hwndCtrl = GetDlgItem(hDlg, IDC_PASSWORD);
			GetWindowText(hwndCtrl, szText, sizeof(szText));
			strcpy(pswd, szText);

			EndDialog(hDlg, TRUE);
			return TRUE;
			
		case IDCANCEL: case VK_ESCAPE:
			EndDialog(hDlg, FALSE);
			return FALSE;
		}
	break;
	}
	return FALSE;
}

