#pragma once

#include "FuncList.h"

#define WM_USER_ExecutionComplete	WM_USER + 0x2020
#define WM_USER_DeviceRemoval		WM_USER + 0x2021

FARPROC WINAPI GetProcAddress_W(__in HMODULE hModule, __in LPWSTR lpProcName);

#define REGKEY_SWI			L"SOFTWARE\\Sierra Wireless Inc"
#define REGKEY_AppName		L"GobiTestApp"
#define REGVAL_MainApi		L"Main API"
#define REGVAL_SecondApi	L"Second API"
#define REGVAL_UseSecond	L"UseSecondApi"

class CApiHelper
{
public:
	CApiHelper(void);
	virtual ~CApiHelper(void) = 0;

	///////////////////////////////////////////////////////////////////////////////
	///
	///	Initialize API helper
	///
	///	\param	[IN] pParent
	///			Handle to parent window
	///
	///	\return	TRUE if initialization successful, FALSE otherwise			
	///
	///////////////////////////////////////////////////////////////////////////////
	virtual BOOL Initialize(CWnd* pParent);

	///////////////////////////////////////////////////////////////////////////////
	///
	///	Uninitialize API helper
	///
	///	\return	TRUE if un-initialization successful, FALSE otherwise			
	///
	///////////////////////////////////////////////////////////////////////////////
	virtual BOOL Uninitialize() = 0;

	///////////////////////////////////////////////////////////////////////////////
	///
	///	Get list of available functions
	///
	///	\param	[OUT] pFuncList
	///			List of available functions
	///
	///	\return	TRUE if successfully retrieve list of available functions, 
	///			FALSE otherwise			
	///
	///////////////////////////////////////////////////////////////////////////////
	virtual BOOL GetAvailFuncList(CFuncList* pFuncList) = 0;

	///////////////////////////////////////////////////////////////////////////////
	///
	///	Copies list of functions to execute and signal worker thread to begin
	/// execution.  Caller thread is not blocked.  Completion of API calls is
	/// signaled by posting WM_USER_ExecutionComplete message to parent window
	/// previously provided with the Initialize call.
	///
	///	\param	[IN] pFuncList
	///			List of functions to execute
	///
	///	\return	TRUE if functions successfully copied and worker thread successfully
	///			signaled, FALSE otherwise			
	///
	///////////////////////////////////////////////////////////////////////////////
   	CFuncList* GetCurrentFuncList(){return &m_FuncList;};
	virtual BOOL ExecuteFunctions(CFuncList* pFuncList) = 0;

protected:
	static DWORD WINAPI WorkerThreadProc(void* pParam);
	DWORD WorkerThread();

	static CWnd* m_pParent;		// handle to parent window
	HANDLE m_hWorkerThread;		// handle to thread which makes all the API calls
	HANDLE m_hWorkerThreadExit;	// signal when you wish to terminate the worker thread
	HANDLE m_hActionToDo;		// signal when there is something for the worker thread to do

	CFuncList m_FuncList;		// list of functions to execute

	static BOOL m_bInitialized;		// TRUE if API initialized, FALSE otherwise

	virtual BOOL Execute() = 0;
};
