// ------------------------------------------------------------------
//	File: gtapi_face.h
//
//	Description:	This header file includes is the master file that
//                includes all of the required header files for developing
//				   a SIP project.
//
// ==================================================================
// IF YOU DO NOT AGREE WITH THE FOLLOWING STATEMENT, YOU MUST 
// PROMPTLY RETURN THE SOFTWARE AND ANY ACCOMPANYING DOCUMENTATION 
// ("PRODUCT") TO PCBest Networks(www.pcbest.net).
//
// PCBest Networks owns all title and 
// ownership rights to Software.  "Software" means any data processing
// programs (hereinafter "programs") consisting of a series of 
// instructions or statements in object code form, including any 
// systemized collection of data in the form of a data base, and any
// related proprietary materials such as flow charts, logic diagrams, 
// manuals media and listings provided for use with the programs.
// User has no right, express or implied, to transfer, sell, provide
// access to or dispose of Software to any third party without PCBest Networks'
// prior written consent.  User will not copy, reverse assemble,
// reverse engineer, decompile, modify, alter, translate or display
// the Software other than as expressly permitted by PCBest Networks in writing.
// ------------------------------------------------------------------

#ifndef GTAPI_HIGH_LEVEL_INTERFACE_HEAD_FILE
#define GTAPI_HIGH_LEVEL_INTERFACE_HEAD_FILE

#include <stdio.h>
#include <time.h>
#include "GTNetCmdClient.h"
#include "GTCfg.h"
#include "GTLog.h"

//#define GTAPI_FACE_OP_ASYNC

#define	GTAPI_FACE_AUDIO_DONE_DTMF_TIMEOUT							0
#define	GTAPI_FACE_AUDIO_DONE_DTMF_MAX_DIGITS						1
#define	GTAPI_FACE_AUDIO_DONE_DTMF_DIGIT_DETECTED					2
#define	GTAPI_FACE_AUDIO_DONE_PLAY									3
#define	GTAPI_FACE_AUDIO_DONE_RECORD								4
#define	GTAPI_FACE_AUDIO_DONE_FORCED_STOP							5

#define GTSRV_INI_PLUGIN						"gtsrv.plugin.dll"
#define GTSRV_INI_NET_PORT						"gtsrv.net.port"
#define GTSRV_INI_NET_PORT_DEF					9220
#define GTSRV_INI_LOG_LEVEL						"gtsrv.log.level"
#define GTSRV_INI_LOG							"gtsrv.log.filename"
#define GTSRV_INI_LOG_FILE_SIZE					"gtsrv.log.size"
#define GTSRV_INI_LOG_FILE_NUM					"gtsrv.log.file.number"
#define GTSRV_INI_LOG_TO_CONSOLE				"gtsrv.log.to.console"
#define GTSRV_INI_HW_CFG						"gtsrv.hardware.config.file"
#define GTSRV_DEFAULT_SIP_PORT					7720
#define GTSRV_DEFAULT_RTP_PORT					16400

#define GTSRV_CFG_FILENAME						"gtsrv.config.filename"
#define GTSRV_CFG_LIC_KEY						"gtsrv.licence.key"
#define GTSRV_LIC_USB_DRIVER					"gtsrv.lic.usb.key.driver"

#define LIC_REG_ON_SERVER_DEFAULT				1
#define LIC_REG_ON_SERVER						"gtsrv.reg.lic.on.server"

#define GTSRV_CFG_VIDEO_RESOLUTION              "gtsrv.video.resolution"

#define GTSRV_WAIT_FOR_CALL_MODE				"gtsrv.wait.for.call.mode"
#define GTSRV_INBOUND_CALL_TYPE					"gtsrv.inbound.call.type"


#ifdef USE_GTAPI_NAMESPACE
namespace GTAPI
{
#endif

class CGTOpAsyncCompound;


struct GT_DLL_API GTAPI_Channel: public CGTLogInterface
{
public:
	enum GTAPI_CHANNEL_STATE
	{
		GTAPI_CHANNEL_IDLE,
		GTAPI_CHANNEL_OFFERED,
		GTAPI_CHANNEL_DIALNG,
		GTAPI_CHANNEL_CONNECTED,
		GTAPI_CHANNEL_DISCONNECTING,
		GTAPI_CHANNEL_RESERVED
	};

public:
	unsigned int		ch_index;

