// ConsoleApplication1.cpp : Defines the entry point for the console application.
//

#include "pch.h"
#include "INITGUID.H"

#include <process.h>

#include "..\..\..\..\Source\Bluetooth\wclBluetooth.h"

using namespace std;
using namespace wclCommon;
using namespace wclBluetooth;

static const GUID BEACON_UUID = { 0x09039835, 0x4A80, 0x443B, { 0x87, 0xAA, 0xDC, 0x56, 0x5D, 0x09, 0xEA, 0x61 } };

class CBeacons
{
private:
	CwclBluetoothRadio*			Radio;
	int							InitResult;
	HANDLE						InitEvent;
	HANDLE						Event;
	HANDLE						RunThread;
	CwclBluetoothLeAdvertiser*	Advertiser;

	string GuidToString(const GUID& guid) const
	{
		char guid_cstr[39];
		snprintf(guid_cstr, sizeof(guid_cstr),
			"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
			guid.Data1, guid.Data2, guid.Data3,
			guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
			guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);

		return string(guid_cstr);
	}

	string wtoa(const tstring& w) const
	{
		return string(w.begin(), w.end());
	}

	void Watcher_OnAdvertisementServiceSol32Frame(void* Sender, const __int64 Address, 
		const __int64 Timestamp, const char Rssi, const unsigned long Uuid)
	{
		UNREFERENCED_PARAMETER(Sender);

		cout << "32 bit SOL service data" << endl;
		cout << "=======================" << endl;
		cout << "  Address: " << hex << Address << dec << endl;
		cout << "  Timestamp: " << hex << Timestamp << dec << endl;
		cout << "  RSSI: " << +Rssi << endl;
		cout << "  UUID: " << hex << Uuid << dec << endl << endl;
	}

	void Watcher_OnAdvertisementServiceSol16Frame(void* Sender, const __int64 Address, 
		const __int64 Timestamp, const char Rssi, const unsigned short Uuid)
	{
		UNREFERENCED_PARAMETER(Sender);

		cout << "16 bit SOL service data" << endl;
		cout << "=======================" << endl;
		cout << "  Address: " << hex << Address << dec << endl;
		cout << "  Timestamp: " << hex << Timestamp << dec << endl;
		cout << "  RSSI: " << +Rssi << endl;
		cout << "  UUID: " << hex << Uuid << dec << endl << endl;
	}

	void Watcher_OnAdvertisementServiceSol128Frame(void* Sender, const __int64 Address, 
		const __int64 Timestamp, const char Rssi, const GUID& Uuid)
	{
		UNREFERENCED_PARAMETER(Sender);

		cout << "128 bit SOL service data" << endl;
		cout << "========================" << endl;
		cout << "  Address: " << hex << Address << dec << endl;
		cout << "  Timestamp: " << hex << Timestamp << dec << endl;
		cout << "  RSSI: " << +Rssi << endl;
		cout << "  UUID: " << GuidToString(Uuid) << endl << endl;
	}

	void Watcher_OnAdvertisementService32DataFrame(void* Sender, const __int64 Address, 
		const __int64 Timestamp, const char Rssi, const unsigned long Uuid, 
		const wclBluetoothLeAdvertisementFrameRawData& Data)
	{
		UNREFERENCED_PARAMETER(Sender);
		UNREFERENCED_PARAMETER(Data);

		cout << "32 bit service data" << endl;
		cout << "===================" << endl;
		cout << "  Address: " << hex << Address << dec << endl;
		cout << "  Timestamp: " << hex << Timestamp << dec << endl;
		cout << "  RSSI: " << +Rssi << endl;
		cout << "  UUID: " << hex << Uuid << dec << endl << endl;
	}

	void Watcher_OnAdvertisementService16DataFrame(void* Sender, const __int64 Address, 
		const __int64 Timestamp, const char Rssi, const unsigned short Uuid, 
		const wclBluetoothLeAdvertisementFrameRawData& Data)
	{
		UNREFERENCED_PARAMETER(Sender);
		UNREFERENCED_PARAMETER(Data);

		cout << "16 bit service data" << endl;
		cout << "===================" << endl;
		cout << "  Address: " << hex << Address << dec << endl;
		cout << "  Timestamp: " << hex << Timestamp << dec << endl;
		cout << "  RSSI: " << +Rssi << endl;
		cout << "  UUID: " << hex << Uuid << dec << endl << endl;
	}

