#ifndef _REMOTEAGENTDRIVER_H
#define _REMOTEAGENTDRIVER_H

#include "ThalesPowerSystemIF.h"
#include "MMDropWeight.h"
#include "LayeredControlIF.h"
#include "MMMissionName.h"
#include "MMRecipient.h"

#include "RemoteAgentOutput.h"
#include "RemoteAgentCommand.h"

class ModemMessage;
class MMActiveBehavior;
class MMAgentRequest;
class MMBehavior;
class MMBehaviorArray;
class MMTailcone;
class MMCircuit;
class MMCircuitBatch;
class MMCurrent;
class MMDriver;
class MMServerAlarm;
class MMDynamicControlCommand;
class MMDynamicControlCommandFull;
class MMThalesBatteryInfo;
class MMWatchdog;
class MMUSBLFix;
class NavigationIF;
class LayeredControlIF;
class DwpTailConeIF;
class DynamicControlIF;
class VehicleConfigurationIF;
class ThalesBatteryIF;
class AhrsIF;
class DepthSensorIF;
class LiPolyBatteryIF;
class RdiadcpIF;
class ApogeeHomingIF;
class GpsIF;
class ExternalPosFixIF;
class MMNmea;
class MMRtcm;
class RtcmIF;
class MMServer;
class MMMissionInfo;
class MMMissionName;
class SupervisorIF;
class SocketBroker;
class ModemBroker;
class RangeFinderIF;
class SVSIF;
class AvtrakIF;
class Ln250IF;
class USBLFilterIF;
class TaskInterface;

class RemoteAgentDriver :  public MMRecipient
{
public:
	RemoteAgentDriver();
	~RemoteAgentDriver();

	// Overrides.
	virtual int init();
	virtual void run();

	// queues a copy of message to send it out
	static void send(ModemMessage* pMM);

	static RemoteAgentDriver * getRemoteAgentDriver();

	// Sort the messages
	void receive(const ModemMessage* pMessage);

	virtual void enableModem();
	virtual void disableModem();

protected:
	static void signalChildHandler( int sigNo );

	int checkServer(char *name);

	// Reset all message flags
	void resetMessageFlags();

	// Read config file
	void loadConfiguration();

	// Create servers
	void createServers();

	// Verify servers still exist
	void verifyServers();

	// Check for messages at remoteBroker
	Boolean checkForMessages();

	//process commands coming in
	void processRequests();

	// Maintain event service
	void sendMessages();

	// Determine whether or not to send a message
	Boolean checkForSending(Boolean flag, int period);

	//polls acks if they need polling
	void pollAcks();

	//file requests for sends to topside
	void processRequestCommand(short mm, short tt, short p);

	//alternate, string based parsing of string messages
	void handleString(ModemMessage* mm);

	// Handle an agent request message
	void handleRequest(ModemMessage* mm);

	//handle a behavior message
	void handleBehavior(ModemMessage* mm);

	//handle a behavior array message
	void handleBehaviorArray(ModemMessage* mm);

	//handle a mission name, meaning changing current mission

	void handleMissionName(ModemMessage* mm);

	void handleJumpBehavior(ModemMessage* mm);

	//handle a driver command
	void handleDriverCommand(ModemMessage* mm);

	// Get the current time
	int getTime();

	// Reload the vehicle configuration (etc.)
	void reloadVehicle();

