#include "RQSnapshotInternal.h"
#include "RQThreadInternal.h"
#include "RQTErrorInternal.h"
#include "RQRawScanProtected.h"

#include <crtdbg.h>

// Called on data available.  RQ_Lock and threadCriticalSection lock are already held.
NDTS_Boolean RQT_UpdateCollect(unsigned long cardIndex)
{
	RQT_State *pThreadState = RQT_ReturnThreadStatePointer(cardIndex) ;
	RQ_RawScan *pRawScan ;
	// unsigned long writeBank;
	NDTS_Boolean isOk = NDTS_BTrue ;
	static int consecutiveRawScanFailures = 0 ;

	if (!pThreadState) 
		return NDTS_BFalse; 

	if(pThreadState->collectState.rawScansInitialised == 0)
	{
		RQ_InitialiseRawScan(&(pThreadState->collectState.rawScans[0]));
		pThreadState->collectState.rawScansInitialised = 1 ;
	}

	// writeBank = (pThreadState-> collectState.readBank) ? 0 : 1 ;
	pRawScan = &(pThreadState->collectState.rawScans[0/*writeBank*/]) ;
	if(pRawScan->numberOfBScans == 0)
	{
		// The raw scan in the write bank is empty. So fetch the raw scan straight into it.
		isOk = RQ_GetRawScanNoBankSwap(cardIndex, pRawScan) ;
	}
	else
	{
		// The write bank contains a valid raw scan. Read the raw scan from the card and add
		// it's data to the raw scan in the write bank.
		RQ_RawScan collectedRawScan ;

		RQ_InitialiseRawScan(&collectedRawScan) ;

		isOk = RQ_GetRawScanNoBankSwap(cardIndex, &collectedRawScan) ;
		if(isOk)
		{
if(((RQ_RawScanProtected*)(collectedRawScan.pInternal))->pDataB)
{
			_ASSERTE(((RQ_RawScanProtected*)(collectedRawScan.pInternal))->pDataB);
			RQ_MoveRawScanDataToRawScan(pRawScan, &collectedRawScan) ;
}
		}

		// Don't need the temporary raw scan anymore.
		RQ_UninitialiseRawScan(&collectedRawScan) ;
	}

	if(isOk)
	{
		consecutiveRawScanFailures = 0 ;

//		isOk = RQ_RequestBankSwap(cardIndex) ;
		isOk = RQ_IndicateSampleDataDownloaded(cardIndex) ;
		if(!isOk) 
		{
			if (!RQT_HandleRQError()) 
				return NDTS_BFalse;
		}
	}
	else
	{
		RQ_ReturnCode rc = RQ_GetLastError();
 		if (rc == RQ_GetRawScan_InternalDataFormatError || 
			rc == RQ_GetRawScan_AScanDesynchronisation ||
			rc == RQ_GetRawScan_CScanDesynchronisation ||
			rc == RQ_GetRawScan_CRCSubSystemInternalError ||
			rc == RQ_ReadRawScanBlocks_BadBlockCRC ||
			rc == RQ_GetRawScan_RawScanNotLargeEnoughForData)
		{
			// The block is corrupted - maybe by scanning too fast.  Drop this block but don't abort the scan
			// All the above cases are caused by firmware issues that could be resolved sometime in the future
			if (++consecutiveRawScanFailures > 3 ||	rc == RQ_WaitForBankSwap_MissingTrigger)
			{
				RQ_ResetFirmware(cardIndex) ;
				consecutiveRawScanFailures = 0 ;

				return NDTS_BTrue ;
			}	
		}
		else if (rc == RQ_WaitForBankSwap_MissingTrigger || rc == RQ_WaitForBankSwap_SampleIncomplete)
			return NDTS_BFalse ;
		else
			return NDTS_BFalse ;

		if (!RQT_HandleRQError()) 
			return NDTS_BFalse ;
	}

	return NDTS_BTrue;
}

// Called from UpdateSampleParameters in rq.dll.  RQ_Lock() will be on before this is called.
void RQT_UpdateParametersCollectHook(unsigned long cardIndex)
{
	RQT_State *pThreadState = RQT_ReturnThreadStatePointer(cardIndex);
	if (!pThreadState) return ;

	// This function is (indirectly?) called by a function in RQ.dll and is, therefore, enclosed in locks.

	// Code needs to be added here if the shape of raw scan in this DLLis different from
	// the settings in the application / RQ.dll eg the range has changed between the application
	// going into RQT.dll to collect a raw scan and it getting one.


	RQ_AllocCardMemoryPools(cardIndex) ;

	if(pThreadState->collectState.rawScansInitialised)
		_ASSERTE(pThreadState->collectState.rawScans[0].numberOfBScans == 0) ;
}

		/*
		RQ_ReturnCode rc = RQ_GetLastError();
 		if (rc == RQ_GetRawScan_InternalDataFormatError || 
			rc == RQ_GetRawScan_AScanDesynchronisation ||
			rc == RQ_GetRawScan_CScanDesynchronisation ||
			rc == RQ_GetRawScan_CRCSubSystemInternalError ||
			rc == RQ_ReadRawScanBlocks_BadBlockCRC ||
			rc == RQ_GetRawScan_RawScanNotLargeEnoughForData ||  // Remove after threading integration
			(rc == RQ_WaitForBankSwap_MissingTrigger && getIsCScanning()) ||  
			(rc == RQ_WaitForBankSwap_SampleIncomplete && getIsCScanning()))
		{
			// The block is corrupted - maybe by scanning too fast.  Drop this block but don't abort the scan
			// All the above cases are caused by firmware issues that could be resolved sometime in the future
			if (++consecutiveRawScanFailures > 3 ||
				rc == RQ_WaitForBankSwap_MissingTrigger)
			{
				resetFirmware() ;
				consecutiveRawScanFailures = 0 ;
				NDTSSysLogSingleton *pSysLog = NDTSSysLogSingleton::getInstance() ;
				pSysLog->writeString(NDTSSysLogSingleton::warning, "Resetting RapiDAQ firmware due to 3 consecutive failures\n") ;
			}	
			logLastSDKFailure(false) ;
			RQ_FreeRawScanData(pNextRawScan, RQ_FRSOAll) ;

			pNextRawScan = 0 ;
			doesRawScanContainData = false ;
			return ;
		}
		else if ((rc == RQ_WaitForBankSwap_MissingTrigger || rc == RQ_WaitForBankSwap_SampleIncomplete) 
			&& !getIsCScanning())
		{
			// When we stop scanning we often switch modes (from encoder-driven to software-driven) during a BSCAN,
			// which can cause the error code RQ_GetRawScan_SampleIncomplete to be returned.
			// We can safely ignore this.
			doesRawScanContainData = false ;
			return ;
		}  
		else
		{   
			logLastSDKFailure() ;

			doesRawScanContainData = false ;
			// Over repped.  Should have trapped settings that caused this in decideRangeBasedSetting()
			if (rc == RQ_WaitForBankSwap_TriggerOccurredBeforeProcessComplete)
			{
				throw new NDTSExceptionGenericAcquisitionBoardOverRepped() ;
			} 
			if (rc == RQ_PerformDMATransfer_PCIDmaBlockTransferFail)
			{
				throw new NDTSExceptionRapiDAQBoardUnrecoverableError(boardIndex) ;
			}
			else
			{
				throw new NDTSExceptionRapiDAQBoardGetCScanFail() ;
			}
		}*/
