
#define _WINSOCK_DEPRECATED_NO_WARNINGS

#include <iostream>
#include "time.h"
#include <list>
using namespace std;
#define _ROUTING_ // uncomment this line for routing (project 3)
#define _WINDOWS // comment this line for linux

#include "target.h"
#ifdef _WINDOWS
#ifndef WIN32_LEAN_AND_MEAN   
#define WIN32_LEAN_AND_MEAN   
#endif   
//#include <sal.h>
#include <windows.h>
#include <winsock2.h>
#include <iphlpapi.h>
#include "process.h"
#ifndef socket_t 
#define socklen_t int
#endif   
#pragma comment(lib, "iphlpapi.lib")  
#pragma comment(lib, "ws2_32.lib")
// #pragma comment(lib, "ws2.lib")   // for windows mobile 6.5 and earlier 
#endif
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h>   
#include <time.h>   
#include <sys/types.h>
#include <sys/timeb.h>
#include <math.h>


#include "helperClasses.h"
#include "someFunctions.h"
#define USE_ROUTING 0
#define TARGET_NUMBER_OF_NEIGHBORS 4

void removeOldNeighbors(list<NeighborInfo> &bidirectionalNeighbors, 
							 list<NeighborInfo> &unidirectionalNeighbors, 
							 bool &searchingForNeighborFlag,
							 NeighborInfo &tempNeighbor);
void sendHelloToAllNeighbors(bool searchingForNeighborFlag, 
							 list<NeighborInfo> &bidirectionalNeighbors, 
							 list<NeighborInfo> &unidirectionalNeighbors, 
							 NeighborInfo &tempNeighbor, 
							 HostId &thisHost,
							 UdpSocket &udpSocket,
							 RoutingTable &routingTable);
void receiveHello(Packet &pkt,
				  bool &searchingForNeighborFlag, 
				  list<NeighborInfo> &bidirectionalNeighbors, 
				  list<NeighborInfo> &unidirectionalNeighbors, 
				  NeighborInfo &tempNeighbor, 
				  HostId &thisHost);

void makeRoutingTable(RoutingTable &routingTable, list<NeighborInfo> &bidirectionalNeighbors, HostId &thisHost);
void dumpNeighbors(list<NeighborInfo> &bidirectionalNeighbors, HostId &thisHost);
int main(int argc, char* argv[])
{	

#ifdef _WINDOWS
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2,1),&wsaData) != 0)
	{ 
		printf("WSAStartup failed: %d\n",GetLastError()); 
		return(1);
	}
#endif
	RoutingTable routingTable; // new for routing

	bool searchingForNeighborFlag  = false;
	list<NeighborInfo> bidirectionalNeighbors;
	list<NeighborInfo> unidirectionalNeighbors;
	list<HostId> allHosts;
	NeighborInfo tempNeighbor;
	HostId thisHost;

	if (argc!=3)
	{
		printf("usage: MaintainNeighbors PortNumberOfThisHost FullPathAndFileNameOfListOfAllHosts\n");
		return 0;
	}

#ifdef _WINDOWS
	srand( _getpid() );
#else
	srand( getpid() );
#endif

	fillThisHostIP(thisHost);
	thisHost._port = atoi(argv[1]);
	readAllHostsList(argv[2],allHosts, thisHost);

	printf("Running on ip %s and port %d\n", thisHost._address, thisHost._port);
	printf("press any  key to begin\n");
	//char c = getchar();

	time_t lastTimeHellosWereSent;	
	time( &lastTimeHellosWereSent );	
	time_t currentTime, lastTimeStatusWasShown;	
	time(&lastTimeStatusWasShown);


	
	UdpSocket udpSocket;
	if (udpSocket.bindToPort(thisHost._port)!=0) {
		cout << "bind failed\n";
		exit(-1);
	}



	Packet pkt;
	while (1)
	{

		// TODO - add your code here

		time(&currentTime);
		if (difftime(currentTime, lastTimeStatusWasShown)>=10) {			
			time( & lastTimeStatusWasShown );
			showStatus( searchingForNeighborFlag, 
				  bidirectionalNeighbors, 
				  unidirectionalNeighbors, 
				  tempNeighbor, 
				  thisHost,
				  TARGET_NUMBER_OF_NEIGHBORS);		
		}

	}
}