	// Message sending functions
	void sendAck();
	void sendActiveBehavior();
	void sendOas();
	void sendSvs();
	void sendLN250();
	void sendNavigationPosition();
	void sendNavigationAttitude();
	void sendTailconeRemote();
	void sendTailconeLocal(ModemMessage* mm);
	void sendTailconeRaw();
	void sendCircuitRemote(int circuit);
	void sendCircuitBatchRemote();
	void sendCircuitLocal(ModemMessage* mm);
	void sendCircuitBatchLocal(ModemMessage* mm);
	void sendCircuitCurrent(int circuit);
	void sendCircuitCurrentBatch();
	void sendCircuitInfo();
	void sendGroundFaultCurrent(int fault);
	void sendGroundFaultCurrentBatch();
	void sendTemperature(int temperature);
	void sendTemperatureBatch();
	void sendWaterAlarm(int number);
	void sendWaterAlarmBatch();
	void sendServerAlarm(int server);
	void sendServerAlarmBatch();
	void sendDropWeightReleaseLocal(ModemMessage* mm);
	void sendDropWeightReleaseBatchRemote();
	void sendDynamicControlCommandLocal(ModemMessage* mm);
	void sendDynamicControlCommandRemote();
	void sendDynamicControlCommandFullLocal(ModemMessage* mm);
	void sendDeviceInfo();
	void sendAhrs();
	void sendDepthSensor();
	void sendThalesBatteryInfo();
	void sendThalesBatteryGlobal();
	void sendWatchdogCommand(ModemMessage* mm);
	void sendDvl();
	void sendDvlBeamVelocities();
	void sendDvlBeamRanges();
	void sendDvlAttTemp();
	void sendHoming();
	void sendGps();
	void sendNmea();
	void sendExternalPosFix(ModemMessage* mm);
	void sendAbortMission();
	void sendKillMission();
	void sendRtcmMessage(ModemMessage* mm);
	void sendUSBLFixMessage(ModemMessage* mm);
	void serverMessage(ModemMessage* mm);
	void sendMissionInfo(ModemMessage* mm);
	void sendDriverStatus();
	void sendLogDirName();

	void sendControlExecute();

	// Drop weight enum conversion
	//DropWeightIF::Weight getDropWeightIF(MMDropWeightRelease::Weight weight);
	//MMDropWeightRelease::Weight getDropWeightMM(DropWeightIF::Weight weight);
	ThalesPowerSystemIF::Weight getThalesPowerSystemIF(MMDropWeightRelease::Weight weight);
	MMDropWeightRelease::Weight getDropWeightMM(ThalesPowerSystemIF::Weight weight);

	// Internal counter
	long m_count;

	//mission change counters
	short _misCounter;

	//internal attributeChange counter
	short _attCounter;

	//to hold things waiting for acknowledgements
	short _singleAck;
	LayeredControlIF::AckData _ackData;
	short* _attNums;
	short* _attDone;
	short _ackArraySize;

	MMMissionName::MissionType m_misType;

	//a couple flags
	Boolean m_ackSingle;
	Boolean m_ackArray;
	Boolean m_ackMis;

	// Server stubs
	NavigationIF *m_navigation;
	LayeredControlIF *m_layeredControl;
	DwpTailConeIF *m_tailcone;
	ThalesPowerSystemIF *m_power;
	//PowerSystemIF *m_power;
	//	WaterAlarmIF *m_waterAlarm;
	//	DropWeightIF *m_dropWeight;
	DynamicControlIF *m_dynamicControl;
	VehicleConfigurationIF *m_vehicleConfiguration;
	AhrsIF *m_ahrs;
	DepthSensorIF *m_depthSensor;
	ThalesBatteryIF *m_battery;
	RdiadcpIF *m_dvl;
	ApogeeHomingIF *m_homing;
	GpsIF *m_gps;
	ExternalPosFixIF *m_externalPosFix;
	RtcmIF *m_rtcm;
	SupervisorIF *m_supervisor;
	RangeFinderIF *m_oas;
	SVSIF *m_svs;
	AvtrakIF *m_avtrak;
	Ln250IF *m_ln250;
	USBLFilterIF *m_usbl;

	typedef void (RemoteAgentDriver::* rF)();
	typedef void (RemoteAgentDriver::* hF)(ModemMessage* mm);

	rF m_requestFunctionList[64];
	hF m_handleFunctionList[64];

	char m_flagList[64];
	short m_periodList[64];

	TaskInterface * m_serverList[64];
	char * m_serverNameList[64];
	int m_numServers;

	virtual int spawnAuxTasks( void ) {return 1;};
 private:
	////////////////////////////////////////////////////////////////////
	// signal handler
	static void signalHandler(int signalNo);
	
	////////////////////////////////////////////////////////////////////
	// Destroy latest ras object
	static void cleanup();
	
	// For debug printing
	debug_t debug;

	//to allow modem to be used or not
	Boolean _allowComs;

	ModemBroker* _modemBroker;

	const char* _remoteSocketIP;   // text version of the target socket IP
	const char* _serialPort1;      // serial port for serial modem 1
	const char* _serialPort2;      // serial port for serial modem 2
	long _baudRate1;	       // baud rate for serial modem 1
	long _baudRate2;	       // baud rate for serial modem 2

	long _connectionSpeed;
	
	static RemoteAgentDriver* _gpRemoteAgentDriver;

	RemoteAgentCommand* _command;
};

#endif



