// This is the main DLL file.
#include "stdafx.h"
#include "NDTS2100SdkManagedWrapper.h"
#include <crtdbg.h>
#include "NDTS2100ManagedEnumPropertyNames.h"
#include "NDTS2100ManagedPropertyVariables.h"
#include "NDTS2100SDK.h"
//#include "..\NDTSNDTS2100\NDTSNDTS2100.h"

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

Snapshot::Snapshot()
{
	pSnapshot = NDTS::NDTS2100::Factory::getInstance()->getSnapshot();
}
bool Snapshot::getAScan(int cardIndex, int sequenceIndex, int bScanIndex, [Out]AScanBuffer ^%pBuffer) 
{
	static const int localBufferLength = 65536;
	static short pData[localBufferLength];
	int bufferLength = pSnapshot->returnNumberOfAScanSamples(cardIndex, sequenceIndex);
	_ASSERTE(bufferLength < localBufferLength);
	pBuffer = gcnew array<short>(bufferLength);

	if (!pSnapshot->getAScan(cardIndex, sequenceIndex, bScanIndex, pData, bufferLength))
		return false;

	// Todo use an interior_ptr for much faster copying?
   	for (int i=0; i < bufferLength; i++)
		pBuffer[i] = pData[i];

	return true;
}

bool Snapshot::getGateData(int cardIndex, int sequenceIndex, int bScanIndex, [Out] IntArray ^%amplitudes, [Out] IntArray ^%depths) 
{
	const int maxGates = NDTS::NDTS2100::maxGates;
	static NDTS::NDTS2100::GateOutput pResults[maxGates];
	amplitudes = gcnew array<int>(maxGates);
	depths = gcnew array<int>(maxGates);

	if (!pSnapshot->getUnPackedGateData(cardIndex, sequenceIndex, bScanIndex, pResults, maxGates))
		return false;

	for (int i=0; i < maxGates; i++)
	{
		amplitudes[i] = pResults[i].amplitudeMetric;
		depths[i] = pResults[i].distanceMetric;
	}
	return true;
}


void Snapshot::getEncoderValues(int cardIndex, int bScanIndex, [Out] IntArray ^%pEncoderValuesArray)
{
	const int maxEncoders = NDTS::NDTS2100::maxEncoders;
	static int pValues[maxEncoders];
	pEncoderValuesArray = gcnew array<int>(maxEncoders);
	
	
	if (!pSnapshot->getEncoderValues(cardIndex, bScanIndex, pValues, maxEncoders))
		return ;
	for (int i=0; i < maxEncoders; i++)
	{
		pEncoderValuesArray[i] = pValues[i];
	}
}

int Snapshot::getEncoderValue(int cardIndex, int bScanIndex,  int encoderIndex)
{
	static int pValues[NDTS::NDTS2100::maxEncoders];
	if (!pSnapshot->getEncoderValues(cardIndex, bScanIndex, pValues, NDTS::NDTS2100::maxEncoders))
		return 0;

	return pValues[encoderIndex];
}


ErrorLog::ErrorLog()
{
	pErrorLog = NDTS::NDTS2100::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::NDTS2100::Factory::getInstance()->getTcg();
}
bool TCG::setCurve(int cardIndex, int sequenceIndex, 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(cardIndex, sequenceIndex, pInt, numberOfPointsInCurve);
}


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

//bool RootProperty::isInitialised = false;

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

NDTS::Managed::SCO::GroupProperty ^ArrayProperty::getRootGroup()
{
	NDTS::Managed::NDTS2100::PropertyVariables pv;  // = gcnew NDTS::Managed::NDTS2100::PropertyVariables;
	return pv.root;
}

NDTS::Managed::SCO::GroupProperty ^ArrayProperty::getCardGroup(int cardIndex)
{
	NDTS::Managed::NDTS2100::PropertyVariables pv;	// = gcnew NDTS::Managed::NDTS2100::PropertyVariables;
	return pv.cardSettingsGroup[cardIndex];
}

NDTS::Managed::SCO::GroupProperty ^ArrayProperty::getStepGroup(int cardIndex, int stepIndex)
{
	NDTS::Managed::NDTS2100::PropertyVariables pv;	// = gcnew NDTS::Managed::NDTS2100::PropertyVariables;
	return pv.stepSettingsGroup[cardIndex, stepIndex];
}

NDTS::Managed::SCO::GroupProperty ^ArrayProperty::getGateGroup(int cardIndex, int stepIndex, int gateIndex)
{
	NDTS::Managed::NDTS2100::PropertyVariables pv;	// = gcnew NDTS::Managed::NDTS2100::PropertyVariables;
	return pv.gateSettingsGroup[cardIndex, stepIndex, gateIndex];
}