using System;
using System.Runtime.InteropServices;
using BioAPI.include.bioapi_type;
using BioAPI.include.bioapi_schema;

namespace BioAPI.framework.h_layer
{
	public class bioapi_api
	{
		public static BioAPI_RETURN BioAPI_EnumModules(
			BioAPI_BSP_SCHEMA [] BspSchemaArray,		// [in, out]
			uint ArraySize,								// [in]
			ref uint ElementsNeeded,					// [out]
			ref uint NumElementsReturned)				// [out]
		{
			BioAPI_RETURN bReturn;

			if (BspSchemaArray == null) 
			{ 
				bReturn = BioAPIWin32.BioAPI_EnumModules(null, ArraySize, 
					ref ElementsNeeded, ref NumElementsReturned);
			} 
			else
			{
				BioAPI_BSP_SCHEMA_MARSHAL [] outputArray = new BioAPI_BSP_SCHEMA_MARSHAL[ArraySize];
				bReturn = BioAPIWin32.BioAPI_EnumModules(outputArray, ArraySize, 
					ref ElementsNeeded, ref NumElementsReturned);
				for (int i = 0; i < NumElementsReturned; i++)
				{
					if (BspSchemaArray[i] == null) BspSchemaArray[i] = new BioAPI_BSP_SCHEMA();
					outputArray[i].Unmarshal(BspSchemaArray[i]);
				}
			}
			return bReturn;
		}


		public static BioAPI_RETURN BioAPI_Enroll(
			BioAPI_HANDLE ModuleHandle,			// [in]
			BioAPI_BIR_PURPOSE Purpose,			// [in]
			BioAPI_INPUT_BIR StoredTemplate,	// [in/optional]
			ref BioAPI_BIR_HANDLE NewTemplate,	// [out]
			BioAPI_DATA Payload,				// [in/optional]
			int Timeout,						// [in]
			ref BioAPI_BIR_HANDLE AuditData)	// [out/optional]
		{
			BioAPI_RETURN bReturn;
			BioAPI_INPUT_BIR_Marshal mStoredTemplate = null;
			IntPtr ptrPayload = IntPtr.Zero;
			IntPtr ptrAuditData = IntPtr.Zero;
			int len = 0;

			if (StoredTemplate != null) 
			{ mStoredTemplate = new BioAPI_INPUT_BIR_Marshal(StoredTemplate); }
			if (Payload != null) 
			{ ptrPayload = Payload.DoMarshal(ref len); }

			if (AuditData >= (BioAPI_BIR_HANDLE) 0) 
			{ ptrAuditData = BioAPIWin32.MarshalInt32((int) AuditData); }


			bReturn = BioAPIWin32.BioAPI_Enroll(
				ModuleHandle,
				Purpose,
				mStoredTemplate,
				ref NewTemplate,
				ptrPayload,
				Timeout,
				ptrAuditData);

			//if (ptrStoredTemplate != IntPtr.Zero) Marshal.FreeCoTaskMem( ptrStoredTemplate );
			if (ptrPayload != IntPtr.Zero) Marshal.FreeCoTaskMem( ptrPayload );
			if (ptrAuditData != IntPtr.Zero) 
			{ AuditData = (BioAPI_BIR_HANDLE) BioAPIWin32.UnmarshalInt32(ptrAuditData, true); }

			return bReturn;
		}


		public static BioAPI_RETURN BioAPI_Capture(
			BioAPI_HANDLE ModuleHandle,			// [in]
			BioAPI_BIR_PURPOSE Purpose,			// [in]
			ref BioAPI_BIR_HANDLE CapturedBIR,	// [out]
			int Timeout,						// [in]
			ref BioAPI_BIR_HANDLE AuditData)	// [out/optional]
		{
			BioAPI_RETURN bReturn;
			IntPtr ptrAuditData = IntPtr.Zero;

			if (AuditData >= (BioAPI_BIR_HANDLE) 0) 
			{ ptrAuditData = BioAPIWin32.MarshalInt32((int) AuditData); }

			bReturn =  BioAPIWin32.BioAPI_Capture(
				ModuleHandle,
				Purpose,
				ref CapturedBIR,
				Timeout,
				ptrAuditData);

			if (ptrAuditData != IntPtr.Zero) 
			{ AuditData = (BioAPI_BIR_HANDLE) BioAPIWin32.UnmarshalInt32(ptrAuditData, true); }

			return bReturn;

		}

