#include "RawScanCardBlockDescriptionsProtected.h"
#include "RawScanProtected.h"
#include "RawScanError.h"
#include <crtdbg.h>
#include "RawScanInternal.h"

/*
These functions can be optimized. The card block descriptions are used only used to read
the data from the card, after which they are destroyed. They could, however, be used for the
next call to GetRawScan(). 
*/

NDTS_Boolean CALL_CONV RawScan_CreateRawScanBScanDescriptions(NDTS_RawScan *pRawScan, RawScan_CardBlockDescription **ppDescriptions, unsigned long *pNumberOfDescriptions)
{
	unsigned long aScanIndex, bScanIndex ;
	RawScan_CardBlockDescription *pCardBlockDescriptionIt ;
	unsigned long bytesPerAScanSample, aScanHeaderSize, trailerSize ;
	RawScan_RawScanProtected *pRawInternal = RawScan_ReturnRawScanInternal(pRawScan);

	// Preconditions.
	_ASSERTE(pRawScan) ;
	_ASSERTE(ppDescriptions) ;

	bytesPerAScanSample = RawScan_ReturnBytesPerSample(pRawScan->sampleSize) ;
	aScanHeaderSize = RawScan_ReturnRawScanAScanHeaderSize(pRawScan) ;
	trailerSize = RawScan_ReturnRawScanBScanTrailerSize(pRawScan) ;

	// Allocate a block of memory to hold all the card block descriptions.
	*pNumberOfDescriptions = pRawScan->numberOfFullBScans* RawScan_ReturnRawScanBScanMemoryBlockListSize(pRawScan) ;
	*ppDescriptions = MemoryFactory_Alloc(sizeof(RawScan_CardBlockDescription) * (*pNumberOfDescriptions)) ;
	if(!(*ppDescriptions)) 
	{
		RawScan_HandleError(RawScan_Alloc_OutOfMemory) ;
		return NDTS_BFalse ; 
	}

	pCardBlockDescriptionIt = *ppDescriptions ;

	for(bScanIndex = 0; bScanIndex < pRawScan->numberOfFullBScans; ++bScanIndex)
	{
		for(aScanIndex = 0; aScanIndex < pRawScan->numberOfAScansInBScan; ++aScanIndex)
		{
			// A-scan header.
			pCardBlockDescriptionIt->size = aScanHeaderSize ;
			pCardBlockDescriptionIt->flags = 0 ;
			pCardBlockDescriptionIt++ ;

			// A-scan body.
			pCardBlockDescriptionIt->size = pRawScan->aScanSampleValuesThisStep[aScanIndex] * bytesPerAScanSample ;
			pCardBlockDescriptionIt->flags = (pRawInternal->isCRCCheckPresent == NDTS_BTrue) ? RawScan_CBDIsCRCCheckPresent : 0 ;
			pCardBlockDescriptionIt++ ;
		}

		// B-scan trailer.
		pCardBlockDescriptionIt->size = trailerSize ;
		pCardBlockDescriptionIt->flags = 0 ; 
		pCardBlockDescriptionIt++ ;
	}

	return NDTS_BTrue ;
}

NDTS_Boolean CALL_CONV RawScan_CreateRawGateValueDescriptions(NDTS_RawScan *pRawScan, RawScan_CardBlockDescription **ppDescriptions, unsigned long *pNumberOfDescriptions)
{
	RawScan_CardBlockDescription *pCardBlockDescriptionIt ;
	unsigned long trailerSize, bScanIndex ;
	RawScan_RawScanProtected *pRawInternal = RawScan_ReturnRawScanInternal(pRawScan);

	// Preconditions.
	_ASSERTE(pRawScan) ;
	_ASSERTE(ppDescriptions) ;

	trailerSize = RawScan_ReturnRawScanGateValuesTrailerSize(pRawScan) ;

	// Allocate a block of memory to hold all the card block descriptions.
	*pNumberOfDescriptions = pRawScan->numberOfBScans * RawScan_ReturnRawScanGateValuesMemoryBlockListSize(pRawScan) ;
	*ppDescriptions = MemoryFactory_Alloc(sizeof(RawScan_CardBlockDescription) * (*pNumberOfDescriptions)) ;
	if(!(*ppDescriptions) )
	{
		RawScan_HandleError(RawScan_Alloc_OutOfMemory) ;
		return NDTS_BFalse ; 
	}

	pCardBlockDescriptionIt = *ppDescriptions ;

	for(bScanIndex = 0; bScanIndex < pRawScan->numberOfBScans; ++bScanIndex)
	{
		// Gate values body.
		pCardBlockDescriptionIt->size = pRawInternal->gateBytesPerBScan - trailerSize - RawScan_ReturnRawScanCRCSize(pRawScan) ;
		pCardBlockDescriptionIt->flags = (pRawInternal->isCRCCheckPresent == NDTS_BTrue) ? RawScan_CBDIsCRCCheckPresent : 0 ;
		pCardBlockDescriptionIt++ ;

		// Gate values trailer.
		if(trailerSize > 0)
		{
			pCardBlockDescriptionIt->size = trailerSize ;
			pCardBlockDescriptionIt->flags = 0 ; 
			pCardBlockDescriptionIt++ ;
		}		
	}

	return NDTS_BTrue ;
}

RAW_SCAN_API void CALL_CONV RawScan_FreeRawDescriptions(RawScan_CardBlockDescription *pDescriptions)
{
	MemoryFactory_Free(pDescriptions); 
}
