/*******************************************************************************
 *	Control.h	Control process
 *			T.Barnaby,	BEAM Ltd,	2007-02-07
 *******************************************************************************
 */
#ifndef Control_H
#define Control_H	1

#include <stdint.h>
#include <BError.h>
#include <BThread.h>
#include <BCondInt.h>
#include <BRWLock.h>
#include <TmsApi.h>
#include <TmsEventServerList.h>
#include <main.h>

#include <DataAcquire.h>
#include <PuServer.h>

class Control;

class DataRequest {
public:
			DataRequest(DataInfo dataInfo);
public:
	DataInfo	dataInfo;
};

class CycleInfo {
public:
			CycleInfo(UInt32 cycleNumber, BString cycleType);
public:
	UInt32		cycleNumber;
	BString		cycleType;
	BList<BError>	errorList;
};

class CycleInfoList {
public:
	enum		{ numCycles = 8 };
			CycleInfoList();
	
	void		cycleAdd(UInt32 cycleNumber, BString cycleType);
	void		cycleAddError(UInt32 cycleNumber, BError error);
	BList<BError>	getCycleErrors(UInt32 cycleNumber);

private:
	BMutex			olock;
	BList<CycleInfo>	olist;
};

/// A Timer test class. this implements a simple timer operated function called every second, that can be used to check on system resources.
class ControlTimer : public BThread {
public:
			ControlTimer(Control& control);
	void*		function();
private:
	Control&	ocontrol;
};

/// The main system control class
class Control {
public:
			Control(int dbFixed);
			~Control();

	// Main functionality	
	BError		init();				///< Initialise the system
	void		run();				///< Start the system running
	
	// Commands
	BError		initCmd();
	BError		setProcessPriority(BUInt32 priority);
	BError		configure(ConfigInfo configInfo);	///< Configure the system for use. This includes mapping the individual physical PickUp channels to logical pickup channels.
	BError		getConfiguration(ConfigInfo& configInfo);
	BError		test(BList<BError>& errors);		///< Performs a basic test of the system returning a list of errors. The call will return an error object indicating success or an error condition as appropriate.
	BError		getStatus(BList<NameValue>& statusList);	///< Returns the current status of the system. This information includes the number of Pick­Up\u2019s present and their individual status.
	BError		getStatistics(BList<NameValue>& statsList);	///< Returns a list of the statistic values as name/value pairs. The call will return an error object indicating success or an error condition as appropriate.
	BError		getPuChannel(UInt32& puChannel, PuChannel& puPhysChannel);	///< Returns the physical module/Pupe/Channel number given a logical PickUp id. This can be used so that the individual PickUps test functions can be accessed etc.
	BError		puServerStarted(UInt32 number);					///< A TmsPuServer has started
	BError		setSimulation(Simulation simulation);
	BError		getSimulation(Simulation& simulation);
	BError		setTestMode(PuChannel puPhysChannel, UInt32 testOutput, UInt32 timingDisableMask);	///< The signal source for the digital test output connector. 0: None, 1: FrefDelayed, 2: PllFRef, 3: PllFRefHarm. The timingDisableMask bit mask defines which of the timing inputs should be disabled. If a timing input is disabled it can be still operated by software command.
	BError		setTimingSignals(PuChannel puPhysChannel, UInt32 timingSignals);	///< This function sets the given timing signals to the values as defined in the timingSignals bit array.
	BError		captureDiagnostics(PuChannel puPhysChannel, TestCaptureInfo captureInfo, BArray<UInt64>& data);	///< This function will capture test data
	BError		setTestData(PuChannel puPhysChannel, Int32 on, BArray<UInt32> data);	///< This function will set a PU channel to sample data from memory rather than the ADC's
	BError		setPupeConfig(PuChannel puPhysChannel, PupeConfig pupeConfig);
	BError		getPupeConfig(PuChannel puPhysChannel, PupeConfig& pupeConfig);

	BError		setControlInfo(CycleParam params);	///< Sets the control information for the cycle number given and subsequent cycles. The parameters for the processing cycle are passed, this includes the Phase and State table information. The call will return an error object indicating success or an error
	BError		getControlInfo(BString cycleType, UInt32 ring, UInt32 puChannel, CycleParam& params);
	BError		delControlInfo(BString cycleType, UInt32 ring, UInt32 puChannel);
	BError		getControlList(BList<CycleParamItem>& itemList);