		public static BioAPI_RETURN BioAPI_Process(
			BioAPI_HANDLE ModuleHandle,			// [in]
			BioAPI_INPUT_BIR CapturedBIR,		// [in]
			ref BioAPI_BIR_HANDLE ProcessedBIR)	// [out]
		{
			BioAPI_RETURN bReturn;
			BioAPI_INPUT_BIR_Marshal mCapturedBIR = null;

			if (CapturedBIR != null) 
			{ mCapturedBIR = new BioAPI_INPUT_BIR_Marshal(CapturedBIR); }

			bReturn = BioAPIWin32.BioAPI_Process(
				ModuleHandle,
				mCapturedBIR,
				ref ProcessedBIR);

			if (mCapturedBIR != null) mCapturedBIR.Dispose();
			return bReturn;
		}

		public static BioAPI_RETURN BioAPI_VerifyMatch(
			BioAPI_HANDLE ModuleHandle,				//	[in]
			ref BioAPI_FAR MaxFARRequested,			//	[in]
			ref BioAPI_FRR MaxFRRRequested,			//	[in/optional]
			ref BioAPI_BOOL FARPrecedence,			//	[in]
			BioAPI_INPUT_BIR ProcessedBIR,			//	[in]
			BioAPI_INPUT_BIR StoredTemplate,		//	[in]
			ref BioAPI_BIR_HANDLE AdaptedBIR,		//	[out/optional]
			ref BioAPI_BOOL Result,					//	[out]
			ref BioAPI_FAR FARAchieved,				//	[out]
			ref BioAPI_FRR FRRAchieved,				//	[out/optional]
			BioAPI_DATA Payload)					//	[out/optional]
		{
			BioAPI_RETURN bReturn = BioAPI_RETURN.BioAPI_OK;
			IntPtr ptrMaxFRRRequested = IntPtr.Zero;
			IntPtr ptrAdaptedBIR = IntPtr.Zero;
			IntPtr ptrFRRAchieved = IntPtr.Zero;
			BioAPI_INPUT_BIR_Marshal mProcessedBIR = null;
			BioAPI_INPUT_BIR_Marshal mStoredTemplate = null;

			if (MaxFRRRequested >= (BioAPI_FRR) 0) 
			{ ptrMaxFRRRequested = BioAPIWin32.MarshalInt32((int) MaxFRRRequested); }

			if (ProcessedBIR != null) 
			{ mProcessedBIR = new BioAPI_INPUT_BIR_Marshal(ProcessedBIR); }
			if (StoredTemplate != null) 
			{ mStoredTemplate = new BioAPI_INPUT_BIR_Marshal(StoredTemplate); }
			if (AdaptedBIR >= (BioAPI_BIR_HANDLE) 0) 
			{ ptrAdaptedBIR = BioAPIWin32.MarshalInt32((int) AdaptedBIR); }

			if (FRRAchieved >= (BioAPI_FRR) 0) 
			{ ptrFRRAchieved = BioAPIWin32.MarshalInt32((int) FRRAchieved); }

			try 
			{
				bReturn = BioAPIWin32.BioAPI_VerifyMatch(
					ModuleHandle,				//	[in]
					ref MaxFARRequested,		//	[in]
					ptrMaxFRRRequested,			//	[in/optional]
					ref FARPrecedence,			//	[in]
					mProcessedBIR,				//	[in]
					mStoredTemplate,			//	[in]
					ptrAdaptedBIR,				//	[out/optional]
					ref Result,					//	[out]
					ref FARAchieved,			//	[out]
					ptrFRRAchieved,				//	[out/optional]
					Payload);					//	[out/optional]
			}
			catch (Exception ex) 
			{	
				Console.WriteLine ("BioAPIWin32.BioAPI_VerifyMatch Exception: \n\tError Message = " + ex.Message);
			}
			finally 
			{	
				if (ptrMaxFRRRequested != IntPtr.Zero) Marshal.FreeCoTaskMem( ptrMaxFRRRequested );
				if (ptrAdaptedBIR != IntPtr.Zero) 
				{ AdaptedBIR = (BioAPI_BIR_HANDLE) BioAPIWin32.UnmarshalInt32(ptrAdaptedBIR, true); }

				if (ptrFRRAchieved != IntPtr.Zero) 
				{ FRRAchieved = (BioAPI_FRR) BioAPIWin32.UnmarshalInt32(ptrFRRAchieved, true); }
			}
			return bReturn;
		}