	void Watcher_OnAdvertisementService128DataFrame(void* Sender, const __int64 Address, 
		const __int64 Timestamp, const char Rssi, const GUID& Uuid, 
		const wclBluetoothLeAdvertisementFrameRawData& Data)
	{
		UNREFERENCED_PARAMETER(Sender);
		UNREFERENCED_PARAMETER(Data);

		cout << "128 bit service data" << endl;
		cout << "====================" << endl;
		cout << "  Address: " << hex << Address << dec << endl;
		cout << "  Timestamp: " << hex << Timestamp << dec << endl;
		cout << "  RSSI: " << +Rssi << endl;
		cout << "  UUID: " << GuidToString(Uuid) << endl << endl;
	}


	void Watcher_OnAdvertisementUuidFrame(void* Sender, const __int64 Address, 
		const __int64 Timestamp, const char Rssi, const GUID& Uuid)
	{
		UNREFERENCED_PARAMETER(Sender);
		
		cout << "UUID FRAME" << endl;
		cout << "==========" << endl;
		cout << "  Address: " << hex << Address << dec << endl;
		cout << "  Timestamp: " << hex << Timestamp << dec << endl;
		cout << "  RSSI: " << +Rssi << endl;
		cout << "  UUID: " << GuidToString(Uuid).c_str() << endl << endl;
	}

	void Watcher_OnAdvertisementFrameInformation(void* Sender, const __int64 Address, 
		const __int64 Timestamp, const char Rssi, const tstring& Name, 
		const wclBluetoothLeAdvertisementType PacketType, const wclBluetoothLeAdvertisementFlags& Flags)
	{
		UNREFERENCED_PARAMETER(Sender);

		cout << "FRAME INFORMATION" << endl;
		cout << "=================" << endl;
		cout << "  Address: " << hex << Address << dec << endl;
		cout << "  Timestamp: " << hex << Timestamp << dec << endl;
		cout << "  RSSI: " << +Rssi << endl;
		cout << "  Name: " << wtoa(Name).c_str() << endl;

		tstring Str;

		switch (PacketType)
		{
		case atConnectableUndirected:
			Str = _T("Connectable Undirected");
			break;
		case atConnectableDirected:
			Str = _T("Connectable Directed");
			break;
		case atScannableUndirected:
			Str = _T("Scannable Undirecte");
			break;
		case atNonConnectableUndirected:
			Str = _T("Non Connectable Undirected");
			break;
		case atScanResponse:
			Str = _T("Scan Response");
			break;
		default:
			Str = _T("Unknown");
			break;
		}
		cout << "  Frame type: " << wtoa(Str).c_str() << endl;

		Str = _T("[");
		if (Flags.find(afLimitedDiscoverableMode) != Flags.end())
			Str = Str + _T(" afLimitedDiscoverableMode");
		if (Flags.find(afGeneralDiscoverableMode) != Flags.end())
			Str = Str + _T(" afGeneralDiscoverableMode");
		if (Flags.find(afClassicNotSupported) != Flags.end())
			Str = Str + _T(" afClassicNotSupported");
		if (Flags.find(afDualModeControllerCapable) != Flags.end())
			Str = Str + _T(" afDualModeControllerCapable");
		if (Flags.find(afDualModeHostCapable) != Flags.end())
			Str = Str + _T(" afDualModeHostCapable");
		Str = Str + _T(" ]");
		cout << "  Flags: " << wtoa(Str).c_str() << endl << endl;
	}

	void Watcher_OnAppleiBeaconFrame(void* Sender, const wclBluetoothLeAdvertisementInfo& Info,
		const wclBluetoothLeAppleiBeaconFrameData& Data)
	{
		UNREFERENCED_PARAMETER(Sender);

		cout << "PROXIMITY BEACON FRAME" << endl;
		cout << "======================" << endl;
		cout << "  Address: " << hex << Info.Address << dec << endl;
		cout << "  Timestamp: " << hex << Info.Timestamp << dec << endl;
		cout << "  RSSI: " << Info.Rssi << endl;
		cout << "  TX RSSI: " << Data.TxRssi << endl;
		cout << "  Minor: " << hex << Data.Minor << dec << endl;
		cout << "  Major: " << hex << Data.Major << dec << endl;
		cout << "  UUID: " << GuidToString(Data.Uuid).c_str() << endl << endl;
	}

