/**
 * @file TiproHidDevice.h
 * 
 * Tipro HID device
 * 
 * This file includes a class that reprisents a Tipro device.
 * 
 * Tipro device is composed of Tipro modules and has one Tipro controller.
 * 
 * Tipro
 * 
 * support@tipro.si
 * 
 * Copyright 2021-2024
 */

#ifndef _TIPRO_TIPROHIDAPI_TIPROHIDDEVICE_H_
#define _TIPRO_TIPROHIDAPI_TIPROHIDDEVICE_H_

#include <mutex>


typedef unsigned char UCHAR;

/**
 * @class TiproHidDevice
 * @file TiproHidDevice.h
 * @brief Represents Tipro device
 */
class TiproHidDevice
{
public:
	
	enum ETErrCode
	{
		// compatible with EErrCode from CHid -> converted in ConvertErr() function
		terrNone,										// 0x00
		terrWrongParameter,								// 0x01
		terrInvalidHandleValue,							// 0x02
		terrDeviceNotOpened,							// 0x03
		terrGetFeature,									// 0x04
		terrSetFeature,									// 0x05
		terrUnknown,									// 0x06
		// CTiproHid specific errors
		terrCmdNotSupportedAtFWLevel,					// 0x07
		terrFWLevelNotAvailable,						// 0x08
		terrFWLevelChangeFailed,						// 0x09
		terrWTCDelayExpired,							// 0x0A
		terrWrongSignatureBytes,						// 0x0B
		terrResponseTimoutExpired,						// 0x0C
		// Firmware exchange errors
		terrExchStatusVoid,								// 0x0D
		terrExchStatusReqTO,							// 0x0E
		terrExchStatusReqReject,						// 0x0F
		terrExchStatusReqFail,							// 0x10
		terrExchStatusReqSucc,							// 0x11
		terrExchStatusAnsPend,							// 0x12
		terrExchStatusAnsTO,							// 0x13
		terrExchStatusAnsReject,						// 0x14
		terrExchStatusAnsFail,							// 0x15
		terrExchStatusAnsOK,							// 0x16
		terrExchStatusFWBug								// 0x17
	};

	//20190904
	static const UCHAR FRCMD_RESET 				= 0x00;
	static const UCHAR FRCMD_TMC_IF_DISABLE 	= 0x01;
	static const UCHAR FRCMD_TMC_IF_ENABLE 		= 0x02;
	static const UCHAR FRCMD_TMC_IF_V2_ENABLE 	= 0x03;
	static const UCHAR FRCMD_LEVEL1_CMD 		= 0x04;
	static const UCHAR FRCMD_CLR_SERIAL_NO 		= 0x05;
	static const UCHAR FRCMD_OPT_IF 			= 0x06;
	static const UCHAR FRCMD_FW_LEVEL 			= 0x07;
	static const UCHAR FRCMD_MID_EXCH 			= 0x08;

	
	/**
	 * @brief Opens device for communication
	 * @return Error code (0 - no error)
	 */
	virtual int Open();
	
	/**
	 * @brief Closes device
	 * @return Error code (0 - no error)
	 */
	virtual int Close();
	
	/**
	 * @brief Constructor
	 */
	TiproHidDevice();
	
	/**
	 * @brief Constructor
	 * @param path Device path
	 */
	TiproHidDevice(const char path[]);
	
	/**
	 * @brief Destructor
	 */
	virtual ~TiproHidDevice();
	
	/**
	 * @brief Constructor
	 * @param other Created from that device
	 */
	TiproHidDevice(const TiproHidDevice& other);
	
	/**
	 * @brief Compare operator
	 * @param other Device to compare to
	 */
	virtual TiproHidDevice& operator= (const TiproHidDevice& other);
	
	/**
	 * @brief Sends command to the device
	 * @param nCommand Command 
	 * @param nDest Destination
	 * @param pParameters Data
	 * @param nLen Length of data
	 * @param pResponse Answer data
	 * @param nResponseLen Length of answer data
	 * @return Error code (0 - no error)
	 */
	virtual int SendCommandToConnectedDeviceEx(const UCHAR nCommand, const UCHAR nDest, const UCHAR *pParameters, const int nLen, UCHAR *pResponse, int *nResponseLen);
	
