#pragma once
#include <windows.h>
#include <devguid.h>    // for GUID_DEVCLASS_CDROM etc
#include <setupapi.h>
#include <cfgmgr32.h>   // for MAX_DEVICE_ID_LEN, CM_Get_Parent and CM_Get_Device_ID
#include <hidsdi.h>
#include <Hidclass.h> 
#include <string>
#include "okClr.h"
#include <msclr\auto_gcroot.h>

namespace OkReadBadge 
{
	public class BadgeUnmanaged
	{

	private:
		LPOVERLAPPED Overlapped;
		msclr::auto_gcroot<BadgeMessageHandler^> m_clr;

	public:
		// TODO: Add your methods for this class here.
		wchar_t * DevicePath = nullptr;
		int DeviceType;
		BYTE buffer[100];
		DWORD bread;
		
		bool nextCSN = false;
		bool nextSite = false;
		bool nextCode = false;
		bool nextFinish = false;
		bool completed = false;
		char Res [100];
		char CSN[50];
		char Site[20];
		char Badge[20];

		int parse(char *rall)
		{
			int items;
			char *source;
			int sourcelen;
			char *dest;
			int destlen;
			char *r = rall;
			char *mx = r + strlen(rall);
			items = 0;
			Res[0] = 0;
			while (r < mx && items<3) {
				if (!strncmp("csn:", r, 4)) {
					items++;
					dest = CSN; destlen = sizeof(CSN);
					source = r + 4; //na csn:
				}
				else if (!strncmp("site:", r, 4)) {
					items++;
					dest = Site; destlen = sizeof(Site);
					source = r + 5; //na site:
				}
				else if (!strncmp("code:", r, 4)) {
					items++;
					dest = Badge; destlen = sizeof(Badge);
					source = r + 5; //na code:
				}
				else {
					dest = NULL; destlen = 0;
				}
				char *x = strchr(source, ';');
				*x = 0; sourcelen = strlen(source);
				if (dest != NULL) {
					memcpy_s(dest, destlen, source, sourcelen + 1);
				}
				r = x + 1;
			}
			return items;
		}

		static bool CALLBACK Message(int err, LPARAM param)
		{
			//m_clr.Result = gcnew buffer
			BadgeUnmanaged *bu = static_cast<BadgeUnmanaged *>((void *)param);
			if (err == 0) {
				byte l = bu->buffer[2];
				char *r = (char *)&bu->buffer[4];
				r[l] = 0;
				if (bu->nextCSN) { 
					memcpy_s(bu->CSN, sizeof(bu->CSN), r, l + 1);
					memcpy_s(bu->Res, sizeof(bu->Res), r, l + 1);
					bu->nextCSN = false; 
				}
				else if (bu->nextSite) { 
					memcpy_s(bu->Site, 20, r, l + 1);
					strncat_s(bu->Res, (const char *)r, l); bu->nextSite = false; }
				else if (bu->nextCode) {
					memcpy_s(bu->Badge, sizeof(bu->Badge), r, l + 1);
					strncat_s(bu->Res, (const char *)r, l); bu->nextCode = false; bu->nextFinish = true;
				}
				else if (!strncmp("csn:", r, 4)) {
					bu->nextCSN = true; bu->nextFinish = bu->nextCode = bu->nextSite = bu->completed = false;
					if (strstr(r, "code:") != NULL) {
						int it = bu->parse(r);
						//char *s = r + 4; //na csn:
						//char *x = strchr(r, ';');
						//*x = 0; l = strlen(s);
						//memcpy_s(bu->CSN, sizeof(bu->CSN), s, l + 1);
						////x+1 should be "site:"
						//s = x + 6; // n a site:v
						//x = strchr(s, ';'); *x = 0; l = strlen(s);
						////x+1 should be "code:"
						//memcpy_s(bu->Site, sizeof(bu->Site), s, l + 1);
						//s = x + 6; // no code:
						//x = strchr(s, ';'); *x = 0; l = strlen(s);
						//memcpy_s(bu->Badge, sizeof(bu->Badge), s, l + 1);
						bu->completed = true;
					}
					else {
						memset(bu->Res, 0, sizeof(bu->Res));
						memset(bu->CSN, 0, sizeof(bu->CSN));
						memset(bu->Site, 0, sizeof(bu->Site));
						memset(bu->Badge, 0, sizeof(bu->Badge));
						bu->completed = false;
						bu->m_clr->Final = false;
					}
				}
				else if (!strncmp("site:", r, 5)) { bu->nextSite = true; }
				else if (!strncmp("code:", r, 5)) { bu->nextCode = true; }
				else if (!strncmp(";", r, 1)) { 
					strncat_s(bu->Res, r, 1);
					bu->nextCode = bu->nextSite =  bu->nextCSN = false; 
					if (bu->nextFinish) {
						bu->nextFinish = false;
						bu->completed = true;
					}
				}
				if (bu->completed) 
				{
					bu->m_clr->Final = true;
					bu->m_clr->CSN= gcnew String(bu->CSN);
					bu->m_clr->Site = gcnew String(bu->Site);
					bu->m_clr->Badge= gcnew String(bu->Badge);
				}
				else
				bu->m_clr->Result = gcnew String(r);
			}
			else {
				if (bu->nextCSN | bu->nextFinish |  bu->nextCode | bu->nextSite | bu->nextCSN  )
					bu->m_clr->Result = gcnew String(bu->Res);
				else {
					bu->m_clr->Result = String::Empty;
					bu->m_clr->Final = false;
				}
			}
			return bu->m_clr->OnMessage((int)err);
		}
		BadgeUnmanaged(BadgeMessageHandler^ clr);
		void GetDeviceUSB(std::wstring vid, std::wstring pid, std::wstring pid2);
		int read();
	};
}