		public static  BioAPI_RETURN BioAPI_Verify(
			BioAPI_HANDLE ModuleHandle,				//	[in]
			ref BioAPI_FAR MaxFARRequested,			//	[in]
			ref BioAPI_FRR MaxFRRRequested,			//	[in/optional]
			ref BioAPI_BOOL FARPrecedence,			//	[in]
			BioAPI_INPUT_BIR StoredTemplate,		//	[in]
			ref BioAPI_BIR_HANDLE AdaptedBIR,		//	[out/optional]
			ref BioAPI_BOOL Result,					//	[out]
			ref BioAPI_FAR FARAchieved,				//	[out]
			ref BioAPI_FRR FRRAchieved,				//	[out/optional]
			BioAPI_DATA Payload,					//	[out/optional]
			int Timeout,							//	[in]
			ref BioAPI_BIR_HANDLE AuditData)		//  [out/optional]
		{
			BioAPI_RETURN bReturn = BioAPI_RETURN.BioAPI_OK;
			IntPtr ptrMaxFRRRequested = IntPtr.Zero;
			IntPtr ptrAdaptedBIR = IntPtr.Zero;
			IntPtr ptrFRRAchieved = IntPtr.Zero;
			BioAPI_INPUT_BIR_Marshal mStoredTemplate = null;
			IntPtr ptrAuditData = IntPtr.Zero;

			if (MaxFRRRequested >= (BioAPI_FRR) 0) 
			{ ptrMaxFRRRequested = BioAPIWin32.MarshalInt32((int) MaxFRRRequested); }

			if (StoredTemplate != null) 
			{ mStoredTemplate = new BioAPI_INPUT_BIR_Marshal(StoredTemplate); }	
	
			if (AdaptedBIR >= (BioAPI_BIR_HANDLE) 0) 
			{ ptrAdaptedBIR = BioAPIWin32.MarshalInt32((int) AdaptedBIR); }

			if (FRRAchieved >= (BioAPI_FRR) 0) 
			{ ptrFRRAchieved = BioAPIWin32.MarshalInt32((int) FRRAchieved); }

			if (AuditData >= (BioAPI_BIR_HANDLE) 0) 
			{ ptrAuditData = BioAPIWin32.MarshalInt32((int) AuditData); }

			try 
			{
				bReturn = BioAPIWin32.BioAPI_Verify(
					ModuleHandle,				//	[in]
					ref MaxFARRequested,		//	[in]
					ptrMaxFRRRequested,			//	[in/optional]
					ref FARPrecedence,			//	[in]
					mStoredTemplate,			//	[in]
					ptrAdaptedBIR,				//	[out/optional]
					ref Result,					//	[out]
					ref FARAchieved,			//	[out]
					ptrFRRAchieved,				//	[out/optional]
					Payload,					//	[out/optional]
					Timeout,					//	[in]
					ptrAuditData);				//  [out/optional]
			}
			catch (Exception ex) 
			{	
				Console.WriteLine ("BioAPIWin32.BioAPI_VerifyMatch Exception: \n\tError Message = " + ex.Message);
			}
			finally 
			{	
				if (ptrMaxFRRRequested != IntPtr.Zero) Marshal.FreeCoTaskMem( ptrMaxFRRRequested );
				if (ptrAdaptedBIR != IntPtr.Zero) 
				{ AdaptedBIR = (BioAPI_BIR_HANDLE) BioAPIWin32.UnmarshalInt32(ptrAdaptedBIR, true); }

				if (ptrFRRAchieved != IntPtr.Zero) 
				{ FRRAchieved = (BioAPI_FRR) BioAPIWin32.UnmarshalInt32(ptrFRRAchieved, true); }

				if (ptrAuditData != IntPtr.Zero) 
				{ AuditData = (BioAPI_BIR_HANDLE) BioAPIWin32.UnmarshalInt32(ptrAuditData, true); }
			}
			return bReturn;
		}