	void Watcher_OnAltBeaconFrame(void* Sender, const __int64 Address, 
		const __int64 Timestamp, const char Rssi, const unsigned short CompanyId,
		const unsigned short Major, const unsigned short Minor, const GUID& Uuid, 
		const char TxRssi, const unsigned char Reserved,
		const wclBluetoothLeAdvertisementFrameRawData& Data)
	{
		UNREFERENCED_PARAMETER(Sender);
		UNREFERENCED_PARAMETER(Data);

		cout << "ALT BEACON FRAME" << endl;
		cout << "======================" << endl;
		cout << "  Address: " << hex << Address << dec << endl;
		cout << "  Timestamp: " << hex << Timestamp << dec << endl;
		cout << "  RSSI: " << +Rssi << endl;
		cout << "  TX RSSI: " << +TxRssi << endl;
		cout << "  Company ID: " << hex << CompanyId << dec << endl;
		cout << "  Minor: " << hex << Minor << dec << endl;
		cout << "  Major: " << hex << Major << dec << endl;
		cout << "  Reserved: " << hex << Reserved << dec << endl;
		cout << "  UUID: " << GuidToString(Uuid).c_str() << endl << endl;
	}

	void Watcher_OnManufacturerRawFrame(void* Sender, const __int64 Address, 
		const __int64 Timestamp, const char Rssi, const unsigned short CompanyId, 
		const wclBluetoothLeAdvertisementFrameRawData& Data)
	{
		UNREFERENCED_PARAMETER(Sender);

		cout << "MANUFACTURER RAW FRAME" << endl;
		cout << "======================" << endl;
		cout << "  Address: " << hex << Address << dec << endl;
		cout << "  Timestamp: " << hex << Timestamp << dec << endl;
		cout << "  RSSI: " << +Rssi << endl;
		cout << "  Company ID: " << hex << CompanyId << endl;
		cout << "  Data length: 0" << Data.size() << endl << endl;
	}

	void Watcher_OnEddystoneUrlFrame(void* Sender, const __int64 Address, 
		const __int64 Timestamp, const char Rssi, const char TxRssi, const tstring& Url)
	{
		UNREFERENCED_PARAMETER(Sender);

		cout << "EDDYSTONE URL FRAME" << endl;
		cout << "===================" << endl;
		cout << "  Address: " << hex << Address << dec << endl;
		cout << "  Timestamp: " << hex << Timestamp << dec << endl;
		cout << "  RSSI: " << +Rssi << endl;
		cout << "  TX RSSI: " << +TxRssi << endl;
		cout << "  URL: " << wtoa(Url).c_str() << endl << endl;
	}

	void Watcher_OnEddystoneUidFrame(void* Sender, const __int64 Address, const __int64 Timestamp, 
		const char Rssi, const char TxRssi, const GUID& Uuid, 
		const wclBluetoothLeAdvertisementFrameRawData& Data)
	{
		UNREFERENCED_PARAMETER(Sender);
		UNREFERENCED_PARAMETER(Data);

		cout << "EDDYSTONE UID FRAME" << endl;
		cout << "===================" << endl;
		cout << "  Address: " << hex << Address << dec << endl;
		cout << "  Timestamp: " << hex << Timestamp << dec << endl;
		cout << "  RSSI: " << +Rssi << endl;
		cout << "  TX RSSI: " << +TxRssi << endl;
		cout << "  UUID: " << GuidToString(Uuid).c_str() << endl << endl;
	}

	void Watcher_OnEddystoneTlmFrame(void* Sender, const __int64 Address, const __int64 Timestamp, 
		const char Rssi, const unsigned long AdvCnt, const unsigned short Batt, 
		const unsigned long SecCnt, const double Temp, const wclBluetoothLeAdvertisementFrameRawData& Data)
	{
		UNREFERENCED_PARAMETER(Sender);
		UNREFERENCED_PARAMETER(Data);

		cout << "EDDYSTONE TLM FRAME" << endl;
		cout << "===================" << endl;
		cout << "  Address: " << hex << Address << dec << endl;
		cout << "  Timestamp: " << hex << Timestamp << dec << endl;
		cout << "  RSSI: " << +Rssi << endl;
		cout << "  Frames sent: " << AdvCnt << endl;
		cout << "  Battery level: " << Batt << endl;
		cout << "  Running time (secs): " << SecCnt << endl;
		cout << "  Temperature: " << Temp << endl << endl;
	}

