#pragma once
#include "VPCmdIF.h"
#include <vector>
#include <mutex>


#define POLHEMUS_VID 0x0f44
#define TX_BUF_SIZE  0x800

class CVPusbIO;
class CVPdevIO;
class CVPcontext
{
public:
	CVPcontext();
	virtual ~CVPcontext();

	int connectNewUSB(vpdev_hnd &, uint16_t vid, uint16_t pid, uint32_t tag=0);
	//int discoverSerCnx(vpdev_hnd & hnd);
	int connectNewSer(vpdev_hnd &, int32_t serport, uint32_t sercfg = 0);
	int SendRecv(vpdev_hnd, CVPcmd&, CFrameInfo&, bool bWantRsp=true);
	int & TraceLev() { return m_eTraceLev; }
	void SetTraceLev(int);

	static std::vector<CVPcontext *> g_vecActiveCtx;
	static bool findPctx(CVPcontext *);
	static void destroyPctx(CVPcontext *);
	static void pushPctx(CVPcontext *);

	std::vector<CVPdevIO *> m_vecDevCnx;
	bool findPdev(CVPdevIO *);
	void destroyPdev(CVPdevIO *);
	void destroyAlldevs();
	void pushPdev(CVPdevIO *);

	std::string m_strReports;
	std::wstring m_wstrReports;
	void reportsClear() {
		m_strReports.clear();
		m_wstrReports.clear();
	}
	void reportAlldevs();
	const char * reportBuf() { return m_strReports.c_str(); }
	const wchar_t* reportBufW() { return m_wstrReports.c_str(); }

	int dev_release(vpdev_hnd hnd);

	int dev_SetPnoCB(vpdev_hnd, VP_PNOREADY_CALLBACK cb, PVOID pInfo);
	int dev_tracelev(vpdev_hnd, int iT);
	int dev_timeoutms(vpdev_hnd, eCmdActions, int ms);
	int dev_report(vpdev_hnd);
	int dev_info(vpdev_hnd hnd, const WHOAMI_STRUCT *& ,  VIPER_SEUID & );
	int dev_tsenable(vpdev_hnd hnd, bool tsEn);
	int dev_pnofrmerr_allow(vpdev_hnd hnd, bool ballow);
	int dev_pnousb_buffer(vpdev_hnd hnd, uint32_t count);

	static void traceBufcmd(std::string& s, uint8_t* pBuf, int32_t iCount, bool bCR, const char* szPre);
	static void traceBufpno(std::string& s, uint8_t* pBuf, int32_t iCount, bool bCR, const char* szPre);

	int cmd_dev					(vpdev_hnd, eViperCmds, eCmdActions, uint8_t* pbuf = 0, uint32_t bufsize = 0, uint32_t a1 = 0, uint32_t a2 = 0);
	int cmd_sns					(vpdev_hnd, int sns, eViperCmds, eCmdActions, uint8_t* pbuf = 0, uint32_t bufsize = 0, uint32_t a2 = 0);

	int cmd_dev_gen				(vpdev_hnd, uint32_t cmd, eCmdActions, uint8_t* pbuf = 0, uint32_t bufsize = 0, uint32_t a1 = 0, uint32_t a2 = 0);
	int cmd_sns_gen				(vpdev_hnd, int sns, uint32_t cmd, eCmdActions, uint8_t* pbuf = 0, uint32_t bufsize = 0, uint32_t a2 = 0);