		public static BioAPI_RETURN BioAPI_IdentifyMatch(
			BioAPI_HANDLE ModuleHandle,				//	[in]
			ref BioAPI_FAR MaxFARRequested,			//	[in]
			ref BioAPI_FRR MaxFRRRequested,			//	[in/optional]
			ref BioAPI_BOOL FARPrecedence,			//	[in]
			BioAPI_INPUT_BIR ProcessedBIR,			//	[in]
			ref BioAPI_IDENTIFY_POPULATION Population,	//	[in]
			BioAPI_BOOL Binning,					//	[in]
			uint MaxNumberOfResults,				//	[in]
			ref uint NumberOfResults,				//	[out]
			ref BioAPI_CANDIDATE [] Candidates,		//	[out]
			int Timeout)							//	[in]
		{
			BioAPI_RETURN bReturn = BioAPI_RETURN.BioAPI_OK;
			IntPtr ptrMaxFRRRequested = IntPtr.Zero;
			BioAPI_INPUT_BIR_Marshal mProcessedBIR = null;
			IntPtr ptrCandidates = IntPtr.Zero;

			if (MaxFRRRequested >= (BioAPI_FRR) 0) 
			{ ptrMaxFRRRequested = BioAPIWin32.MarshalInt32((int) MaxFRRRequested); }

			if (ProcessedBIR != null) 
			{ mProcessedBIR = new BioAPI_INPUT_BIR_Marshal(ProcessedBIR); }

			try 
			{
				bReturn = BioAPIWin32.BioAPI_IdentifyMatch(
					ModuleHandle,				//	[in]
					ref MaxFARRequested,		//	[in]
					ptrMaxFRRRequested,			//	[in/optional]
					ref FARPrecedence,			//	[in]
					mProcessedBIR,				//	[in]
					ref Population,				//	[in]
					Binning,					//	[in]
					MaxNumberOfResults,			//	[in]
					ref NumberOfResults,		//	[out]
					ptrCandidates,				//	[out]
					Timeout);					//	[in]
			}
			catch (Exception ex) 
			{	
				Console.WriteLine ("BioAPIWin32.BioAPI_IdentifyMatch Exception: \n\tError Message = " + ex.Message);
				return bReturn;
			}

			if (ptrMaxFRRRequested != IntPtr.Zero) Marshal.FreeCoTaskMem( ptrMaxFRRRequested );
			IntPtr ptrCandidate = Marshal.ReadIntPtr(ptrCandidates, 0);
			if (ptrCandidate != IntPtr.Zero)
			{
				int len = 0;
				BioAPI_CANDIDATE_Marshal [] mCandidates = new BioAPI_CANDIDATE_Marshal[NumberOfResults];
				Candidates = new BioAPI_CANDIDATE[NumberOfResults];
				IntPtr ptrNext = ptrCandidate;
				for (int i = 0; i < NumberOfResults; i++)
				{
					mCandidates[i].DoUnmarshal(ptrNext, ref len, false);
					Candidates[i] = new BioAPI_CANDIDATE();
					mCandidates[i].Unmarshal(Candidates[i], true);
					ptrNext = new IntPtr(ptrNext.ToInt32() + len);
				}
			}
			
			return bReturn;
		}

		public static BioAPI_RETURN BioAPI_Identify(
			BioAPI_HANDLE ModuleHandle,				//	[in]
			ref BioAPI_FAR MaxFARRequested,			//	[in]
			ref BioAPI_FRR MaxFRRRequested,			//	[in/optional]
			ref BioAPI_BOOL FARPrecedence,			//	[in]
			ref BioAPI_IDENTIFY_POPULATION Population,	//	[in]
			BioAPI_BOOL Binning,					//	[in]
			uint MaxNumberOfResults,				//	[in]
			ref uint NumberOfResults,				//	[out]
			ref BioAPI_CANDIDATE [] Candidates,		//	[out]
			int Timeout,							//	[in]
			ref BioAPI_BIR_HANDLE AuditData)		//	[out/optional]
		{
			BioAPI_RETURN bReturn = BioAPI_RETURN.BioAPI_OK;
			IntPtr ptrMaxFRRRequested = IntPtr.Zero;
			IntPtr ptrCandidates = IntPtr.Zero;
			IntPtr ptrAuditData = IntPtr.Zero;

			if (MaxFRRRequested >= (BioAPI_FRR) 0) 
			{ ptrMaxFRRRequested = BioAPIWin32.MarshalInt32((int) MaxFRRRequested); }

			if (AuditData >= (BioAPI_BIR_HANDLE) 0) 
			{ ptrAuditData = BioAPIWin32.MarshalInt32((int) AuditData); }

			try 
			{
				bReturn = BioAPIWin32.BioAPI_Identify(
					ModuleHandle,				//	[in]
					ref MaxFARRequested,		//	[in]
					ptrMaxFRRRequested,			//	[in/optional]
					ref FARPrecedence,			//	[in]
					ref Population,				//	[in]
					Binning,					//	[in]
					MaxNumberOfResults,			//	[in]
					ref NumberOfResults,		//	[out]
					ptrCandidates,				//	[out]
					Timeout,					//	[in]
					ptrAuditData);				//  [out/optional]
			}
			catch (Exception ex) 
			{	
				Console.WriteLine ("BioAPIWin32.BioAPI_Identify Exception: \n\tError Message = " + ex.Message);
				return bReturn;
			}
			if (ptrMaxFRRRequested != IntPtr.Zero) Marshal.FreeCoTaskMem( ptrMaxFRRRequested );
			IntPtr ptrCandidate = Marshal.ReadIntPtr(ptrCandidates, 0);
			if (ptrCandidate != IntPtr.Zero)
			{
				int len = 0;
				BioAPI_CANDIDATE_Marshal [] mCandidates = new BioAPI_CANDIDATE_Marshal[NumberOfResults];
				Candidates = new BioAPI_CANDIDATE[NumberOfResults];
				IntPtr ptrNext = ptrCandidate;
				for (int i = 0; i < NumberOfResults; i++)
				{
					mCandidates[i].DoUnmarshal(ptrNext, ref len, false);
					Candidates[i] = new BioAPI_CANDIDATE();
					mCandidates[i].Unmarshal(Candidates[i], true);
					ptrNext = new IntPtr(ptrNext.ToInt32() + len);
				}
			}
			if (ptrAuditData != IntPtr.Zero) 
			{ AuditData = (BioAPI_BIR_HANDLE) BioAPIWin32.UnmarshalInt32(ptrAuditData, true); }
	
			return bReturn;
		}