	bool				originate;

	GTAPI_CHANNEL_STATE ch_status;

	char				caller_num[255];
	char				callee_num[255];

	time_t				call_start_time;
	time_t				call_end_time;

	GTNetCmdClientI*	pNetClient;

	GT_HANDLE		timer_h;
	GT_HANDLE		reserved_h;

	bool				call_succeed;
	//int					sent_hold;

	char				dtmf_str[256];

	CGTOpAsyncCompound*					m_pOpAsyncCompound;


	bool				bDetectHumanOrMachine;
	GT_HANDLE			hDetectHumanOrMachineTimer;
	unsigned int		tickConnected;
	unsigned int		tickFirstVoiceOn;
	unsigned int		tickFirstVoiceOff;
	unsigned int		tickSecondVoiceOn;

	//customer data
	unsigned long		user_data[10];
	char*				user_str[10];

public:
	GTAPI_Channel();
	virtual ~GTAPI_Channel();
	virtual void Reset();

	void AllocUserStr();
	void FreeUserStr();

	void StartTimer(unsigned long milli_secs);
	void StopTimer();
	virtual void OnTimer();

	static void chan_timer_callback(
		void *pData, //the reserved data
		unsigned int idEvent,  // timer identifier
		unsigned int dwTime   // current system time
		);

	void AppendDTMFStr(const char* s);
	void AppendDTMFStr(char c);
	const char* GetDTMFStr(){return dtmf_str;}

	bool Reserve();
	bool Free();

	void				StartHumanDetection(unsigned int dur);
	void				SubmitHumanDetectionResult();

};

class GT_DLL_API CGTAPIEnv : public GTNetCmdClientI, public CGTCfgInterface, public CGTLogInterface
{
public:
	CGTAPIEnv();
	virtual ~CGTAPIEnv();

	static CGTAPIEnv* GetGTAPIEnv();

	static const char*		GetLocalIP(int idx);
	static int				GetLocalIPCount();
	static GT_BOOL			GetSIPAddressInfo(char *str_FullAddress, char** pstr_Name, char** pstr_Address, char** pstr_Port);

	virtual bool StartServer();
	virtual bool StopServer();

	virtual GTAPI_Channel* AllocChannels(){return new GTAPI_Channel;}
	virtual void FreeChannels(GTAPI_Channel* p){delete p;}

	virtual bool InitMicCtrl();
	virtual bool FreeMicCtrl();
	virtual bool InitSpkCtrl();
	virtual bool FreeSpkCtrl();

	unsigned int GetTotalChannelNumber();

	GTAPI_Channel*	GetChannel(int idx);

	unsigned short GetLocalSIPPort();
	unsigned short GetLocalRTPPort();

	void LoadConfigFile();

//sound device assistance

	void		SetMicVolume(float v);
	float		GetMicVolume();
	void		SetSpeakerVolume(float v);
	float		GetSpeakerVolume();

	void		SetSpeakerMuteStatus(GT_BOOL bMute);
	GT_BOOL		GetSpeakerMuteStatus();
	void		SetMicMuteStatus(GT_BOOL bMute);
	GT_BOOL		GetMicMuteStatus();

	static unsigned int GetSoundDeviceCount();
	static const char* GetSoundDeviceName(int idx);

	static unsigned int GetRenderDeviceCount();
	static const char* GetRenderDeviceName(int idx);
	static GT_BOOL	IsRenderDevicePrimary(int idx);

	static unsigned int GetCaptureDeviceCount();
	static const char* GetCaptureDeviceName(int idx);
	static GT_BOOL	IsCaptureDevicePrimary(int idx);

	static const char* GetLicHWInfo(const char* sAppName, const char* sKey, int nChanNum, const char* sMAC); 
	static const char* GetLicFileName(const char* sAppName);
	static const char* ValidLicHWInfo(const char* sHWInfo);

