#include "tconnection_amcs.hpp"

//constructor
TConnection_AMCS::TConnection_AMCS()
{
	currentIP = 0;		
}

//destructor
TConnection_AMCS::~TConnection_AMCS()
{
}

//Try connect method, used to launch the series of call to connect to AMCS
bool TConnection_AMCS::setUp(TVSP_AMCS activeVSP, TClientAMCS clientQueue)
{
	for(int j=0;j<4;j++)
	{
	//Make sure the table is empty
	this->enabledIPs[j]=0;;
	}
	int j=0;
	//check for valid IPs
	for(int i=0; i<4; i++)
	{
	
	if (activeVSP.ip_Amcs[i]!=0)	{
		
		this->enabledIPs[i-j] = activeVSP.ip_Amcs[i];
	}
	else
	{
		j++;
	}
	}
	if (this->enabledIPs[0]!=0)
	{	
		return true;
	}
	return false;	
	//SET UP THE BULLETIN
	//INITSYSTEMHANDLERCLIENT();
}

//Ping method, will output the ping command results to a file then reads it.
bool TConnection_AMCS::ping(char* ipAddress)
{
	int returning;  			//shell command return	
	int counter=0;  			//will be used to count the failed ping commands
	char command[50];  			//command string 
	strcpy(command,"ping -c 1 ");
	strcat(command, ipAddress);

	//Beginning of ping 
	for(int i=0; i<2; i++)     		//will send two times two packets
	{
		fflush(stdout);
		returning = system(command);
	  	//sets the returning value of the shell
		if (returning!=0)			//If the value different than success
		{
			counter++;		//add 1 to the counter
		}				//end if
	}					//end for

	if (counter<2)				//If the counter is 0 or 1, 
	{
		return true;			//ping was successful
	}					//end if
	else
	{
		return false;			//else it wasn't
	}					//end else
}						//end method


//Method to try to establish a connection to the AMCS
bool TConnection_AMCS::establish(char* portNumber, int index)
{
	int connectReturn;
	// Create the TCP socket 
        if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) 
	{
		exit(1);
        }	
	//Construct the server sockaddr_in structure 
	memset(&echoserver, 0, sizeof(echoserver));       	// Clear struct
        echoserver.sin_family = AF_INET;                  // Internet/IP
        echoserver.sin_addr.s_addr = inet_addr(enabledIPs[index]);// IP address
        echoserver.sin_port = htons(atoi(portNumber));    // server port
        // Establish connection */
	connectReturn = connect(sock,
           (struct sockaddr *) &echoserver,
            sizeof(echoserver));
	sleep(2);
	
	if (connectReturn < 0)
	{
        	return false;//Failed to connect with server
        }
	return true;
}

//softwareCOMM method
//This method is used to engage the process of greeting and timeout messages
bool TConnection_AMCS::softwareComm(TVSP_AMCS vsps)
{
	bool returns;
	TMessages_AMCS * greeting = new TMessages_AMCS();
	//Format that message as a greetings message
	returns = greeting->generateGreetingsMsg(vsps.hostName,vsps.rasSystemIdent, vsps.rasSiteIdent);
	//Send greetings
	returns = sendMessage(greeting->completeMessage);
	//delete the message
	delete greeting;	
	// Receive the message back from the AMCS
	returns = receiveMessage();		
	if (returns == true)
	{
		//Generate the timeout sequence		
		TMessages_AMCS * timeout = new TMessages_AMCS();
		//Format that message as a timeout message
		returns = timeout->generateTimeoutMsg(vsps.hostName,vsps.rasSystemIdent, vsps.rasSiteIdent, vsps.timeoutSeconds);	
		//send Timeout
		returns = sendMessage(timeout->completeMessage);
		//delete the message;
		delete timeout;
		//Receive the message back from the AMCS
		returns = receiveMessage();
		if (returns == true)
		{
			return true;
		}
		return false;
	}
	return false;
}


//reconnectFAIL method
//This method will loop until a reconnection has been done.
bool TConnection_AMCS::reconnectFail(TVSP_AMCS vsps)
{
	int i = currentIP;
	//retry the connection with the current IP and util the last one
	while (true)
	{
		//If i=4, then re-read VSP and start back the loop
		if ((i==4) or (enabledIPs[i] == 0))
		{
			//read VSPs;
			//setUPIPtable etc
			i=0;
		}
		//ping the current IP
		printf("\n\n%i\n", i);
		printf("%s\n\n", enabledIPs[i]);
		if (ping(enabledIPs[i])==true)
		{
			printf("ping was true\n");
			if (establish(vsps.port_AMCS, i)== true)
			{
				printf("establish was true\n");
				if (softwareComm(vsps)== true)
				{
					currentIP = i;
					//return true to where it was called
					return true;
				}
			}			
		}
		i++;
		sleep(5);
	}
return false;	
	
}

//Method to send messages
bool TConnection_AMCS::sendMessage(string messageToSend)
{
	unsigned int echolen;	
	char* message;		
	//CAST to char*
	message = strdup(messageToSend.c_str()); 
	// Send the message to the server
        echolen = strlen(message);
		
        //if (send(sock, message, echolen, 0) != echolen)
	if (write(sock, messageToSend.c_str(), echolen) != echolen)
	{
        	//mismatch in number of sent bytes
		printf("i will print the erro no\n");
		perror("write");
		return false;
	}
	return true;
}


bool TConnection_AMCS::receiveMessage()
{
	fprintf(stdout, "Received: ");	
        int received = 0;
	char buffering[200];
	int bytes = 0;
        sleep(1);
	if ((bytes = recv(sock, buffering, 200-1, 0)) < 1)
	{
               	//Failed to receive bytes from server
		return false;
        }
        received += bytes;
        buffering[bytes] = '\0';        // Assure null terminated string 
        fprintf(stdout, buffering);
	fprintf(stdout, "\n");        	
	return true;
}	

bool TConnection_AMCS::presenceOfAMCS(TVSP_AMCS vspSettings,int index)
{
	char command[34];
	//poll to see if the system is still there	
	strcpy(command,"netstat | grep ");
	strcat(command,vspSettings.port_AMCS);
	strcat(command," > temp.txt"); 
	system(command);
	//DEBUG
	printf("%s\n", enabledIPs[currentIP]);
	sleep(1);	
	//Search for "Established" in the temp file
	if ((establishSearch("temp.txt")==false) or (ping(enabledIPs[currentIP])==false))
	{
		printf("\n\nCONNECTION FAILED\n\n");
		return false;
	}
	return true;
}

bool TConnection_AMCS::establishSearch(const string& textFile)
{
	string line;
    	bool found = false;

	ifstream ifs(textFile.c_str());	
	fflush(stdout);
    	while (getline(ifs, line))
	{
      		if (line.find("ESTABLISHED") != string::npos)
         	{
               		found = true;
               		break;
         	}
	}
     	ifs.close();
     	return found;
}

void TConnection_AMCS::closeSocket()
{
	close(sock);
}