		public static BioAPI_RETURN BioAPI_GetHeaderFromHandle(
			BioAPI_HANDLE ModuleHandle,		// [in]
			BioAPI_BIR_HANDLE BIRHandle,	// [in]
			BioAPI_BIR_HEADER Header)		// [out]
		{
			BioAPI_RETURN bReturn;
			//IntPtr ptrHeader = IntPtr.Zero;
			//int len = 0;

			if (Header == null) { Header = new BioAPI_BIR_HEADER();	}
			//ptrHeader = Header.DoMarshal(ref len);
			bReturn = BioAPIWin32.BioAPI_GetHeaderFromHandle(
				ModuleHandle,
				BIRHandle,
				Header);
			//ptrHeader);
			//Header.DoUnmarshal(ptrHeader, ref len, false);
			//			Console.WriteLine("Length = " + Header.Length + "; Header.HeaderVersion = " + Header.HeaderVersion +
			//				"; Type = " + Header.Type + "; PurposeMask = " + Header.PurposeMask +
			//				"; Format.FormatOwner = " + Header.Format.FormatOwner +
			//				"; Format.FormatID = " + Header.Format.FormatID);

			return bReturn;
		}

		public static BioAPI_RETURN BioAPI_GetBIRFromHandle(
			BioAPI_HANDLE ModuleHandle,		// [in]
			BioAPI_BIR_HANDLE BIRHandle,	// [in]
			ref BioAPI_BIR BIR)				// [out]
		{
			BioAPI_RETURN bReturn;
			IntPtr mBIR;
			IntPtr ptrBIR = IntPtr.Zero;
			int len = 0;

			if (BIR != null) 
			{ 	
				ptrBIR = BIR.DoMarshal(ref len); 
			}

			mBIR = Marshal.AllocCoTaskMem(Marshal.SizeOf(Type.GetType("System.IntPtr")));
			Marshal.WriteIntPtr(mBIR, ptrBIR);

			bReturn = BioAPIWin32.BioAPI_GetBIRFromHandle(
				ModuleHandle,
				BIRHandle,
				mBIR);

			ptrBIR = Marshal.ReadIntPtr(mBIR);

			if (ptrBIR == IntPtr.Zero)
			{
				BIR = null;
			}
			else if (BIR == null) 
			{
				BIR = new BioAPI_BIR();	 
			}

			if (BIR != null ) 
			{
				BIR.DoUnmarshal(ptrBIR, ref len, false);
			}
			
			return bReturn;
		}

		public static BioAPI_RETURN BioAPI_FreeBIRHandle(
			BioAPI_HANDLE ModuleHandle,		// [in]
			BioAPI_BIR_HANDLE BIRHandle)	// [in]
		{
			return BioAPIWin32.BioAPI_FreeBIRHandle(ModuleHandle, BIRHandle);
		}

		public static BioAPI_RETURN BioAPI_EnableEvents(
			BioAPI_HANDLE ModuleHandle,				// [in]
			ref BioAPI_MODULE_EVENT_MASK Events)	// [in]
		{
			return BioAPIWin32.BioAPI_EnableEvents(ModuleHandle, ref Events);
		}