	//for SIP NAT type and mapped public address
	int				GetDetectedNATType();

	const char*		GetMappedPublicSIPIPAddress();
	unsigned short	GetMappedPublicSIPIPPort();

	const char*		GetLocalNetworkIPAddress();

	HWND GetMainWnd(){return m_hMainWnd;}
	void SetMainWnd(HWND wnd){m_hMainWnd=wnd;}

	const char* GetAppName();
	void SetAppName(const char* s);

	const char* GetLicTo();

	void SetChanDir(int ch, int dir); //1 = inbound call only, 2 = outbound call only, 3 = both
	void SetChanAudioDir(int ch, int dir); //0 = no audio, 1 = send audio only, 2 = receive audio only, 3 = both (default)

	void SetChanConfMask(int ch, unsigned int bitMask);

	void SetChanDTMFType(int ch, unsigned int dtmfType); //dtmf method //0 = in audio //1 = sip info //2 = rtp //3 = auto
	unsigned int GetChanDTMFType(int ch);

	void SetChanSIPAndRTPAddr(int ch, const char* SIPAddrAndPort, const char* RTPAddrAndPort);

	void SetChanAudioCodec(int ch, int ac);
	int	GetChanAudioCodec(int ch);
	int GetChanLastMsgCode(int ch);
	const char* GetChanLastMsgText(int ch);

	const char* GetChanCallID(int ch);
	const char* GetChanCallFromTag(int ch);
	const char* GetChanCallToTag(int ch);

	GT_BOOL	GetChanCallCredit(int ch);

	const char* GetPAssertedIdentity(int ch);
	void SetPAssertedIdentity(int ch, const char* p);
	
	const char* GetPChargingVector(int ch);
	void SetPChargingVector(int ch, const char* p);	

	const char* GetRemotePartyID(int ch);
	void SetRemotePartyID(int ch, const char* p);
	
	const char* GetChanSIPMsg(int ch);

	const char* GetChanAudioRecordFileName(int ch);

	GT_BOOL ReserveChan(int ch, GT_BOOL bReserve);

	//user data
	bool SetChanUserData(int chan_id, int data_idx, unsigned long d);
	bool GetChanUserData(int chan_id, int data_idx, unsigned long* d);
	bool SetChanUserStr(int chan_id, int data_idx, const char* sVal);
	const char* GetChanUserStr(int chan_id, int data_idx);

	//Set Chan AGC
	void SetChanAudioLevel(int ch, float inLevel, float outLevel);

	//Set Chan Extra SIP Header for INVITE
	void SetChanCallExtraSIPHeader(int ch, const char* s);

	//peer node infomation
	const char* GetPeerSIPIPAddress(int ch);
	unsigned short GetPeerSIPIPPort(int ch);
	const char* GetPeerRTPIPAddress(int ch);
	unsigned short GetPeerRTPIPPort(int ch);
	const char*	GetPeerSIPContactAddress(int ch);

	GT_HANDLE		SIPAccount_Add(const char* dp_name, const char* username, const char *domain, const char* proxy,
			const char* authorization, const char *password, int expire, GT_BOOL bReg, int maxSimultaneousCalls, int retryInterval, bool bEnabled, int prot);
	void			SIPAccount_Remove(GT_HANDLE h);
	int				SIPAccount_Count();
	int				SIPAccount_Index(GT_HANDLE h);
	GT_HANDLE		SIPAccount_Handle(int idx);
	//type = 0 display name 1 = username 2 = domain  3 = proxy  4 = authorization 5 = password
	const char*		SIPAccount_Get(int idx, int type);
	void			SIPAccount_Set(int idx, int type, const char* v);
	void			SIPAccount_Enable(GT_HANDLE h, bool b);

	//void			SIPAccount_Register(GT_HANDLE h, bool b);
	void			SIPAccount_Register(int idx, bool b);


