/*************************************************************************
 * This file is part of the Distributed Computation feature
 *
 * Project created in conformity with the requirements for the Degree of
 * Master of Engineering in Software Engineering, Computing and Software
 * Department, McMaster University 2012
 *
 * Author:	David Kirby
 * Supervisor: Dr. Ryan Leduc
 *
 * Description: This class wraps the communication between the Master and 
 * the Slave processes, hiding the actual implementation from the rest of 
 * the code.
 ************************************************************************/

#pragma once

#include <string>
#include <sstream>

#include "DesAlgo.h"

#include "Host.h"
#include "HostList.h"

#include "DistCommon.h"
#include "CommonDefinitions.h"

#ifdef __ENABLE_DIST__
#include <mpi.h>
#include <pthread.h>
#endif

namespace DESpot
{
	class CommHandler
	{
		public:
			// Constructor 
			// Parameters: isSlave indicates whether the process is the Master or a Slave
			//			   maxHosts indicates the maximum number of remote hosts to spawn - Master process only
			CommHandler(bool isSlave = true, int maxHosts = -1);

		public:
			// Send a command and return the result - Master process only
			remoteCheck* sendRecv(std::string data);

			// Send an int to the Master process - Slave process only
			void send(int data);
			// Send a string to the Master process - Slave process only
			void send(std::string data);
			// Receive an int from the Master process - Slave process only
			int recvInt();
			// Receive a string from the Master process - Slave process only
			std::string recvString();

			// Get the total number of slave nodes
			int getSlaveCount();

			// Terminate slave processes
			void terminateSlaves();

		public:
			static void closeConnection();

		private:
			// Ensures that MPI has been initialized
			static void checkInit();

		private:			
			// Parent process that spawned this process - Slave process only
			#ifdef __ENABLE_DIST__
			MPI_Comm parent;
			#endif
			bool isSlave;

		private:
			// The list of valid hosts to send commands to - Master process only
			static HostList hosts;
			static bool initialized;
			#ifdef __ENABLE_DIST__
			static pthread_mutex_t CommHandlerMutex;
			#endif
	};
}