		public static BioAPI_RETURN BioAPI_SetGUICallbacks(
			BioAPI_HANDLE ModuleHandle,								// [in]
			BioAPI_GUI_STREAMING_CALLBACK GuiStreamingCallback,		// [in]
			byte[] GuiStreamingCallbackCtx,							// [in]
			BioAPI_GUI_STATE_CALLBACK GuiStateCallback,				// [in]
			byte[] GuiStateCallbackCtx)								// [in]
		{
			BioAPI_RETURN bReturn;
			IntPtr ptrGuiStreamingCallbackCtx = IntPtr.Zero;
			IntPtr ptrGuiStateCallbackCtx = IntPtr.Zero;	

			if (GuiStreamingCallbackCtx != null) 
				ptrGuiStreamingCallbackCtx = BioAPIWin32.MarshalByteArray(GuiStreamingCallbackCtx);
			if (GuiStateCallbackCtx != null) 
				ptrGuiStateCallbackCtx = BioAPIWin32.MarshalByteArray(GuiStateCallbackCtx);		

			bReturn = BioAPIWin32.BioAPI_SetGUICallbacks(
				ModuleHandle, 
				GuiStreamingCallback,
				ptrGuiStreamingCallbackCtx,
				GuiStateCallback,
				ptrGuiStateCallbackCtx);

			if (ptrGuiStreamingCallbackCtx != IntPtr.Zero) Marshal.FreeCoTaskMem( ptrGuiStreamingCallbackCtx );
			if (ptrGuiStateCallbackCtx != IntPtr.Zero) Marshal.FreeCoTaskMem( ptrGuiStateCallbackCtx );
			return bReturn;
		}

		public static BioAPI_RETURN BioAPI_SetStreamCallback(
			BioAPI_HANDLE ModuleHandle,								// [in]
			BioAPI_GUI_STREAMING_CALLBACK GuiStreamingCallback,		// [in]
			byte[] GuiStreamingCallbackCtx)							// [in]
		{
			BioAPI_RETURN bReturn;
			IntPtr ptrGuiStreamingCallbackCtx = IntPtr.Zero;

			if (GuiStreamingCallbackCtx != null) 
				ptrGuiStreamingCallbackCtx = BioAPIWin32.MarshalByteArray(GuiStreamingCallbackCtx);

			bReturn = BioAPIWin32.BioAPI_SetStreamCallback(
				ModuleHandle, 
				GuiStreamingCallback,
				ptrGuiStreamingCallbackCtx);

			if (ptrGuiStreamingCallbackCtx != IntPtr.Zero) Marshal.FreeCoTaskMem( ptrGuiStreamingCallbackCtx );
			return bReturn;
		}

		public static  BioAPI_RETURN BioAPI_StreamInputOutput(
			BioAPI_HANDLE ModuleHandle,			// [in]
			BioAPI_DATA InMessage,				// [in]
			BioAPI_DATA OutMessage)				// [out]
		{
			return BioAPIWin32.BioAPI_StreamInputOutput(
				ModuleHandle, 
				InMessage,
				OutMessage);
		}

		public static BioAPI_RETURN BioAPI_CreateTemplate(
			BioAPI_HANDLE ModuleHandle,				// [in]
			BioAPI_INPUT_BIR CapturedBIR,			//	[in]
			BioAPI_INPUT_BIR StoredTemplate,		//	[in/optional]
			ref BioAPI_BIR_HANDLE NewTemplate,		// [out]
			BioAPI_DATA Payload)					// [in/optional]
		{
			BioAPI_RETURN bReturn;
			BioAPI_INPUT_BIR_Marshal mCapturedBIR = null;
			BioAPI_INPUT_BIR_Marshal mStoredTemplate = null;

			if (CapturedBIR != null) 
			{ mCapturedBIR = new BioAPI_INPUT_BIR_Marshal(CapturedBIR); }
			if (StoredTemplate != null) 
			{ mStoredTemplate = new BioAPI_INPUT_BIR_Marshal(StoredTemplate); }

			bReturn = BioAPIWin32.BioAPI_CreateTemplate(
				ModuleHandle,		// [in]
				mCapturedBIR,		//	[in]
				mStoredTemplate,	//	[in/optional]
				ref NewTemplate,	// [out]
				Payload);			// [in/optional]

			return bReturn;
		}

		public static BioAPI_RETURN BioAPI_Import(
			BioAPI_HANDLE ModuleHandle,						// [in]
			BioAPI_DATA InputData,							// [in]
			BioAPI_BIR_BIOMETRIC_DATA_FORMAT InputFormat,	//	[in]
			BioAPI_BIR_PURPOSE Purpose,						// [in]
			ref BioAPI_BIR_HANDLE ConstructedBIR)			// [out]
		{
			return  BioAPIWin32.BioAPI_Import(
				ModuleHandle, InputData, InputFormat,
				Purpose, ref ConstructedBIR);
		}

		public static  BioAPI_RETURN BioAPI_SetPowerMode(
			BioAPI_HANDLE ModuleHandle,						// [in]
			BioAPI_POWER_MODE PowerMode)					// [in]
		{
			return  BioAPIWin32.BioAPI_SetPowerMode( ModuleHandle, PowerMode );
		}