	//num = 0-9, '*' or '#', otherwise stop playing
	bool PlayNumTone(char num);
	bool PlayLocalRingSound();
	bool PlayRemoteRingSound();
	bool PlayBusySound();
	bool StopSound();

	unsigned int GetIdleChannelCount();
	unsigned int GetActiveChannelCount();

//new conference functions
	GT_HANDLE CreateConf();
	void	DestroyConf(GT_HANDLE h);
	GT_BOOL SetChanInConf(GT_HANDLE h, int ch, int bAdd);
	int		GetConfIndex(GT_HANDLE h);

//video
	void EnableChanVideo(int ch, GT_BOOL b);
	/*
SQCIF 128 × 96       =        1
QCIF 176 × 144       =        2
CIF = 352x288        =        3
4CIF 704 × 576       =        4
16CIF 1408 × 1152    =        5

QVGA = 320x240       =        10
VGA = 640x480        =        20
	*/
	void ShowCameraWnd(GT_BOOL bShow, int resolution = 2);

public:
	virtual void On_RecvConnected(int ch);
	virtual void On_RecvOffered(int ch, const char* sCaller, const char* sCallee, const char* sDestAddr, \
		const char* sViaAddr, const char* sFromIP, unsigned short nFromPort);
	virtual void On_RecvDialing(int ch, const char* sCaller, const char* sCallee);
	virtual void On_RecvIdle(int ch, int code, const char* desc);
	virtual void On_RecvRinging(int ch);

	virtual void On_VoiceActivityDetected(int ch, int voice_dir, int voice_on, int level, unsigned int reserved);
	void FireOn_VoiceActivityDetected(int ch, int voice_dir, int voice_on, int level, unsigned int reserved);

	virtual void On_DetectHumanVoiceDone(int ch, int result){}

	virtual void On_RecvNoAudio(int ch, int reserved){}
	void FireOn_RecvNoAudio(int ch, int reserved);

	//virtual void On_RecvRegStatus(int user_id, int status, int regtime);

public:
	void					StartTimer(int ch, unsigned long milli_secs);
	void					StopTimer(int ch);
	virtual void			OnTimer(int ch);

	//dir 0 = incoming, 1 = outgoing
	virtual void			On_SIPMsg(int dir, const char* src_ip, unsigned short src_port, \
		const char* dest_ip, unsigned short dest_port, char* buf, int len, int prot, void* reserved){}
	void					FireOn_SIPMsg(int dir, const char* src_ip, unsigned short src_port, \
		const char* dest_ip, unsigned short dest_port, char* buf, int len, int prot, void* reserved);

protected:
	virtual void					ProcessEvent(TGTEvent* pevent);

public:
	GTAPI_Channel						**m_pChans;

	void*								m_pMicCtrl;
	void*								m_pSpkCtrl;

private:
	HWND								m_hMainWnd;
	char								m_sAppName[80];
	char								m_sLicTo[200];

//For Human or Voice Detection
public:
	bool								m_bDetectHumanOrMachine;
	unsigned int						m_uDetectHumanTotalDuration;
	unsigned int						m_uDetectHumanVoiceOnDuration;

	unsigned int						m_uSentenceMaxInterval;
	unsigned int						m_uSentenceMinDuration;


//proxy interfaces:
public:
	//events:

	virtual void						On_ProxyUserRegistered(unsigned int pid, const char* username, time_t tnow, unsigned int exp_sec, const char* org_contact, const char* mapped_contact, const char* szUAName, int UANatType, const char* szFromID, const char* szToID, const char* saddr, unsigned short nport){}
	//void FireOn_ProxyUserRegistered(unsigned int pid, const char* username, time_t tnow, unsigned int exp_sec, const char* contact, const char* szUAName, int UANatType, const char* szFromID, const char* szToID, const char* saddr, unsigned short nport);

	virtual void						On_ProxyUserSubscribed(unsigned int pid, const char* fromid, const char* toid, const char* suri, const char* via, const char* callid, \
		const char* saddr, unsigned short nport){}