	void Watcher_OnAdvertisementRawFrame(void* Sender, const __int64 Address, 
		const __int64 Timestamp, const char Rssi, const unsigned char  DataType, 
		const wclBluetoothLeAdvertisementFrameRawData& Data)
	{
		UNREFERENCED_PARAMETER(Sender);

		cout << "RAW FRAME" << endl;
		cout << "=========" << endl;
		cout << "  Address: " << hex << Address << dec << endl;
		cout << "  Timestamp: " << hex << Timestamp << dec << endl;
		cout << "  RSSI: " << +Rssi << endl;
		cout << "  Data type: " << hex << DataType << dec << endl;
		cout << "  Data length: " + Data.size() << endl << endl;
	}

	void Watcher_OnStopped(void* sender)
	{
		UNREFERENCED_PARAMETER(sender);

		cout << "Monitoring has been stopped" << endl;
	}

	void Watcher_OnStarted(void* sender)
	{
		UNREFERENCED_PARAMETER(sender);

		cout << "Monitoring has been started" << endl;
	}

	static UINT __stdcall _MonitorBeacons(LPVOID Param)
	{
		((CBeacons*)Param)->MonitorBeacons();
		return 0;
	}

	void MonitorBeacons()
	{
		system("cls");
		cout << "MONITORING BLUETOOTH LE BEACONS" << endl;
		cout << "===============================" << endl;

		// Create beacon watcher and set event handlers.
		CwclBluetoothLeBeaconWatcher* Watcher = new CwclBluetoothLeBeaconWatcher();
		__hook(&CwclBluetoothLeBeaconWatcher::OnStarted, Watcher, &CBeacons::Watcher_OnStarted);
		__hook(&CwclBluetoothLeBeaconWatcher::OnStopped, Watcher, &CBeacons::Watcher_OnStopped);
		__hook(&CwclBluetoothLeBeaconWatcher::OnAdvertisementRawFrame, Watcher, &CBeacons::Watcher_OnAdvertisementRawFrame);
		__hook(&CwclBluetoothLeBeaconWatcher::OnEddystoneTlmFrame, Watcher, &CBeacons::Watcher_OnEddystoneTlmFrame);
		__hook(&CwclBluetoothLeBeaconWatcher::OnEddystoneUidFrame, Watcher, &CBeacons::Watcher_OnEddystoneUidFrame);
		__hook(&CwclBluetoothLeBeaconWatcher::OnEddystoneUrlFrame, Watcher, &CBeacons::Watcher_OnEddystoneUrlFrame);
		__hook(&CwclBluetoothLeBeaconWatcher::OnManufacturerRawFrame, Watcher, &CBeacons::Watcher_OnManufacturerRawFrame);
		__hook(&CwclBluetoothLeBeaconWatcher::OnAppleiBeaconFrame, Watcher, &CBeacons::Watcher_OnAppleiBeaconFrame);
		__hook(&CwclBluetoothLeBeaconWatcher::OnAltBeaconFrame, Watcher, &CBeacons::Watcher_OnAltBeaconFrame);
		__hook(&CwclBluetoothLeBeaconWatcher::OnAdvertisementFrameInformation, Watcher, &CBeacons::Watcher_OnAdvertisementFrameInformation);
		__hook(&CwclBluetoothLeBeaconWatcher::OnAdvertisementUuidFrame, Watcher, &CBeacons::Watcher_OnAdvertisementUuidFrame);
		__hook(&CwclBluetoothLeBeaconWatcher::OnAdvertisementService128DataFrame, Watcher, &CBeacons::Watcher_OnAdvertisementService128DataFrame);
		__hook(&CwclBluetoothLeBeaconWatcher::OnAdvertisementService32DataFrame, Watcher, &CBeacons::Watcher_OnAdvertisementService32DataFrame);
		__hook(&CwclBluetoothLeBeaconWatcher::OnAdvertisementService16DataFrame, Watcher, &CBeacons::Watcher_OnAdvertisementService16DataFrame);
		__hook(&CwclBluetoothLeBeaconWatcher::OnAdvertisementServiceSol128Frame, Watcher, &CBeacons::Watcher_OnAdvertisementServiceSol128Frame);
		__hook(&CwclBluetoothLeBeaconWatcher::OnAdvertisementServiceSol32Frame, Watcher, &CBeacons::Watcher_OnAdvertisementServiceSol32Frame);
		__hook(&CwclBluetoothLeBeaconWatcher::OnAdvertisementServiceSol16Frame, Watcher, &CBeacons::Watcher_OnAdvertisementServiceSol16Frame);

		// Try to start watcher.
		InitResult = Watcher->Start(Radio);
		if (InitResult != WCL_E_SUCCESS)
			cout << "Failed to start monitoring. Error: 0x" << hex << InitResult << dec << endl;

		// Initialization completed.
		SetEvent(InitEvent);

		if (InitResult == WCL_E_SUCCESS)
		{
			WaitForSingleObject(Event, INFINITE);
			Watcher->Stop();
		}

		__unhook(Watcher);
		delete Watcher;
	}