		public static BioAPI_RETURN BioAPI_DbOpen(
			BioAPI_HANDLE ModuleHandle,						// [in]
			string DbName,									// [in]
			BioAPI_DB_ACCESS_TYPE AccessRequest,			// [in]
			ref BioAPI_DB_HANDLE DbHandle,					// [out]
			ref BioAPI_DB_CURSOR Cursor)					// [out]	
		{
			return  BioAPIWin32.BioAPI_DbOpen( 
				ModuleHandle, DbName, AccessRequest, 
				ref DbHandle, ref Cursor );
		}

		public static BioAPI_RETURN BioAPI_DbClose(
			BioAPI_HANDLE ModuleHandle,					// [in]
			BioAPI_DB_HANDLE DbHandle)					// [in]
		{
			return  BioAPIWin32.BioAPI_DbClose( ModuleHandle, DbHandle );
		}

		public static BioAPI_RETURN BioAPI_DbCreate(
			BioAPI_HANDLE ModuleHandle,						// [in]
			string DbName,									// [in]
			BioAPI_DB_ACCESS_TYPE AccessRequest,			// [in]
			ref BioAPI_DB_HANDLE DbHandle)					// [out]
		{
			return  BioAPIWin32.BioAPI_DbCreate( 
				ModuleHandle, DbName, AccessRequest, ref DbHandle );
		}

		public static BioAPI_RETURN BioAPI_DbDelete(
			BioAPI_HANDLE ModuleHandle,				// [in]
			string DbName)							// [in]
		{
			return  BioAPIWin32.BioAPI_DbDelete( ModuleHandle, DbName );
		}

		public static BioAPI_RETURN BioAPI_DbSetCursor(
			BioAPI_HANDLE ModuleHandle,				// [in]
			BioAPI_DB_HANDLE DbHandle,				// [in]
			BioAPI_UUID KeyValue,					// [in]
			ref BioAPI_DB_CURSOR Cursor)			// [out]
		{
			BioAPI_RETURN bioReturn;
			int len = 0;
			IntPtr ptrKeyValue = IntPtr.Zero;

			if (KeyValue != null) ptrKeyValue =	KeyValue.DoMarshal(ref len);
			
			bioReturn = BioAPIWin32.BioAPI_DbSetCursor(
				ModuleHandle, 
				DbHandle, 
				ptrKeyValue, 
				ref Cursor);
			if (ptrKeyValue != IntPtr.Zero) Marshal.FreeCoTaskMem( ptrKeyValue );

			return  bioReturn;
		}


		public static BioAPI_RETURN BioAPI_DbFreeCursor(
			BioAPI_HANDLE ModuleHandle,				// [in]
			ref BioAPI_DB_CURSOR Cursor)			// [in]
		{
			return  BioAPIWin32.BioAPI_DbFreeCursor( ModuleHandle, ref Cursor );
		}

		public static BioAPI_RETURN BioAPI_DbStoreBIR(
			BioAPI_HANDLE ModuleHandle,				// [in]
			BioAPI_INPUT_BIR BIRToStore,			// [in]
			BioAPI_DB_HANDLE DbHandle,				// [in]
			BioAPI_UUID Uuid)					// [out]
		{
			BioAPI_RETURN bioReturn;
			int len = 0;
			IntPtr ptrUuid = IntPtr.Zero;
			BioAPI_INPUT_BIR_Marshal mBIRToStore = null;

			if (BIRToStore != null) 
			{ mBIRToStore = new BioAPI_INPUT_BIR_Marshal(BIRToStore); }
		
			bioReturn = BioAPIWin32.BioAPI_DbStoreBIR(
				ModuleHandle, 
				mBIRToStore, 
				DbHandle, 
				ptrUuid);
			if (ptrUuid != IntPtr.Zero)
			{
				if (Uuid == null) Uuid = new BioAPI_UUID();
				Uuid.DoUnmarshal(ptrUuid, ref len, true);
			}

			return  bioReturn;
		}

		public static BioAPI_RETURN BioAPI_DbGetBIR(
			BioAPI_HANDLE ModuleHandle,			// [in]
			BioAPI_DB_HANDLE DbHandle,			// [in]
			BioAPI_UUID KeyValue,				// [in]
			ref BioAPI_BIR_HANDLE RetrievedBIR,	// [out]
			ref BioAPI_DB_CURSOR Cursor)		// [out]
		{
			BioAPI_RETURN bioReturn;
			int len = 0;
			IntPtr ptrKeyValue = IntPtr.Zero;

			if (KeyValue != null) ptrKeyValue =	KeyValue.DoMarshal(ref len);
			
			bioReturn = BioAPIWin32.BioAPI_DbGetBIR(
				ModuleHandle, 
				DbHandle, 
				ptrKeyValue, 
				ref RetrievedBIR,
				ref Cursor);
			if (ptrKeyValue != IntPtr.Zero) Marshal.FreeCoTaskMem( ptrKeyValue );

			return  bioReturn;
		}