	virtual void						On_ProxyCallTransaction(unsigned int pid, unsigned int sid, const char *szFrom, const char* szTo, \
		const char* szUri, const char* szVia, const char* szRealContact, time_t t_start, time_t t_end, \
		int session_status, int result_code, const char* result_txt){}

	//"sip:undefined" = wait until ProxySetNewCallSessionAddr is called
	//"channel"  =  to channel
	//"unauthorized"   =  need credit to process
	//"sip:123@abc.com"   =  with right credit or don't need credit, processed by proxy site and transfered to this address
	//"|" can be used to seperate the credit info
	//For example: "To<sip:123@abc.com>|From<sip:456@abc.com>|User<1234>|Password<4567>"
	//otherwise = refer to user's contact info by using GetProxyUserContact.
	//2012-11-12 Added one more parameter for real username in Authorization
	virtual const char*					On_ProxyNewCallSession(unsigned int pid, unsigned int sid, GT_HANDLE msg, \
										const char* authid, \
										const char* fromid, const char* toid, const char* suri, \
										const char* via, const char* saddr, unsigned short nport, \
										int bCredit){return "channel";}

/*
	//functions:
	virtual int								GetProxyUserValid(unsigned int pid, const char* username){return 0;}
	virtual const char*						GetProxyUserPassword(unsigned int pid, const char* username){return "";}
	virtual time_t							GetProxyUserRegTime(unsigned int pid, const char* username){return 0;}
	virtual unsigned int					GetProxyUserRegExpire(unsigned int pid, const char* username){return 0;}
	virtual const char*						GetProxyUserContact(unsigned int pid, const char* username){return "";}
	virtual const char*						GetProxyUserUAName(unsigned int pid, const char* username){return "";}
	virtual int								GetProxyUserNATType(unsigned int pid, const char* username){return -1;}	
*/
	void							    ProxySetUserInfo(unsigned int pid, const char* username, const char* passwd, time_t regt, unsigned int regex, const char* org_contact, const char* mapped_contact, const char* uaname, int nattype, const char* src_ip, unsigned short src_port, const char* from_id, const char* to_id);
	void								ProxySetUserMsg(unsigned int pid, const char* username, bool bMsgWait, const char* sMsgAcct, int cnt1, int cnt2, int cnt3, int cnt4);
	void								ProxyDisableAllUsers(unsigned int pid);
	void								ProxySetUserAuthType(unsigned int pid, const char* username, int authType);
	void								ProxySetUserAttr(unsigned int pid, const char* username, int attr, const char* val);

	//direction can be set to “recipient”, "initiator"
	//state can be set to:
	//"confirmed" ===> connected
	//"early" ===> ringing
	//"terminated" or "void" ===> idle
	void								ProxyUpdateUserState(unsigned int pid, const char* username, const char* direction, const char* state);

	virtual void						On_ProxyCallSessionStatus(unsigned int pid, unsigned int sid, time_t sbegin, time_t send, \
		int status, const char* szFrom, const char* szTo, const char* szURI, const char* szVia, const char* szRealContact){}

	void								InitProxySites();
	void								FreeProxySites();

	GT_BOOL								ProxySetNewCallSessionAddr(unsigned int pid, unsigned int sid, const char* sAddr);
	GT_BOOL								ProxyConnectCallSessions(unsigned int pid1, unsigned int sid1, unsigned int dir1, unsigned int pid2, unsigned int sid2, unsigned int dir2);

