#include <ctype.h>
#include <signal.h>

#include <cdevSystem.h>
#include <cdevRequestObject.h>
#include <cdevDevice.h>
#include <cdevGroup.h>
#include <cdevCommon.h>
#include <testMessages.cc>

int      fouled       = 0;
int      expectedHits = 0;
int      hits         = 0;
unsigned totalCount   = 0;

void callback ( int status, void * arg, cdevRequestObject &, cdevData & data)
	{
	hits++;
	if(status!=CDEV_SUCCESS)
		{
		printf("ERROR: Transmission failure of %i\n", (int)arg);
		}
	else
		{
		if(data!=*TestMessage[(int)arg].getData())
			{
			fouled = 1;
			printf("ERROR: Mismatch on entry %i - Inbound data differs from expected\n", 
				(int)arg);
			printf("----------------------------- INBOUND DATA -----------------------------\n");
			data.asciiDump();
			printf("----------------------------- EXPECTED DATA ----------------------------\n");
			TestMessage[(int)arg].getData()->asciiDump(); 
			}
		else
			{
			totalCount++;
			if(totalCount%100==0)
				{
				printf("Transmission %i still matches correctly\n", totalCount);
				}
			}
		}
	}
	
	
int main(int argc, char ** argv)
{
createTestMessages();
int maxCount        = 0;
int group1          = TestMessageCount/3;
int group2          = group1+group1;

cdevRequestObject &tReq = cdevRequestObject::attachRef(TestMessage[TestMessageIndex].getDeviceList()[0], TestMessage[TestMessageIndex].getMessage());
tReq.setContext(*TestMessage[0].getContext());

if(argc>1) maxCount = atoi(argv[1]);

while(!fouled && (!maxCount ||  maxCount<totalCount))
	{
	hits         = 0;
	expectedHits = 0;

	for(TestMessageIndex = 0; TestMessageIndex<group1; TestMessageIndex++)
		{
		int                 mismatch = 0;
		cdevData            data;
		cdevRequestObject * req = cdevRequestObject::attachPtr(TestMessage[TestMessageIndex].getDeviceList()[0], TestMessage[TestMessageIndex].getMessage());
		req->setContext(*TestMessage[TestMessageIndex].getContext());

		if(req->send(TestMessage[TestMessageIndex].getData(), &data)==CDEV_SUCCESS)
			{
			if(data!=*TestMessage[TestMessageIndex].getData())
				{
				fouled = -1;
				printf("ERROR: Mismatch on entry %i - Inbound data differs from expected\n", 
					TestMessageIndex);
				printf("----------------------------- INBOUND DATA -----------------------------\n");
				data.asciiDump();
				printf("----------------------------- EXPECTED DATA ----------------------------\n");
				TestMessage[TestMessageIndex].getData()->asciiDump(); 
				}
			else
				{
				totalCount++;
				if(totalCount%100==0)
					{
					printf("Transmission %i still matches correctly\n", totalCount);
					}
				}
			}
		else 	{
			printf("ERROR: Transmission failure of %i\n",
				TestMessageIndex);
			}
		}

	for( ; TestMessageIndex<group2; TestMessageIndex++)
		{
		cdevCallback        cb(callback, (void *)TestMessageIndex); 	
		int                 mismatch = 0;
		cdevData            data;
		cdevRequestObject * req = cdevRequestObject::attachPtr(TestMessage[TestMessageIndex].getDeviceList()[0], TestMessage[TestMessageIndex].getMessage());
		req->setContext(*TestMessage[TestMessageIndex].getContext());

		if(req->sendCallback(TestMessage[TestMessageIndex].getData(), cb)!=CDEV_SUCCESS)
			{
			fouled = -1;
			printf("ERROR: Transmission failure of %i\n",
				TestMessageIndex);
			}
		else expectedHits++;
		}
	
	for(int retryCnt=0; hits<expectedHits && retryCnt<1000; retryCnt++)
		{
		cdevSystem::defaultSystem().poll();
		}

	if(hits<expectedHits)
		{
		printf("ERROR: Processed only %i of %i callback requests after %i attempts\n", hits, expectedHits, retryCnt);
		}
			
	cdevData * outputData = new cdevData[TestMessageCount - (group2)];
	cdevGroup  group;
	
	group.start();
	for(int dataIdx=0; TestMessageIndex<TestMessageCount; TestMessageIndex++, dataIdx++)
		{
		int                 mismatch = 0;
		cdevData            data;
		cdevRequestObject * req = cdevRequestObject::attachPtr(TestMessage[TestMessageIndex].getDeviceList()[0], TestMessage[TestMessageIndex].getMessage());
		req->setContext(*TestMessage[TestMessageIndex].getContext());

		if(req->sendNoBlock(TestMessage[TestMessageIndex].getData(), outputData[dataIdx])!=CDEV_SUCCESS)
			{
			fouled = -1;
			printf("ERROR: Transmission failure of %i\n",
				TestMessageIndex);
			}
		}
	group.end();
	
	for(int grpRetryCnt=0; !group.allFinished() && grpRetryCnt<1000; grpRetryCnt++)
		{
		group.poll();
		}
		
	if(!group.allFinished())
		{
		printf("ERROR: Failed to process all group requests after %i attempts\n", grpRetryCnt);
		}
		
	for(dataIdx=0, TestMessageIndex=group2; TestMessageIndex<TestMessageCount; TestMessageIndex++, dataIdx++)
		{
		if(outputData[dataIdx]!=*TestMessage[TestMessageIndex].getData())
			{
			fouled = -1;
			printf("ERROR: Mismatch on entry %i - Inbound data differs from expected\n", 
				TestMessageIndex);
			printf("----------------------------- INBOUND DATA -----------------------------\n");
			outputData[dataIdx].asciiDump();
			printf("----------------------------- EXPECTED DATA ----------------------------\n");
			TestMessage[TestMessageIndex].getData()->asciiDump(); 
			}
		else 
			{
			totalCount++;
			if(totalCount%100==0)
				{
				printf("Transmission %i still matches correctly\n", totalCount);
				}
			}
		}	
	delete [] outputData;
	}
return 1;
}