		public static BioAPI_RETURN BioAPI_DbGetNextBIR(
			BioAPI_HANDLE ModuleHandle,				// [in]
			ref BioAPI_DB_CURSOR Cursor,			// [in/out]
			ref BioAPI_BIR_HANDLE RetrievedBIR,		// [out]
			BioAPI_UUID KeyValue)					// [out]
		{
			BioAPI_RETURN bioReturn;
			int len = 0;
			IntPtr ptrKeyValue = IntPtr.Zero;

			bioReturn = BioAPIWin32.BioAPI_DbGetNextBIR(
				ModuleHandle, 
				ref Cursor, 
				ref RetrievedBIR, 
				ptrKeyValue);
			if (ptrKeyValue != IntPtr.Zero)
			{
				if (KeyValue == null) KeyValue = new BioAPI_UUID();
				KeyValue.DoUnmarshal(ptrKeyValue, ref len, true);
			}
			return  bioReturn;
		}


		public static BioAPI_RETURN BioAPI_DbQueryBIR(
			BioAPI_HANDLE ModuleHandle,				// [in]
			BioAPI_DB_HANDLE DbHandle,				// [in]
			BioAPI_INPUT_BIR BIRToQuery,			// [in]
			BioAPI_UUID Uuid)						// [out]
		{
			BioAPI_RETURN bioReturn;
			int len = 0;
			IntPtr ptrUuid = IntPtr.Zero;
			BioAPI_INPUT_BIR_Marshal mBIRToQuery = null;

			if (BIRToQuery != null) 
			{ mBIRToQuery = new BioAPI_INPUT_BIR_Marshal(BIRToQuery); }
	
			bioReturn = BioAPIWin32.BioAPI_DbQueryBIR(
				ModuleHandle, 
				DbHandle, 
				mBIRToQuery, 
				ptrUuid);
			if (ptrUuid != IntPtr.Zero)
			{
				if (Uuid == null) Uuid = new BioAPI_UUID();
				Uuid.DoUnmarshal(ptrUuid, ref len, true);
			}
			return  bioReturn;
		}


		public static BioAPI_RETURN BioAPI_DbDeleteBIR(
			BioAPI_HANDLE ModuleHandle,				// [in]
			BioAPI_DB_HANDLE DbHandle,				// [in]
			BioAPI_UUID KeyValue)					// [in]
		{
			BioAPI_RETURN bioReturn;
			int len = 0;
			IntPtr ptrKeyValue = IntPtr.Zero;

			if (KeyValue != null) ptrKeyValue =	KeyValue.DoMarshal(ref len);
			
			bioReturn = BioAPIWin32.BioAPI_DbDeleteBIR(
				ModuleHandle, 
				DbHandle, 
				ptrKeyValue);
			if (ptrKeyValue != IntPtr.Zero) Marshal.FreeCoTaskMem( ptrKeyValue );

			return  bioReturn;
		}

		private static void print_BIR_HEADER(BioAPI_BIR_HEADER Header)
		{
			Console.WriteLine("Header.Length = " + Header.Length + "; Header.HeaderVersion = " + Header.HeaderVersion +
				"; Type = " + Header.Type + "; PurposeMask = " + Header.PurposeMask +
				"; Format.FormatOwner = " + Header.Format.FormatOwner +
				"; Format.FormatID = " + Header.Format.FormatID);
		}

		private static void print_BioAPI_BIR_BIOMETRIC_DATA(BioAPI_BIR_BIOMETRIC_DATA [] data)
		{
			string str = "Biometric data = ";
			if (data == null) 
				str += "null"; 
			else
				for (int i = 0; i < data.Length; i++) str += Convert.ToString(data[i]) + " ";
			Console.WriteLine(str);
		}

		private static void print_BioAPI_DATA(BioAPI_DATA data)
		{
			string str = "BioAPI_DATA = ";
			if (data == null) 
				str += "null"; 
			else
			{
				str += Convert.ToString(data.Length) + "; ";
				for (int i = 0; i < data.Length; i++) str += Convert.ToString(data.Data[i]) + " ";
			}
			Console.WriteLine(str);
		}
		
	}
}