	//Security Functions, type 0 = black list, 1 = white list. act == 1 add, 0 == remove
	GT_BOOL								SetIPFilter(const char* s, int type, int act);
	GT_INT								GetIPFilterCount(int type);
	const char*							GetIPFilterItem(int type, int idx);

};

#ifdef GTAPI_FACE_OP_ASYNC

//**********************************************************************************************************************
/////////////////////////////////////////////////////////////////////////////
/** Base class for GTAPI-Based asynchronous operations (i.e. play, record, etc..)
//
//	Example usage:
//
//	class MyOp : public CGTOpAsync {
//	public:
//		virtual void beginOp(DWORD dwOpId, ICallback* pCallback) {
//			// Kicks off the operation...
//		}
//
//		// Some state stimulus / incoming event methods to drive the 
//		// state machine of the async operation to eventual completion...
//
//		// Eventually, when the operation is complete, it will call:
//
//					fireDone();
//	
//		// which will call the callback providing the dwOpId and the 
//		// hardware result code.
//	};
//
//
//	class OperationUser : public CGTOpAsync::ICallback {
//	public:
//		void main() {
//			// initialization code... setting up event pumps, etc...
//			MyOp theOp;
//			// use the pointer to the operation for lack of better unique id
//			DWORD dwTheOpId = (void*)(&theOp);
//			
//			theOp.perform(dwTheOpId, &this);
//
//			// Event threads, etc... drive the operation.
//		}
//
//		/// The callback method
//		virtual void done(DWORD dwOpId, GT_STATUS hwStatus) {
//			// Hoooray... the operation is complete... check the end result
//			// and go from there...
//		}
//	};
//
*/
class GT_DLL_API CGTOpAsync: public CGTCfgInterface, public CGTLogInterface
{
public:
	enum ResultCode
	{
		OP_RESULT_UNDEFINED	= -1,
		OP_RESULT_SUCCESS,
		OP_RESULT_ABORTED,
		OP_RESULT_TIMEOUT,
		OP_RESULT_ERROR
	};

	/////////////////////////////////////////////////////////////////////////
	/** The callback interface that a user of the operation should implement
	//	to receive completion notification.
	*/
	struct ICallback
	{
		/////////////////////////////////////////////////////////////////////////////////
		/** Notification that the operation is complete, and the associated status*/
		virtual void done(CGTOpAsync* dwOpId, ResultCode result, GT_STATUS hwStatus) = 0;
	};

public:
	CGTOpAsync(CGTOpAsyncCompound* ac, CGTAPIEnv* env, GTAPI_Channel* chan);
	virtual ~CGTOpAsync();

	/////////////////////////////////////////////////////////////////////////
	/** Perform the asynchronous operation.
	*/
	void perform();

	/////////////////////////////////////////////////////////////////////////
	/** Child classes override this to provide their "kick-off" code.
	*/
	virtual void beginOp() = 0;

	/////////////////////////////////////////////////////////////////////////
	/** Child classes override this to provide the ability to abort the
	//	operation.
	*/
	virtual void abort() = 0;

	CGTOpAsyncCompound* getAsyncOpCompound(){return m_pOpAsyncCompound;}
	CGTAPIEnv*			getEnv(){return m_pEnv;}
	GTAPI_Channel*		getChannel(){return m_pChan;}
	ResultCode getResult() {return _result;}
	GT_STATUS getHwCode() {return _hwStatus;}

	/////////////////////////////////////////////////////////////////////////
	/** \return Whether or not the operation is done.
	*/
	bool isDone() {return _isDone;}

	/////////////////////////////////////////////////////////////////////////
	/** \return The number of times this operation has been performed.
	*/
	int getPerformCount() {return _iPerformCount;}

	/////////////////////////////////////////////////////////////////////////
	/** Sends the specified digits to the operation as if the keys were 
	//	actually pressed and reported via the API.  This helps to support
	//	type-ahead.
	*/
//	virtual void injectDtmf(const char* digits);

public:
	virtual void On_RecvConnected(int ch){}
	virtual void On_RecvOffered(int ch, const char* sCaller, const char* sCallee, const char* sDestAddr, \
		const char* sViaAddr, const char* sFromIP, unsigned short nFromPort){}
	virtual void On_RecvDialing(int ch, const char* sCaller, const char* sCallee){}
	virtual void On_RecvIdle(int ch, int code, const char* desc){}
	virtual void On_RecvRinging(int ch){}

	virtual void On_RecvHolding(int ch, int hold_on){}
	virtual void On_RecvTransfering(int ch, const char* sAddr, const char* sReplaceCallID, const char* sReplaceFromTag, const char* sReplaceToTag){}

	virtual void On_RecvRegStatus(int user_id, int status, int regtime){}