	void Advertiser_OnStopped(void* sender)
	{
		UNREFERENCED_PARAMETER(sender);

		cout << "Advertiser has been sopped" << endl;
		Advertiser->Clear();
	}

	void Advertiser_OnStarted(void* sender)
	{
		UNREFERENCED_PARAMETER(sender);

		cout << "Advertiser has been started" << endl;
	}

	void StartAdvertising(CwclBluetoothLeAdvertisement* const Adv)
	{
		Advertiser->Clear();

		InitResult = Advertiser->Add(Adv);
		if (InitResult != WCL_E_SUCCESS)
		{
			cout << "  Add advertisement failed. Error: 0x" << hex << InitResult << dec << endl;
			delete Adv;
		}
		else
		{
			InitResult = Advertiser->Start(Radio);
			if (InitResult != WCL_E_SUCCESS)
				cout << "  Start advertiser failed. Error: 0x" << hex << InitResult << dec << endl;
		}

		SetEvent(InitEvent);

		if (InitResult == WCL_E_SUCCESS)
		{
			WaitForSingleObject(Event, INFINITE);
			Advertiser->Stop();
		}
	}

	static UINT __stdcall _ProximityBeacon(LPVOID Param)
	{
		((CBeacons*)Param)->ProximityBeacon();
		return 0;
	}

	void ProximityBeacon()
	{
		system("cls");
		cout << "BLUETOOTH LE PROXIMITY BEACON" << endl;
		cout << "=============================" << endl;

		StartAdvertising(new CwclBluetoothLeProximityBeaconAdvertisement(-5, 0x0101,
			0x0202, BEACON_UUID, 0xFFFE));
	}

	static UINT __stdcall _AltBeacon(LPVOID Param)
	{
		((CBeacons*)Param)->AltBeacon();
		return 0;
	}

	void AltBeacon()
	{
		system("cls");
		cout << "BLUETOOTH LE ALT BEACON" << endl;
		cout << "=======================" << endl;

		StartAdvertising(new CwclBluetoothLeAltBeaconAdvertisement(-5, 0x0101,
			0x0202, BEACON_UUID, 0xFFFE, 0x11));
	}

	static UINT __stdcall _EddystoneUidBeacon(LPVOID Param)
	{
		((CBeacons*)Param)->EddystoneUidBeacon();
		return 0;
	}

	void EddystoneUidBeacon()
	{
		system("cls");
		cout << "BLUETOOTH LE EDDYSTONE UID BEACON" << endl;
		cout << "=================================" << endl;

		StartAdvertising(new CwclBluetoothLeEddystoneUidBeaconAdvertisement(-5, BEACON_UUID));
	}

	static UINT __stdcall _EddystoneUrlBeacon(LPVOID Param)
	{
		((CBeacons*)Param)->EddystoneUrlBeacon();
		return 0;
	}

	void EddystoneUrlBeacon()
	{
		system("cls");
		cout << "BLUETOOTH LE EDDYSTONE URL BEACON" << endl;
		cout << "=================================" << endl;

		StartAdvertising(new CwclBluetoothLeEddystoneUrlBeaconAdvertisement(-5,
			L"https://www.btframework.com"));
	}

	static UINT __stdcall _CustomBeacon(LPVOID Param)
	{
		((CBeacons*)Param)->CustomBeacon();
		return 0;
	}

	void CustomBeacon()
	{
		system("cls");
		cout << "BLUETOOTH LE CUSTOM BEACON" << endl;
		cout << "==========================" << endl;

		string Str = "WCL Custom Beacon";
		wclBluetoothLeAdvertisementFrameRawData Data;
		Data.resize(Str.length());
		memcpy(&Data.front(), Str.c_str(), Str.length());
		StartAdvertising(new CwclBluetoothLeManufacturerAdvertisement(0xFFFE, Data));
	}

