#include <cdevPlatforms.h>
#include <cdevSystem.h>
#include <cdevRequestObject.h>
#include <cdevDevice.h>
#include <cdevGroup.h>
#include <cdevCommon.h>

int callbackCount = 0;

void callback ( int status, void * arg, cdevRequestObject & req, cdevData & data )
	{
	if(status==CDEV_SUCCESS) callbackCount++;
	}
	
const int DEVICE_COUNT  = 9;
const int MESSAGE_COUNT = 9;

int main ( int argc, char ** argv )
	{
	fprintf(stdout, "\n\
=> **********************************************************************\n\
=> * This is program will post a collection of monitors to the monitor  *\n\
=> * server and will then post changes to the attributes.  The program  *\n\
=> * will wait for results to be returned.                              *\n\
=> **********************************************************************\n\n");
	fflush(stdout);
	cdevDevice * deviceList[DEVICE_COUNT];
	cdevRequestObject * reqList[DEVICE_COUNT*MESSAGE_COUNT];
	cdevCallback cb(callback, NULL);
	cdevData     data;
	float        values[DEVICE_COUNT*MESSAGE_COUNT];
	char         msg[255];
	int          deviceCnt;
	int          msgCnt;
	int          repeatCount = (argc>1)?atoi(argv[1]):5;
	
	// *********************************************************************
	// * First get all of the values from the devices and install monitors.
	// *********************************************************************
	for(deviceCnt=0; deviceCnt<DEVICE_COUNT; deviceCnt++)
		{
		sprintf(msg, "device%i", deviceCnt);
		deviceList[deviceCnt] = cdevDevice::attachPtr(msg);
		
		for(msgCnt=0; msgCnt<MESSAGE_COUNT; msgCnt++)
			{
			sprintf(msg, "get attrib%i", msgCnt);
			if(deviceList[deviceCnt]->send(msg, NULL, data)==CDEV_SUCCESS)
				{
				data.get("value", &values[deviceCnt*MESSAGE_COUNT+msgCnt]);
				}
			else	{
				values[deviceCnt*MESSAGE_COUNT+msgCnt] = 0;
				fprintf(stdout, "ERROR : device %s : %s failed\n", deviceList[deviceCnt]->name(), msg);
				}
			sprintf(msg, "monitorOn attrib%i", msgCnt);
			deviceList[deviceCnt]->sendCallback(msg, NULL, cb);
			callbackCount--;
			
			sprintf(msg, "set attrib%i", msgCnt);
			reqList[deviceCnt*MESSAGE_COUNT+msgCnt] = deviceList[deviceCnt]->getRequestObject(msg);
			}		
		}
	
	fprintf(stdout, "=> Sending %i changes to %i monitors\n", repeatCount, DEVICE_COUNT*MESSAGE_COUNT); 

	for(int i = 0; i<repeatCount; i++)
		{
		for(int j=0; j<DEVICE_COUNT*MESSAGE_COUNT; j++)
			{
			values[j]+=1.0;
			data.insert("value", values[j]);
			reqList[j]->sendNoBlock(data, NULL);
			}
		cdevSystem::defaultSystem().pend();
		fprintf(stdout, "%i Change Requests Transmitted\n", (i+1)*DEVICE_COUNT*MESSAGE_COUNT);
		}
	
	while(callbackCount<DEVICE_COUNT*MESSAGE_COUNT*repeatCount) 
		{
		cdevSystem::defaultSystem().pend(1.0);
		fprintf(stdout, "=> %i Monitors received so far...\n", callbackCount);
		}
	fprintf(stdout, "=> %i Monitors have been fired\n", callbackCount); 
	
	// *********************************************************************
	// * Finally, remove all monitors.
	// *********************************************************************
	for(deviceCnt=0; deviceCnt<DEVICE_COUNT; deviceCnt++)
		{
		for(msgCnt=0; msgCnt<MESSAGE_COUNT; msgCnt++)
			{
			sprintf(msg, "monitorOff attrib%i", msgCnt);
			deviceList[deviceCnt]->sendCallback(msg, NULL, cb);
			}
		}
	cdevSystem::defaultSystem().pend();
	
	return 0;
	}
