#include "RQTErrorInternal.h"
#include "RQ.h"
#include "RQThreadInternal.h"
#include "RQTError.h"

typedef struct  
{
	RQT_ReturnCode	code ;
	char *			codeString ;
} RQT_Errors ;

RQT_Errors RQT_ApiErrors[] = 
{
	{RQT_OK											, "RQT_OK"},
	{RQT_OutOfMemory								, "RQT_OutOfMemory"}, 
	{RQT_NonFatalError								, "RQT_NonFatalError"}, 
	{RQT_FatalError									, "RQT_FatalError"}, 
	{RQT_ThreadHasShutdown							, "RQT_ThreadHasShutdown"}, 
	{RQT_NoDataAvailable							, "RQT_NoDataAvailable "},
	{RQT_Initialise_AlreadyInititialised			, "RQT_Initialise_AlreadyInititialised"}, 
	{RQT_Initialise_FailedToCreatePLXInterrupt		, "RQT_Initialise_FailedToCreatePLXInterrupt"}, 
	{RQT_SetThreadState_InvalidState				, "RQT_SetThreadState_InvalidState"}, 
	{RQT_SetThreadState_MustNotBeCalledInsideRQLock	, "RQT_SetThreadState_MustNotBeCalledInsideRQLock"}, 
	{RQT_SetThreadState_TimeoutWaitingForThread		, "RQT_SetThreadState_TimeoutWaitingForThread"}, 
	{RQT_SetThreadState_ThreadFailedToAcknowledgeNewState, "RQT_SetThreadState_ThreadFailedToAcknowledgeNewState"}, 
	{RQT_ThreadMain_ReleaseSemaphoreReturnedError	, "RQT_ThreadMain_ReleaseSemaphoreReturnedError	"}, 
	{RQT_BankSwapAndUpdate_TimeOutWaitingForBankSwap, "RQT_BankSwapAndUpdate_TimeOutWaitingForBankSwap"},
	{RQT_GetRawScan_NoDataAvailableOrBuffered		,  "RQT_GetRawScan_NoDataAvailableOrBuffered"},
	{RQT_LastError,															"Unknown"}
} ;

const char * CALL_CONV RQT_GetCodeString(int errorCode)
{
	int i = 0 ;

	while (RQT_ApiErrors[i].code != errorCode && RQT_ApiErrors[i].code != RQT_LastError)
		i++ ;

	return RQT_ApiErrors[i].codeString ;
}


NDTS_Boolean RQT_HandleRQError()
{
	switch(RQ_GetLastErrorSummary())
	{
	case RQES_OK:
	case RQES_NonFatalError:
		return NDTS_BTrue;

	case RQES_OutOfMemory:
		RQT_HandleError(RQT_OutOfMemory);
		return NDTS_BFalse;

	case RQES_FatalError:
	default:
		RQT_HandleError(RQT_FatalError);
		return NDTS_BFalse;
	}
}

RQ_API RQT_ReturnCode  RQT_GetLastError()
{
	return NDTS_GetLastError() ;
}

RQ_API unsigned long RQT_ReturnNumberOfErrorLogLines()
{
	return NDTS_ReturnNumberOfErrorLogLines() ;
}

NDTS_Boolean RQT_GetErrorLogLine(unsigned long lineNumber, char *pMessageBuffer, unsigned long numberOfBytesInMessageBuffer)
{
	return NDTS_GetErrorLogLine(lineNumber, pMessageBuffer, numberOfBytesInMessageBuffer) ;
}

RQ_API NDTS_Boolean RQT_ClearErrorLog() 
{
	return NDTS_ClearErrorLog() ;
}

void RQT_HandleError(RQT_ReturnCode errorCode) 
{
	NDTS_HandleError(errorCode);
}


RQ_ErrorSummary RQ_GetLastErrorSummary(void)
{
	switch(RQ_GetLastError())
	{
	case 	RQ_OK:
		return RQES_OK;
	case RQ_Calibrate_OutOfMemory:
	case RQ_SetCurvedGateData_OutOfMemory:
	case RQ_SetTCGValues_OutOfMemory:
	case RQ_SetPingPongSequenceElement_OutOfMemory:
	case RQ_GetRawScan_MemoryAllocationFail:
	case RQ_GetRawScan_OutOfMemory:
	case RQ_StructuresInitialise_OutOfMemory:
	case RQ_Alloc_OutOfMemory:
	case RQOffline_ExtractCScan_OutOfMemory	:
		return RQES_OutOfMemory;
		break;
	case RQ_GetRawScan_CRCSubSystemInternalError:  // Could make these codes selectablely fatal by the application
	case RQ_GetRawScan_InternalDataFormatError:
	case RQ_GetRawScan_AScanDesynchronisation:
	case RQ_GetRawScan_CScanDesynchronisation:
	case RQ_ReadRawScanBlocks_BadBlockCRC:
	case RQ_GetRawScan_RawScanNotLargeEnoughForData:
	case RQ_WaitForBankSwap_MissingTrigger:
	case RQ_WaitForBankSwap_SampleIncomplete:
	case RQ_SetRequestEarlySampleData_DataFullError:
		return RQES_NonFatalError;
		break;
	default:
		return RQES_FatalError;
		break;
	}
}