	/**
	 * @brief Enumerates modules of the device
	 * @return Error code (0 - no error)
	 */
	virtual int EnumerateModules();//201907from tiprohidapiwindows
	
	/**
	 * @brief Returns path name of the device
	 * @return Platform-specific device path
	 */
	virtual const char* GetPath();
	
	/**
	 * @brief Resets the device
	 * @return Error code (0 - no error)
	 */
	virtual int Reset();
	
	/**
	 * @brief Gets a string from device, based on its string index
	 * @param[in] lStrIx The index of the string to get
	 * @param[out] pString A wide string buffer to put the data into
	 * @param[in] lBufferLen The length of the buffer in multiples of wchar_t
	 * @return Error code (0 - no error)
	 */
	virtual int GetIndexedStringDescriptor(int lStrIx, wchar_t *pString, int lBufferLen);
	
	/**
	 * @brief Gets manufacturer string from device
	 * @param[out] pString A wide string buffer to put the data into
	 * @param[in] lBufferLen The length of the buffer in multiples of wchar_t
	 * @return Error code (0 - no error)
	 */
	virtual int GetManufacturerString(wchar_t *pString, int lBufferLen);
	
	/**
	 * @brief Gets product string from device
	 * @param[out] pString A wide string buffer to put the data into
	 * @param[in] lBufferLen The length of the buffer in multiples of wchar_t
	 * @return Error code (0 - no error)
	 */
	virtual int GetProductString(wchar_t *pString, int lBufferLen);
	
	/**
	 * @brief Gets serial number string from device
	 * @param[out] pString A wide string buffer to put the data into
	 * @param[in] lBufferLen The length of the buffer in multiples of wchar_t
	 * @return Error code (0 - no error)
	 */
	virtual int GetSerialNumberString(wchar_t *pString, int lBufferLen);
	
	/**
	 * @brief Gets module version from device, based on module index
	 * @param[in] nIndex Module index (zero based, from right to left)
	 * @param[out] nVerMaj Major version of module
	 * @param[out] nVerMin Minor version of module
	 * @param[out] nVerBuild Build version of module
	 * @return Error code (0 - no error)
	 */
	virtual int GetModuleVersion(int nIndex, unsigned char *nVerMaj, unsigned char *nVerMin, unsigned char *nVerBuild);
	
	/**
	 * @brief Gets module version, type and ID from device, based on module index
	 * @param[in] nIndex Module index (zero based, from right to left)
	 * @param[out] nVerMaj Major version of module
	 * @param[out] nVerMin Minor version of module
	 * @param[out] nVerBuild Build version of module
	 * @param[out] nModuleType Module type
	 * @param[out] nModuleID Module ID
	 * @return Error code (0 - no error)
	 */
	virtual int GetModuleVersionEx(int nIndex, unsigned char *nVerMaj, unsigned char *nVerMin, unsigned char *nVerBuild, unsigned char *nModuleType, unsigned char *nModuleID);
	
	/**
	 * @brief Gets controller version of device
	 * @param[out] nVerMaj Major version of controller
	 * @param[out] nVerMin Minor version of controller
	 * @param[out] nVerBuild Build version of controller
	 * @param[out] nVerCustom Custom version of controller
	 * @param[out] nFWLevel Firmware level of controller
	 * @return Error code (0 - no error)
	 */
	virtual int GetControllerInfo(int *nVerMaj, int *nVerMin, int *nVerBuild,int *nVerCustom, int *nFWLevel);
	
	/**
	* @brief Sets controller to specified key layer
	* @param[in] nLayer New active layer (KEY_LAYER1, KEY_LAYER2, KEY_LAYER3, KEY_LAYER4)
	* @return Command status: 0-OK, else error code
	*/
	virtual int SetKeyLayer(int nLayer);
	
	
};

#endif