	BError		setNextCycle(UInt32 cycleNumber, BString cycleType);	///< Sets the cycle number for the next processing cycle. The call will return an error object indicating success or an error condition as appropriate. This should be called at least 100ms before the next CYCLE_START event.
	BError		setNextCycleInternal(UInt32 cycleNumber, BString cycleType);	///< Sets the cycle number for the next processing cycle. The call will return an error object indicating success or an error condition as appropriate. This should be called at least 100ms before the next CYCLE_START event.

	BError		getCycleInfo(UInt32& cycleNumber, BString& cycleType);	///< Gets the current cycle number.
	BError		getCycleInformation(UInt32 cycleNumber, CycleInformation& cycleInformation);
	BError		getCycleTypeInformation(BString cycleType, CycleTypeInformation& cycleTypeInformation);
	BError		getData(DataInfo dataInfo, Data& data);	///< This function returns a set of data from the data present in the data cache or directly from the Pick-Up processing engines. The  DataInfo object describes the data required. The call will return the required data along with an error object indicating success or an error condition as appropriate. The call will block until data is ready.

	BError		addEventServer(BString name);
	BError		requestData(DataInfo dataInfo);

	// Events
	void		errorEvent(UInt32 cycleNumber, BError error);
	void		cycleStartEvent(UInt32 cycleNumber);
	void		cycleStopEvent(UInt32 cycleNumber);
	
	// System utilities
	int		ring();				///< The ring number
	void		timer();
	BString		boapnsHost();
	uint32_t	diskSpace(BString dir);		///< Return disk space in Megabytes
	uint32_t	memoryFree();			///< Return amount of memory free in Megabytes

public:
	// General data
	int			osimulate;		///< Simulation mode
	DataAcquire		odataAquire;		///< The Data Acquire object

private:
	BError			waitForData(BUInt32 cycleNumber);
	BError			getSimCaptureData(TestCaptureInfo captureInfo, BArray<UInt64>& data);
	BError			initPuServer(UInt32 number);
	BError			readCycleParams();

	// Control data
	int			odebugFixed;		///< Fixed debug level from command line
	BMutex			olock;

	ControlTimer		ocontrolTimer;

	BString			oboapnsHost;		///< The Boap name server host name	
	BoapServer		oboapServer;		///< The overal Boap server class
	TmsControlServer	otmsControlServer;	///< The TmsControl API interface
	TmsProcessServer	otmsProcessServer;	///< The TmsProcess API interface
	TmsEventServer		otmsEventServer;	///< The TmsEvent API interface

	BList<PuServer*>	opuServers;		///< The list of Pick Up Servers in use
	BRWLock			opuServersLock;

	BUInt			oring;			///< The ring number
	bool			omaster;		///< This is a master system
	ConfigInfo		oconfigInfo;		///< The configuration of PickUp channels
	BList<CycleParam>	ocycleParms;		///< The table of cycle parameters

	BCondWrap		ocycleNumber;		///< The Cycle number
	BCondWrap		ocycleCompleteNumber;	///< The Last Completed Cycle number
	UInt32			ocycleNumberNext;	///< The Next Cycle number
	BString			ocycleType;		///< The Cycle type
	BString			ocycleTypeNext;		///< The Cycle type for the next cycle
	
	TmsEventServerList	oeventServers;		///< The list of event servers
	BList<DataRequest>	orequestList;		///< The list of data requested
	CycleInfoList		ocycleInfoList;		///< Information on current and past cycles
	Simulation		osimulation;		///< Overal simualtion
	
	// Statistics
	double			ostartTime;		///< The start time
	UInt64			ocycleProcessed;	///< The number of cycles processed
	UInt64			onumNextCycleErrors;	///< The number of times the next cycle information was not recieved on time
	UInt64			onumFpgaStateErrors;	///< The number of FPGA State errors that occurred
	UInt64			onumDataGoneErrors;	///< The number of data gonbe errors
};

#endif