	void StartThread(_beginthreadex_proc_type Proc)
	{
		RunThread = (HANDLE)_beginthreadex(NULL, 0, Proc, this, 0, NULL);
		if (RunThread == NULL)
			cout << "Start thread failed" << endl;
		else
		{
			//. Wait for initialization.
			WaitForSingleObject(InitEvent, INFINITE);
			if (InitResult == WCL_E_SUCCESS)
			{
				system("pause");
				SetEvent(Event);
			}
			WaitForSingleObject(RunThread, INFINITE);
			CloseHandle(RunThread);
			RunThread = NULL;
		}
	}

public:
	CBeacons()
	{
		Radio = NULL;
		InitResult = WCL_E_SUCCESS;
		InitEvent = NULL;
		Event = NULL;
		RunThread = NULL;

		Advertiser = new CwclBluetoothLeAdvertiser();
		__hook(&CwclBluetoothLeAdvertiser::OnStarted, Advertiser, &CBeacons::Advertiser_OnStarted);
		__hook(&CwclBluetoothLeAdvertiser::OnStopped, Advertiser, &CBeacons::Advertiser_OnStopped);
	}

	~CBeacons()
	{
		Advertiser->Stop();
		Advertiser->Clear();

		__unhook(Advertiser);

		delete Advertiser;
	}

	void Run()
	{
		system("cls");

		cout << "Beacon IoT demo." << endl;
		cout << "The demo shows how to use Bluetooth Framework on Windows 10 IoT devices" << endl;
		cout << "in console mode using Asynchronous message processing." << endl;

		// Create termination event.
		Event = CreateEvent(NULL, FALSE, FALSE, NULL);
		if (Event == NULL)
			cout << "Create termination event failed" << endl;
		else
		{
			// Try to create initialization event.
			InitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
			if (InitEvent == NULL)
				cout << "Create initialization event failed" << endl;
			else
			{
				// Create Bluetooth Manager.
				CwclBluetoothManager* Manager = new CwclBluetoothManager();
				Manager->MessageProcessing = mpAsync;
				// Try to open Bluetooth Manager.
				int Res = Manager->Open();
				if (Res != WCL_E_SUCCESS)
					cout << "Error opening Bluetooth Manager: 0x" << hex << Res << dec << endl;
				else
				{
					if (Manager->Count == 0)
						cout << "Not Bluetooth hardware found." << endl;
					else
					{
						for (size_t i = 0; i < Manager->Count; i++)
						{
							if (Manager->Radios[i]->Available)
							{
								Radio = Manager->Radios[i];
								break;
							}
						}

						if (Radio == NULL)
							cout << "No available Bluetooth hardware were found." << endl;
						else
						{
							bool Terminated = false;
							do
							{
								cout << "BLUETOOTH LE BEACONS DEMO" << endl;
								cout << "=========================" << endl;
								cout << "  1 - Monitor Beacons" << endl;
								cout << "  2 - Start Proximity Beacon" << endl;
								cout << "  3 - Start Eddystone UID Beacon" << endl;
								cout << "  4 - Start Eddystone URL Beacon" << endl;
								cout << "  5 - Start Custom Beacon" << endl;
								cout << "  6 - Start Alt Beacon" << endl;
								cout << "  0 - Exit" << endl;
								cout << "Select option: ";
								int opt;
								cin >> opt;
								cout << endl;

								switch (opt)
								{
								case 0:
									Terminated = true;
									break;
								case 1:
									StartThread(_MonitorBeacons);
									break;
								case 2:
									StartThread(_ProximityBeacon);
									break;
								case 3:
									StartThread(_EddystoneUidBeacon);
									break;
								case 4:
									StartThread(_EddystoneUrlBeacon);
									break;
								case 5:
									StartThread(_CustomBeacon);
									break;
								case 6:
									StartThread(_AltBeacon);
									break;
								default:
									cout << "Wrong selection. Try again." << endl;
									break;
								}
							} while (!Terminated);

							Radio = NULL;
						}
					}
					// Close Bluetooth Manager.
					Manager->Close();
				}
				delete Manager;

				// Release initialization event.
				CloseHandle(InitEvent);
			}
			// Close termination event.
			CloseHandle(Event);
		}
	}
};

int main(int argc, char **argv)
{
	UNREFERENCED_PARAMETER(argc);
	UNREFERENCED_PARAMETER(argv);

	CBeacons* Beacons = new CBeacons();
	Beacons->Run();
	delete Beacons;
}