#pragma once
#pragma unmanaged
#include <windows.h>
#pragma unmanaged
#include "EpdCommon.h"
#include "Epd3.h"
#include "Epd2.h"

#pragma unmanaged
#define MaxPeakRates 10
#define MaxSensitivities 10
#define MaxDoses 4
#define MaxCounts 6
#define MaxAlarmConfig 10
#define MaxTresholds 10

namespace Epd3Base {
	class Epd3U
	{
	public:
		char  comPort[5] = { "COM4" };
		CommsHandle epdComsHandle;
		uint32_t CurrentDeviceID;
		EpdGeneration EpdGen;
		DiscoveryId Epd;
		CompletionToken token;
		WORD port = 3;
		const WORD MaxDevices = 10;
		WORD DeviceCount = 0;
		DWORD DeviceIDs[10];

		WORD Error = 0;
		WORD ErrorSource;
		WORD ErrorReason;
		WORD ErrorData;

		int32_t Dll3RV;
		UINT16 EndSessionControl; 
	public:
		//HANDLE hWaitTimer = 0;
		HANDLE hCompletion = 0;


	private:
		WORD CommsInitialized = 0;

	public:
		Epd3U(int _comport);
		~Epd3U();
		DWORD StartCom();
		void EndCom();
		int StartDiscover(int tokentimeout);

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


		//ErrorStatus
		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;

		DWORD Password = 9;

		//Identification

		DWORD EpdID = 0;
		WORD HardVersion;
		WORD SoftVersion;
		WORD FunctionFlags;

		DWORD EpdClock;
		DWORD RealTime;
		WORD IssueCount;
		DWORD OffTime;
		WORD OtherAlarms;
		WORD EEPROMBadSectors;

		EpdTypes EpdType = EpdTypes::Mk2Gamma;
		bool isBG = false;
		bool isNG = false;
		bool VersionOK = false;
		bool isMK3 = false;
		bool hasAlarm = false;
		SYSTEMTIME tRealTime;

		//Wearer
#define WearerIDLength  12
		BYTE WearerID[(WearerIDLength)+1];
#define WearerNameLength  22
		BYTE WearerName[WearerNameLength + 1];

		// Dose

		float Hp10Dose;
		float Hp07Dose;
		float Hp10Total;
		float Hp07Total;
		WORD Knocks;
		WORD Resets;
		WORD QualityData;

		//Peaks
		float Hp10Peak;
		float Hp07Peak;
		DWORD Hp10Time;
		DWORD Hp07Time;
		long long Hp10FTime,Hp07FTime;


		//AlarmDoseTreshold
		float Hp10THDose1;
		float Hp10THDose2;
		float Hp07THDoseA; //Alarm
		float Hp07THDose;

		float Hp10Rate1On;
		float Hp10Rate2On;
		float Hp07RateOn;
		float Hp07RateAOn;
		float Hp10Rate1Off;
		float Hp10Rate2Off;
		float Hp07RateOff;
		float Hp07RateAOff;


		float K1;
		float K2;
		float K3;
		float K4;
		float K5;
		float K6;
		uint32_t SG;
		uint32_t BC;
		uint32_t FB;
		uint32_t HG;

		DWORD	D1;
		DWORD	D2;
		DWORD	D3;
		DWORD	D4;
		DWORD  CountsClock;

		DWORD	BaseD1;
		DWORD	BaseD2;
		DWORD	BaseD3;
		DWORD	BaseD4;
		DWORD  BaseCountsClock;




		BYTE ConnectTimerFired;
		int ConnectTries;
		
		OpStatusFlags OperatingStatus;
		FaultStatusFlags ErrorStatus;
		AlarmStatusFlags AlarmStatus;
		
		StatusData_t epd3status;
		uint8_t counterIds[MaxCounts]; //max 6 for mk3
		uint8_t counterIdLen;

		MeasurementId mIDs[MAX_MEASUREMENTS];
		uint8_t nmIDs = 0;

		MeasValue_t doses[MaxDoses];
		MeasValue_t totdoses[MaxDoses];
		PeakRate_t peakRates[MaxPeakRates];
		AlarmConfig_t alarmConfig[MaxAlarmConfig];
		CalSensitivity_t sensitivities[MaxSensitivities];
		Counter_t Counts[MaxCounts];
		uint8_t countsRead;
		uint32_t seconds;
		uint8_t numDoses, numtotDoses, numRates, numSensitivities, numTresholds;
		uint16_t numAlarm;
		uint32_t utc;
		Mk3QualityData_t quality;
		Mk3AlarmThresholds_t hp07tresholds;
		Mk3RatePercentage_t RatePct[2];
		Mk3AlarmThresholds_t hp10tresholds;

		DetectorThreshold_t dTresholds[MaxTresholds];

		//Functions
		int OpenDev(DiscoveryId DeviceID);
		int DisCon(UINT16 alarm);
		
		void CloseDev(bool CloseAll);
		void DecodeStatus();
		void SetTime();
		
		int ReadStatus();

		protected:
		void decodeCounters(int count);
		void decodeBaseCounters(int count);
		void decodeTreshold(Mk3AlarmThresholds_t* th);
		void encodeTreshold(Mk3AlarmThresholds_t* th);
		void decodedTresholds(int numdTresholds);
		void decodeSensitivities(int count);
		void decodetotDoses(int count);
		void decodeDoses(int count);
		void decodePeakRates(int count);


		public:
			int GetAll(bool Closeconnection);
			int GetAllDeissue();
			int IssueAndCheck(float gain);
			WORD ReadCal();
			WORD ReadSensitivitiesAndTresholds();
		WORD ReadDoses();
		int ClearDoses();
		int ClearAlarms();
		WORD PrepareForIssue();
		WORD ReadAlarmConfig();
		int ConnectAndStatus(int tokenSourceTimeout);
		WORD ReadAlarmTresholds();
		WORD WriteAlarmTresholds();
		WORD DeIssue();
		WORD WriteWearer();

		WORD Issue();
		WORD EPDReadExtraStatus();
		WORD WriteCal();
		
};
}

