#include "RS2ASDKManagedWrapper.h"
#include <crtdbg.h>
#include "RS2AManagedEnumPropertyNames.h"
#include "RS2AManagedPropertyVariables.h"
#include "NDTSEnums.h"
#include "RQConstants.h"
//#include "..\NDTSRS2A\NDTSRS2A.h"

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace NDTS::Managed::RS2A;

Snapshot::Snapshot()
{
	pSnapshot = NDTS::RS2A::Factory::getInstance()->getSnapshot();
}

bool Snapshot::getAScan(int bScanIndex, int aScanIndex, [Out]AScanBuffer ^%pBuffer) 
{
	static short pData[NDTS_MAXIMUM_NUMBER_OF_SAMPLES];
	int bufferLength = pSnapshot->returnNumberOfSamples();
	pBuffer = gcnew array<short>(bufferLength);
    
	if (!pSnapshot->getAScan(bScanIndex, aScanIndex, pData, NDTS_MAXIMUM_NUMBER_OF_SAMPLES - 1))
		return false;

	for (int i=0; i < bufferLength; i++)
		pBuffer[i] = pData[i];
	
	return true;
}

bool Snapshot::getGateData(int bScanIndex, int aScanIndex, [Out]IntArray ^%amplitudes, [Out]IntArray ^%depths)
{
    static NDTS::RS2A::GateOutput pResults[NDTS_MAXIMUM_NUMBER_OF_GATES_COMPILE_TIME];
	amplitudes = gcnew array<int>(NDTS_MAXIMUM_NUMBER_OF_GATES_COMPILE_TIME);
	depths = gcnew array<int>(NDTS_MAXIMUM_NUMBER_OF_GATES_COMPILE_TIME);
    
	if (!pSnapshot->getUnPackedGateData(bScanIndex, aScanIndex, pResults, NDTS_MAXIMUM_NUMBER_OF_GATES_COMPILE_TIME))
		return false;
    
	for (int i=0; i < NDTS_MAXIMUM_NUMBER_OF_GATES_COMPILE_TIME; i++)
	{
		amplitudes[i] = pResults[i].amplitudeMetric;
		depths[i] = pResults[i].distanceMetric;
	}

	return true;
}


void Snapshot::getEncoderValues(int bScanIndex, int numberOfEncoders, [Out]IntArray ^%pEncoderValuesArray)
{
	static int pValues[RQ_NUMBER_OF_ENCODERS];
	pEncoderValuesArray = gcnew array<int>(RQ_NUMBER_OF_ENCODERS);
    
	//gcnew can not be passed into c++ function, so use pValues instead
	if (!pSnapshot->getEncoderValues(bScanIndex, numberOfEncoders, pValues))
		return; 
    
	for (int i=0; i < numberOfEncoders; i++)
		pEncoderValuesArray[i] = pValues[i];
}


int Snapshot::getEncoderValue(int bScanIndex, int encoderIndex)
{
	int value;
	if (!pSnapshot->getEncoderValue(bScanIndex, encoderIndex, &value))
		return 0;
	return value;
}


void Snapshot::resetEncoderValue(int encoderIndex)
{
	pSnapshot->resetEncoder(encoderIndex);
}

ErrorLog::ErrorLog()
{
	pErrorLog = NDTS::RS2A::Factory::getInstance()->getErrorLog();
}

String ^ErrorLog::getErrorLogLine(int lineNumber)
{
	static char tempBuf[1000];
	pErrorLog->getErrorLogLine(lineNumber, tempBuf, 998);
	
	String ^s = gcnew String(tempBuf);
	return s;
}

TCG::TCG()
{
	pTcg = NDTS::RS2A::Factory::getInstance()->getTcg();
}
bool TCG::setCurve(TCGBuffer ^%pTCGCurve, int numberOfPointsInCurve)
{
	static int pInt[65537];
	_ASSERTE(numberOfPointsInCurve < 65536);
	for (int i=0; i < numberOfPointsInCurve; i++)
		pInt[i] = pTCGCurve[i];
	return pTcg->setCurve(pInt, numberOfPointsInCurve);
}


bool Test::runUnitTests()
{
	return  NDTS::RS2A::Test::runUnitTests();
}

//bool RootProperty::isInitialised = false;

NDTS::Managed::SCO::Property ^RootProperty::getRootProperty()
{
	if (!isInitialised)
	{
		NDTS::RS2A::Factory::getInstance()->initialise();
		isInitialised = true;
	}
	NDTS::Managed::SCO::Property ^root = gcnew NDTS::Managed::SCO::GroupProperty;
	root->setPropVoid(dynamic_cast<NDTS::SCO::Property*>(NDTS::RS2A::Factory::getInstance()->getRootProperty()));
	return root;
};