#pragma once
#include "MK3Base.h"
#pragma comment(lib,"Reader3.lib")
#pragma managed

using namespace System;
using namespace System::Collections::Generic;
using namespace System::Runtime::InteropServices;
#include <msclr\marshal.h>
#include <msclr\marshal_cppstd.h>

namespace MK3 {
	const char* cEpdError = "Setreader Error";
	ref class Epd2;

	public ref class EpdEventArgs : EventArgs
	{
		
	public:
		int deviceID;
		bool isIssued, isBG, isMK3;

		EpdEventArgs(int epdID,bool epdIssued, bool isBG, bool isMK3) : EventArgs()
		{
			
			this->deviceID = epdID;
			this->isIssued = epdIssued;
			this->isBG = isBG;
			this->isMK3 = isMK3;
		}

	};
	public ref struct EpdException : System::Exception
	{
	public:
		int errorCode;
		EpdException(int r) : System::Exception(gcnew String(cEpdError))
		{
			this->errorCode = r;
		}
	};
	public ref class EpdErrorEventArgs : EventArgs
	{
	public:
		int returnValue;

		EpdErrorEventArgs(int ReturnValue) : EventArgs()
		{
			this->returnValue = ReturnValue;
		}

	};


	public ref class Epd2
	{
	private:
		DateTime^ Jan2000;

	public:
		delegate void dEpdRead(Epd2^ Sender, EpdEventArgs^ e);
		delegate void dEpdTO(Epd2^ Sender, EventArgs^ e);
		delegate void dEpdError(Epd2^ Sender, EpdErrorEventArgs^ e);

		dEpdRead^ _EpdRead;
		dEpdTO^ _EpdTO;
		dEpdError^ _EpdError;

		event dEpdRead^ EpdRead
		{
			void add(dEpdRead^ handler)
			{
				_EpdRead += handler;
			}

			void remove(dEpdRead^ handler)
			{
				_EpdRead -= handler;
			}
		}
		event dEpdError^ EpdError
		{
			void add(dEpdError^ handler)
			{
				_EpdError += handler;
			}

			void remove(dEpdError^ handler)
			{
				_EpdError -= handler;
			}
		}
		event dEpdTO^ EpdTO
		{
			void add(dEpdTO^ handler)
			{
				_EpdTO += handler;
			}

			void remove(dEpdTO^ handler)
			{
				_EpdTO -= handler;
			}
		}

		Epd2U* epd;
		//int CurrentDeviceID; ==> is EpdID
		DateTime^ RealTime;
		
		String^ WearerName;
		String^ WearerID;
		bool Issued;
		bool isOn;
		bool isBG;
		bool isMK3;

		int InitRV;
		int DiscRV;
		int StatusRV;
		int GetStatusError;
		int GetDosesError;
		int ReadTresholdsError;
		int PrepareForIssueError;
		int SetIssuedError;
		int ConnectError;
		int ReadDosesRV;
		int DeviceCount = 0;

		double Hp07;
		double Hp10;
		double Hp07Peak;
		double Hp10Peak;
		System::Nullable<System::DateTime> Hp10PeakTime;
		System::Nullable<System::DateTime> Hp07PeakTime;
		double Hp07Total;
		double Hp10Total;

		double alarmHP07;
		double alarmHP10;


		double Hp10THDose1;
		double Hp10THDose2;
		double Hp07THDose;

		double Hp10Rate1On;
		double Hp10Rate2On;
		double Hp07RateOn;
		double Hp10Rate1Off;
		double Hp10Rate2Off;
		double Hp07RateOff;

		float K1;
		float K2;
		float K3;
		float K4;
		float K5;
		float K6;

		int SG;
		int BC;
		int FB;
		int HG;
		int QualityData;

		unsigned int D1, D2, D3, D4, CountsClock, CountsClockBase;

		int epdType;
		AlarmStatusFlags alarmStatus;
		int otherAlarms;
		FaultStatusFlags errorStatus;
		OpStatusFlags operatingStatus;
		unsigned int EpdID;
		int HardVersion;
		int SoftVersion;
		int FunctionFlags;

		unsigned short BatADC;
		unsigned short SupplyADC;

		//OperatingStatus
		BYTE DetectorsOn = 0;
		BYTE EPDIssued = 0;
		BYTE EPDLocked = 0;
		BYTE EPDTesting = 0;
		BYTE EPDProcSec = 0;
		BYTE EPDFaulty = 0;

		//ERrrostatus
		BYTE EPDNewFault = 0;
		BYTE EPDComFault = 0;
		BYTE EPDCalFault = 0;
		BYTE EPDDetFault = 0;
		BYTE EPDEprFault = 0;
		BYTE EPDTrhFault = 0;
		BYTE EPDOthFault = 0;

		//AlarmStatus
		BYTE AlarmDoseHP101G = 0;
		BYTE AlarmDoseHP102G = 0;
		BYTE AlarmDoseHP07N = 0;
		BYTE AlarmRateHP101G = 0;
		BYTE AlarmRateHP102G = 0;
		BYTE AlarmRateHP07N = 0;

		//OtherAlarm
		BYTE OtherAlarmRateHp101G = 0;
		BYTE OtherAlarmRateHp102G = 0;
		BYTE OtherAlarmRateHp07N = 0;
		BYTE OtherAlarmReturn = 0;
		BYTE OtherAlarmBatLow = 0;
		BYTE OtherAlarmCarrier = 0;
		BYTE OtherAlarmBatVolt = 0;

		Epd2(int port);
		~Epd2();
		!Epd2();

		int Connect(bool reinit);

		int Close();

		int DecodeStatus();

		int SetTime();

		int ReadAlarmConfig();

		int ReadAlarmTresholds();

		int GetStatus();

		int GetDoses();
		int SetDeIssued();
		int SetIssued();
		int PrepareForIssue();
		int WriteCalibration();
		int ReadTresholds();
		int ReadExtraStatus();

		int ConnectAndStatus();

		void WaitEpd();

		System::Threading::CancellationTokenSource^ tokenSource;
		int tokenSourceTimeout;
		int readRetries;
		System::Threading::Tasks::Task^ waitTask;
		System::Threading::Tasks::Task^ Wait(int timeout, int Retries);

		void WaitEnd();



	};
}
