// ======================================================================================
//
//	Copyright (c) 2017 Hamamatsu Photonics K.K.
//
//	Project		: MS Minispectrometer Console Sample Application(C++/CLI)
//	
//	.NET Framework	: .NET Framework 3.5
//
//=======================================================================================

//-----------------------------------------------------------------------------
// include
//-----------------------------------------------------------------------------
#include "stdafx.h"

//-----------------------------------------------------------------------------
// define
//-----------------------------------------------------------------------------
#define D_MAX_CAMERA_DEVICE		8	//Max MiniSpec Count
#define D_SERIAL_NUMBERSIZE		16	//Serial Number Size
#define D_INTEGRATION_DATASIZE	256	//Data Size
#define D_REPEAT_COUNT			5	//Repeat Count
//-----------------------------------------------------------------------------
// namespace
//-----------------------------------------------------------------------------
using namespace System;
using namespace System::Threading;
using namespace HMSUSB2_DLL;

//-----------------------------------------------------------------------------
// function
//-----------------------------------------------------------------------------
long	StartMeasure(HMSUSB2^ hHMSUSB2);
bool	DisplayData(array<unsigned short>^ aryusImageData);

//-----------------------------------------------------------------------------
// main function
//-----------------------------------------------------------------------------
int main(array<System::String ^> ^args)
{
	long lReturn = 0;
	HMSUSB2^ hHMSUSB2 = nullptr;

	Console::WriteLine(L"Hamamatsu Minispectrometer for MS Sample Application");

	try{
		hHMSUSB2 = gcnew HMSUSB2();
	}
	catch (...){
		return 1;
	}
	//Start measurement
	lReturn = StartMeasure(hHMSUSB2);

	//result
	if (lReturn != (long)E_HMSErrCode::HMS_success){
		return 1;
	}

	return 0;
}

//-----------------------------------------------------------------------------
// Measurement start function
//-----------------------------------------------------------------------------
long StartMeasure(HMSUSB2^ hHMSUSB2)
{
	long	lReturn = 0;
	int		nRepeatCount = 0;
	String^ strDevice = nullptr;
	unsigned short 	usNum = 0;
	UInt64	ulIntegrationTime = 0;
	array<String^>^ aryConnList = nullptr;
	array<unsigned short>^ aryusIntegrationData = nullptr;

	//Argument error check
	if (hHMSUSB2 == nullptr){
		return (long)E_HMSErrCode::HMS_unsuccess;
	}

	Console::WriteLine("Opening Device............");

	//Initialization
	lReturn = hHMSUSB2->HMS_initialize();
	if (lReturn != (long)E_HMSErrCode::HMS_success){
		Console::WriteLine("Error code 0x{0:x04}: Dll Can not be Initialized.", lReturn);
		return lReturn;
	}
	//Device ID storage area allocation
	try{
		aryConnList = gcnew array<String^>(D_MAX_CAMERA_DEVICE);
	}
	catch (OutOfMemoryException^){
		return (long)E_HMSErrCode::HMS_unsuccess;
	}
	//Get connected device list
	lReturn = hHMSUSB2->HMS_getDeviceList(aryConnList, usNum);
	if (lReturn != (long)E_HMSErrCode::HMS_success){
		Console::WriteLine("Error code 0x{0:x04}: Module Connection list failed.", lReturn);
		return lReturn;
	}
	if (usNum > 0){
		strDevice = aryConnList[0];
	}
	else{
		Console::WriteLine("Module Connection list Nothing.");
		return lReturn;
	}
	//Open device
	lReturn = hHMSUSB2->HMS_openDevice(strDevice);
	if (lReturn != (long)E_HMSErrCode::HMS_success){
		Console::WriteLine("Error code 0x{0:x04}: Device can not be open.", lReturn);
		return lReturn;
	}
	//Check device
	lReturn = hHMSUSB2->HMS_checkDevice(strDevice);
	if (lReturn != (long)E_HMSErrCode::HMS_success){
		Console::WriteLine("Error code 0x{0:x04}: Device Error.", lReturn);
		return lReturn;
	}
	if (lReturn == (long)E_HMSErrCode::HMS_success){

		//Get Integration Time
		lReturn = hHMSUSB2->HMS_getIntegrationTime(strDevice, ulIntegrationTime);
		if (lReturn != (long)E_HMSErrCode::HMS_success){
			Console::WriteLine("Error code 0x{0:x04}: HMS_getIntegrationTime failed.", lReturn);
			return lReturn;
		}
		//Data acquisition is reapeated 5 times while determining status of capture
		do{
			try{
				//Allocate a buffer to store data
				aryusIntegrationData = gcnew array<unsigned short>(D_INTEGRATION_DATASIZE);
				//Get data from device
				lReturn = hHMSUSB2->HMS_getSensorData(strDevice, ulIntegrationTime, aryusIntegrationData);
				if (lReturn != (long)E_HMSErrCode::HMS_success){
					Console::WriteLine("Error code 0x{0:x04}: HMS_getSensorData failed.", lReturn);
					return lReturn;
				}
				//Display data
				DisplayData(aryusIntegrationData);

				if (aryusIntegrationData != nullptr){
					delete[] aryusIntegrationData;
					aryusIntegrationData = nullptr;
				}
			}
			catch (OutOfMemoryException^){
				return (long)E_HMSErrCode::HMS_unsuccess;
			}
			nRepeatCount++;
			Thread::Sleep(1);
		} while (nRepeatCount < D_REPEAT_COUNT);

		//Close device
		lReturn = hHMSUSB2->HMS_closeDevice(strDevice);
		if (lReturn != (long)E_HMSErrCode::HMS_success){
			Console::WriteLine("Error code 0x{0:x04}: Device can not be closed.", lReturn);
			return lReturn;
		}

		//Uninitialization
		lReturn = hHMSUSB2->HMS_unininitalize();
		if (lReturn != (long)E_HMSErrCode::HMS_success){
			Console::WriteLine("Error code 0x{0:x04}: Uninitialize failed.", lReturn);
		}
	}

	return lReturn;
}

//-----------------------------------------------------------------------------
// Display data function
//-----------------------------------------------------------------------------
bool DisplayData(array<unsigned short>^ aryusImageData)
{
	String^	strData = nullptr;
	int		nData = 0;
	//Output data to the console
	for (int nIdx = 0; nIdx < aryusImageData->Length; nIdx++){
		nData = aryusImageData[nIdx];
		strData = String::Format("{0:X04} ", nData);
		Console::Write(strData);
		strData = L"";
	}
	Console::WriteLine(L"");
	return true;
}