/*******************************************************************************
 *	TmsControlClient2.cpp	TMS API example code
 *			T.Barnaby,	BEAM Ltd,	2007-02-07
 *******************************************************************************
 *
 *	This is a very basic example of using the TmsApi to set the
 *	TMS's cycleNumber and cycleType.
 *	It is designed to give an overview of using the API.
 */
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <TmsD.h>
#include <TmsC.h>
#include <TmsS.h>
#include <BSema.h>

using namespace Tms;
using namespace std;

#define	DEBUG	0

#if DEBUG
#define	dprintf(fmt, a...)	printf(fmt, ##a);
#else
#define	dprintf(fmt, a...)
#endif

BSema	cycleStopSemaphore;

double getTime()
{
	struct timeval	tp;
	
	gettimeofday(&tp, NULL);
	return ((double) tp.tv_sec + (double) tp.tv_usec * 1e-6);
}

class TmsEventServer : public Tms::TmsEventService {
public:
	TmsEventServer(BoapServer& server, BString name) : Tms::TmsEventService(server, name){
	}

	BError errorEvent(BUInt32 cycleNumber, BError error){
		BError	err;
		
		dprintf("Event: Error: Cycle: %d Error: %d:%s\n", cycleNumber, error.getErrorNo(), error.getString().retStr());

		return err;
	}
	
	BError cycleStartEvent(BUInt32 cycleNumber){
		BError	err;
		
		dprintf("Event: CycleStartEvent: %d\n", cycleNumber);

		return err;
	}
	
	BError cycleStopEvent(BUInt32 cycleNumber){
		BError	err;
		
		dprintf("Event: CycleStopEvent: %d\n",cycleNumber );
		cycleStopSemaphore.post();
		
		return err;
	}
	
	BError dataEvent(DataInfo dataInfo){
		BError	err;
		
		dprintf("Event: DataEvent: %d\n", dataInfo.numValues);

		return err;
	}
};

BError tmsEventsProcess(TmsProcess& tmsProcess, BString host){
	BError			err;
	static BoapServer	boapServer;
	static TmsEventServer	tmsEventServer(boapServer, "");

	if(err = boapServer.init(host, BoapServer::THREADED)){
		return err;
	}

	boapServer.run(1);

	if(err = tmsProcess.addEventServer(tmsEventServer.name())){
		return err;
	}

	return err;
}

// Loop sending next cycle information
BError tmsControlLoop(TmsControl& tmsControl){
	BError			err;
	BUInt32			cn = 0;
	BString			ct;
	BString			ct1 = "Beam3";
	BString			ct2 = "SigGenBeam3";
	double			t1, t2, tLast;
	double			tStart;
	
	tStart = tLast = getTime();
	while(1){
		// Wait for next cycle information
		cycleStopSemaphore.wait();

		// Set next cycle information
		cn = cn + 1;
#ifndef ZAP
		if(cn & 0x01)
			ct = ct1;
		else
			ct = ct2;
#endif
				
		// Send the next cycle information to the TMS server
		t1 = getTime();
		if(err = tmsControl.setNextCycle(cn, ct)){
			cerr << "Error: " << err.getString() << "\n";
		}
		t2 = getTime();
		printf("Send Next Cycle Info: %f TimeDiff: %f TimeTaken: %fms\n", t2 - tStart, t2 - tLast, (t2 - t1) * 1000.0);
		tLast = t2;
	}	

	return err;
}

int main(int argc, char** argv){
	BError			err;
	BString			host = "localhost";
	TmsControl		tmsControl;
	TmsProcess		tmsProcess;

	if(argc == 2)
		host = argv[1];

	// Connect to the Control service
	if(err = tmsControl.connectService(BString("//") + host + "/tmsControl1")){
		cerr << "Error: " << err.getString() << "\n";
		return 1;
	}

	// Set the network priority high
	if(err = tmsControl.setPriority(BSocket::PriorityHigh)){
		cerr << "Error: " << err.getString() << "\n";
		return 1;
	}

	// Set the TmsServer thread priority high
	if(err = tmsControl.setProcessPriority(PriorityHigh)){
		cerr << "Error: " << err.getString() << "\n";
		return 1;
	}

	// Connect to the Process service
	if(err = tmsProcess.connectService(BString("//") + host + "/tmsProcess1")){
		cerr << "Error: " << err.getString() << "\n";
		return 1;
	}

	// Start processing events
	if(err = tmsEventsProcess(tmsProcess, host)){
		cerr << err.getString() + "\n";
		return 1;	
	}

	if(err = tmsControlLoop(tmsControl)){	
		cerr << "Error: " << err.getString() << "\n";
		return 1;
	}

	return 0;
}