	virtual void On_RecvAudioPlayDone(int ch, int doneReason, const char* dtmfBuffer){}
	virtual void On_RecvAudioRecordDone(int ch, int doneReason, const char* dtmfBuffer){}
	virtual void On_RecvAudioStatus(int ch, int resType, int statusCode, unsigned long bytesDone){}

	virtual void On_RecvDTMFDone(int ch, int reason, const char* dtmfBuf){}
	virtual void On_RecvDTMFKeyDown(int ch, unsigned char keyValue, unsigned long ticks){}
	virtual void On_RecvDTMFKeyUp(int ch, unsigned char keyValue, unsigned long ticks){}

	virtual void On_RecvFaxDone(int ch){}
	virtual void On_RecvFaxStatus(int ch, int statusCode){}
	virtual void On_RecvStatus(int chBegin, int chEnd, int chStatus){}

	virtual void On_RecvError(int ch, int errCode){}

	virtual void OnTimer(int ch){}

protected:
	/////////////////////////////////////////////////////////////////////////
	/** Called by child classes to signal the operation is complete and 
	//	call back on the owner's callback.
	*/
	void fireDone();
	void fireDone(ResultCode result, GT_STATUS hwStatus);

	/////////////////////////////////////////////////////////////////////////
	/** \return The generic operation result code.
	*/
	void setResult(ResultCode result) {_result = result;}

	/////////////////////////////////////////////////////////////////////////
	/** Set the hardware status code for this operation.  This is writeable
	//	only when transitioning from GT_SUCCESS to non-GT_SUCCESS so that 
	//	the first operation to give a non success will be the remembered 
	//	result for the whole operation. (and not overwritten by subsequent 
	//	actions).
	//*/
	void setHwCode(GT_STATUS hwStatus) {if(GT_SUCCESS == _hwStatus) _hwStatus = hwStatus;}


protected:
	/// The end result of the operation.
	ResultCode		_result;

	/// The hardware status code
	GT_STATUS		_hwStatus;

	/// A running count of the number of times this operation has been
	/// "performed".  Whether it is valid to perform the same operation
	///	multiple times or not is up to the child class implementation.
	int				_iPerformCount;

	/// Flag to indicate if the operation is done or not.
	bool			_isDone;

	bool			_bAborting;


	CGTOpAsyncCompound* m_pOpAsyncCompound;
	CGTAPIEnv*			m_pEnv;
	GTAPI_Channel*		m_pChan;
};


/////////////////////////////////////////////////////////////////////////////
/** A base class for compound asynchronous operations... i.e. CGTOpAsyncs with
//	sub-operations.  This base class encapsulates some helper book-keeping
//	functionality to help keep track of and apply operations to sub-operations.
*/

class GT_DLL_API CGTOpAsyncCompound : public CGTOpAsync::ICallback, public CGTCfgInterface, public CGTLogInterface
{
public:
	CGTOpAsyncCompound(CGTAPIEnv* env, int ch);
	virtual ~CGTOpAsyncCompound();

	int getChanIndex(){return m_chIndex;}
	CGTAPIEnv* getEnv(){return m_pEnv;}