	int cmd_dev_bit					(vpdev_hnd,				 BIT_STRUCT *);
	int cmd_dev_bit_report			(vpdev_hnd);
	int cmd_dev_resetblockcfg		(vpdev_hnd);
	int cmd_dev_framerate			(vpdev_hnd, eCmdActions, FRAMERATE_CONFIG *);
	int cmd_dev_persist				(vpdev_hnd);
	int cmd_dev_selfcalstate		(vpdev_hnd, eCmdActions, SELFCAL_CONFIG*);
	int cmd_dev_selfcalsave 		(vpdev_hnd, eCmdActions, BINARY_CONFIG*);
	int cmd_dev_resetfc				(vpdev_hnd);
	//int cmd_dev_restart				(vpdev_hnd);
	int cmd_dev_seuid				(vpdev_hnd, eCmdActions, SEUID_CONFIG *);
	int cmd_dev_serialif			(vpdev_hnd, eCmdActions, SERIAL_CONFIG *);
	int cmd_dev_sourcerot			(vpdev_hnd, int src, eCmdActions, SRCROT_CONFIG *);
	int cmd_dev_sourcecfg			(vpdev_hnd, int src, eCmdActions, SRC_CONFIG *);
	int cmd_dev_stationmap			(vpdev_hnd, eCmdActions, STATION_MAP *);
	int cmd_dev_stylusmode			(vpdev_hnd, eCmdActions, STYLUS_CONFIG *wai);
	int cmd_dev_syncmode			(vpdev_hnd, eCmdActions, BINARY_CONFIG *);
	int cmd_dev_units				(vpdev_hnd, eCmdActions, UNITS_CONFIG *);
	int cmd_dev_dualoutput			(vpdev_hnd, eCmdActions, BINARY_CONFIG *);
	int cmd_dev_whoami				(vpdev_hnd,				 WHOAMI_STRUCT *);
	int cmd_dev_whoami_report		(vpdev_hnd);
	int cmd_dev_sourcewhoami		(vpdev_hnd hnd, int src, WHOAMI_STRUCT * out_wai);
	int cmd_dev_sourcewhoami_report	(vpdev_hnd hnd, int src);

	int cmd_dev_contpno			(vpdev_hnd, eCmdActions, CONT_FC_CONFIG *, ePnoMode);
	int cmd_dev_singlepno		(vpdev_hnd, vpFrameInfo &, ePnoMode);

	int cmd_sns_boresight		(vpdev_hnd, int sns, eCmdActions, BORESIGHT_CONFIG *wai, uint32_t resetorigin);
	int cmd_sns_filter			(vpdev_hnd, int sns, eCmdActions, FILTER_CONFIG *wai, eViperFilterTargets etar);
	int cmd_sns_ftt				(vpdev_hnd, int sns, eCmdActions, ENUM_CONFIG *wai);
	int cmd_sns_ftthome			(vpdev_hnd, int sns, eCmdActions, PNODATA *wai, eFTTHomeMethod eMethod);
	int cmd_sns_srcselect		(vpdev_hnd, int sns, eCmdActions, SRC_SEL_CONFIG *wai);
	int cmd_sns_origin			(vpdev_hnd, int sns, eCmdActions, ENUM_CONFIG *wai);
	int cmd_sns_virtual			(vpdev_hnd, int sns, eCmdActions, VIRTUAL_SNS_CONFIG *wai);
	int cmd_sns_blockcfg		(vpdev_hnd, int sns, eCmdActions, SENSOR_CONFIG *wai);
	int cmd_sns_predfilter		(vpdev_hnd, int sns, eCmdActions, PF_CONFIG *);
	int cmd_sns_predfilterext	(vpdev_hnd, int sns, eCmdActions, PF_CONFIG_EXT *);
	int cmd_sns_hemisphere		(vpdev_hnd, int sns, eCmdActions, HEMISPHERE_CONFIG *wai);
	int cmd_sns_increment		(vpdev_hnd, int sns, eCmdActions, INCREMENT_CONFIG *wai);
	int cmd_sns_tipoffset		(vpdev_hnd, int sns, eCmdActions, TIP_OFFSET_CONFIG *wai);
	int cmd_sns_whoami			(vpdev_hnd, int sns, WHOAMI_STRUCT *);
	int cmd_sns_whoami_report	(vpdev_hnd, int sns);

	int dev_fifopnof			(vpdev_hnd, CFrameInfo &);
	int dev_fifopnofraw			(vpdev_hnd, CFrameInfo &);
	int dev_fifo_count			(vpdev_hnd, uint32_t & fc, uint32_t & bc);
	int dev_fifo_readrawbuf		(vpdev_hnd, uint32_t & fc, uint8_t *& pbuf, uint32_t & size);
	int dev_lastpnof			(vpdev_hnd, CFrameInfo &);
	int dev_lastpnofraw			(vpdev_hnd, CFrameInfo &);
	int dev_resetpno			(vpdev_hnd);

	int dev_nextpnof			(vpdev_hnd, CFrameInfo &);

	int     m_ntxcount;
	uint8_t m_txbuf[TX_BUF_SIZE];

	int m_eTraceLev;
	uint32_t m_dev_USBBufcount;

protected:
	std::mutex m_mtxTxData;


};


