#include <iostream>
#include "string.h"
#include "TiproHidApi.h"
#include <unistd.h>

/**
 * @brief Callback function for returning pressed/released keys programmed with HID telephony content
 * @param nID ID of the telephony device (supporting more then one telephony devices on the same PC)
 * @param nUsagePage Top collection usage page (for now always 0x0b = Telephony)
 * @param nLinkUsage Usage of the specific link collection (0x01 = Phone, 0x06 = Key Pad, 0x07 = Progrmable Button)
 * @param nUsage Usage at the specific collection
 * @param bPressed Key pressed = TRUE or released = FALSE
 * @return 0
 */
int function_to_recive_callbacks(USHORT nID, USHORT nUsagePage, USHORT nLinkUsage, USHORT nUsage, bool bPressed)
{
	std::cout << "Key event - device id: " << nID << " usagepage: " << nUsagePage << " linkusage: " << nLinkUsage << " usage: " << nUsage 
		<< ((bPressed) ? " Pressed" : " Released") << std::endl;
	return 0;
}

int main(int argc, char **argv)
{
	int res = -1;
	const int MAX_STR = 255;

	//***********************************************************
	// Detect and list connected Tipro devices and their modules
	//***********************************************************

	//search for connected devices with Tipro controller
	res = HIDDetectDevices();
	if (res == 0)
	{
		//get number of detected devices
		int num = HIDGetNumOfDetectedDevices();
		
		if (num > 0)
			std::cout << num << " Tipro device(s) detected." << std::endl;
		else
			std::cout << "No Tipro device detected." << std::endl;
		
		for (int i=0; i<num; i++)
		{
			//select device to comunicate with
			res = HIDSelectDeviceEx(i);
			if (res == 0)
			{
				//enumerate device modules
				res = HIDEnumerateModules();
				if (res == 0)
				{
					std::cout << std::endl << "*** Tipo device " << i << " ***" << std::endl;
					wchar_t wstr[MAX_STR];
					
					//get controller info
					int vmaj, vmin, vbuild, vcustom, fwlevel;
					res = HIDGetControllerInfo(&vmaj, &vmin, &vbuild, &vcustom, &fwlevel);
					if (res == 0)
					{
						std::cout << std::hex << "   controller ver: " << vmaj << "." << vmin << "." << vbuild << "." << vcustom << " fw_level: " << fwlevel << std::endl;
					}
					
					for (int j=0; j<16; j++)
					{
						//get module info
						unsigned char cmaj, cmin, cbuild, ctype, cid;
						res = HIDGetModuleVersionEx(j, &cmaj, &cmin, &cbuild, &ctype, &cid);
						if (res != 0)
						{
							break;
						}
						std::cout << std::hex << "   module" << j << " ver: " << static_cast<int>(cmaj) << "." << static_cast<int>(cmin) << "." << static_cast<int>(cbuild) 
							<< " type: " << static_cast<int>(ctype) << " id: " << static_cast<int>(cid) << std::endl;
					}
					
					//manage modules by using module specific functions
				}
			}
		}
	}
	else
	{
		std::cout << "HIDDetectDevices() error: " << res << std::endl;
	}
	
	std::cout << std::endl;


	//****************************
	// Catch HID Telephony events
	//****************************

	//detect conected devices with HID telephony support
	res = HIDDetectTelephonyDevices();
	if (res == 0)
	{
		//get number of HID telephony devices
		int num = HIDGetNumOfDetectedTelephonyDevices();
		
		if (num > 0)
			std::cout << num << " HID telephony device(s) detected." << std::endl;
		else
			std::cout << "No HID telephony device detected." << std::endl;
		
		for (int i=0; i<num; i++)
		{
			std::cout << std::endl << "*** HID telephony device " << i << " ***" << std::endl;
			wchar_t wstr[MAX_STR];
			char cstr[MAX_STR];
			short unsigned int vid, pid;
			
			//get HID telephony device info
			res = HIDGetTelephonyDevice_VID_PID(i, &vid, &pid);
			if (res == 0)
			{
				std::cout << std::hex << "   vendor id: 0x" << vid << std::endl << "   product id: 0x" << pid << std::endl;
			}
			
			memset(cstr, 0, MAX_STR);
			res = HIDGetTelephonyDevicePath(i, &cstr, MAX_STR);
			if (res == 0)
			{
				std::cout << "   device path: " << cstr << std::endl;
			}

			//register callback function
			HIDRegisterTelephonyCallbacks(i, function_to_recive_callbacks, NULL); 
		}
		
		try
		{
  			std::cout << std::endl << "Press keys programmed with HID telephony content." << std::endl << "Press Enter key to exit..." << std::endl; 

   			//wait for enter key
			getchar();

			for (int i=0; i<num; i++)
			{
				//unregister callback function
				HIDStopTelephonyKeyDevice(i);
			}
        	
		}
		catch (std::exception const &exc)
		{
			std::cout << "Exception caught " << exc.what() << "\n";
		}
		catch (...)
		{
			std::cout << "Unknown exception caught\n";
		}
		
	}
	else
	{
		std::cout << "HIDDetectTelephonyDevices() error: " << res << std::endl;
	}
	
	return 0; 
}