	virtual void start() = 0;

public:
	CGTOpAsync*			m_pOpAsync;

protected:
	CGTAPIEnv*			m_pEnv;
	int					m_chIndex;

/*
protected:
	/////////////////////////////////////////////////////////////////////////
	// Helper function that subclasses can use to abort a sub operation.
	void abortSubOp(CGTOpAsync* pOp);

	/////////////////////////////////////////////////////////////////////////
	//  Helper function to add the sub op to the list of all operations, but
	//	not do anything with it yet.
	void addSubOp(CGTOpAsync* pOp);

	/////////////////////////////////////////////////////////////////////////
	//  Helper function that "performs" the sub op, (and makes sure it's
	//	added to the set of all operations, and is in the "running ops"
	//	set as well).
	//
	//	NOTE:  The op's pointer itself becomes the dwOpId in this convention.
	void performSubOp(CGTOpAsync* pOp);

	/////////////////////////////////////////////////////////////////////////
	//  Removes (but does not "delete") the specified sub op from all the
	//	book-keeping sets.
	void removeSubOp(CGTOpAsync* pOp);

	/////////////////////////////////////////////////////////////////////////
	//  Calls "delete" on all sub-ops, and cleans out all sets.  This is 
	//	useful when "desctructing".
	void clearSubOps();

	/////////////////////////////////////////////////////////////////////////
	//  Helper function to abort all __currently running__ sub ops.
	void abortSubOps();

	/////////////////////////////////////////////////////////////////////////
	//  \return	true	- All registered ops are "done".
	//			false	- otherwise.
	bool areAllOpsDone();

private:
	/// The set of all operations (running or otherwise).
	CPtArray _allOps;

private:
	/////////////////////////////////////////////////////////////////////////
	// Inserts the specified operation into the specified list if it 
	//	is not already there... otherwise, leaves the existing element there.
	void insert(CGTOpAsync* pOp);

	/////////////////////////////////////////////////////////////////////////
	// Removes the specified operation from the specified list.
	void remove(CGTOpAsync* pOp);
*/

};

class GT_DLL_API CGTOpAsyncEnv : public CGTAPIEnv
{
public:
	CGTOpAsyncEnv():CGTAPIEnv(){}
	virtual ~CGTOpAsyncEnv(){}

public:
	virtual void On_RecvConnected(int ch);
	virtual void On_RecvOffered(int ch, const char* sCaller, const char* sCallee, const char* sDestAddr, \
		const char* sViaAddr, const char* sFromIP, unsigned short nFromPort);
	virtual void On_RecvDialing(int ch, const char* sCaller, const char* sCallee);
	virtual void On_RecvIdle(int ch, int code, const char* desc);
	virtual void On_RecvRinging(int ch);

	virtual void On_RecvHolding(int ch, int hold_on);
	virtual void On_RecvTransfering(int ch, const char* sAddr, const char* sReplaceCallID, const char* sReplaceFromTag, const char* sReplaceToTag);

	virtual void On_RecvRegStatus(int user_id, int status, int regtime);

	virtual void On_RecvAudioPlayDone(int ch, int doneReason, const char* dtmfBuffer);
	virtual void On_RecvAudioRecordDone(int ch, int doneReason, const char* dtmfBuffer);
	virtual void On_RecvAudioStatus(int ch, int resType, int statusCode, unsigned long bytesDone);

	virtual void On_RecvDTMFDone(int ch, int reason, const char* dtmfBuf);
	virtual void On_RecvDTMFKeyDown(int ch, unsigned char keyValue, unsigned long ticks);
	virtual void On_RecvDTMFKeyUp(int ch, unsigned char keyValue, unsigned long ticks);

	virtual void On_RecvFaxDone(int ch);
	virtual void On_RecvFaxStatus(int ch, int statusCode);
	virtual void On_RecvStatus(int chBegin, int chEnd, int chStatus);

	virtual void On_RecvError(int ch, int errCode);

	virtual void OnTimer(int ch);

};


class GT_DLL_API CGTOpCallTransfer : public CGTOpAsync 
{
public:
    CGTOpCallTransfer(CGTOpAsyncCompound* ac, CGTAPIEnv* env, GTAPI_Channel* chan, \
		GTAPI_Channel* chan1, const char* callee, const char* caller, int ringSeconds, int maxDuration);

	virtual void beginOp();
	virtual void abort();

	virtual void On_RecvConnected(int ch);
	virtual void On_RecvIdle(int ch, int code, const char* desc);
	virtual void On_RecvRinging(int ch);
	virtual void On_RecvError(int ch, int errCode);
	virtual void OnTimer(int ch);

public:
    char caller_num[256];
    char callee_num[256];
    GTAPI_Channel* trans_chan;
    int ring_seconds;
    bool trans_succeed;
	int max_duration;

	time_t	call_start_time;
	time_t	call_end_time;

};

#endif

#ifdef USE_GTAPI_NAMESPACE
}
#endif

#endif
