#pragma	once

#include <winsock2.h>
#include <mstcpip.h>
#include <mswsock.h>
#include <Windows.h>


#include <map>
#include <vector>
#include <queue>

#include "NetBridge_Define.h"
#include "NetBridge_EventObj.h"

using namespace std;

class CNetBridge_Base;
class CNetSocket;
class CEventMsg;
//class CBuffer;
//class CCritcalsection;






class CCritcalsection
{
private:
	CRITICAL_SECTION	m_cs;
public:
	CCritcalsection()	{	InitializeCriticalSection( &m_cs ); }
	~CCritcalsection()	{	DeleteCriticalSection( &m_cs );		}
	void	Enter()		{	EnterCriticalSection( &m_cs );		}
	void	Leave()		{	LeaveCriticalSection( &m_cs );		}
};

/*
class CPacket
{
public:

DWORD	m_dwPacketSize;
BYTE*	m_pPacket;
};
*/


class CBuffer
{
public:
	CBuffer( DWORD dwSize );
	~CBuffer();

	DWORD				GetRemain() { return ( m_dwTotalSize - m_dwSize ); }

	//DWORD				m_dwMode;
	WSAOVERLAPPED		m_overlapped;
	EM_BUFFER_MODE		m_emMode;
	CNetSocket*			m_pNetSocket;
	DWORD				m_dwFlag;

	bool				m_IsCompress;
	bool				m_IsCollect;

	BYTE*				m_pData;



	DWORD				m_dwSize;			// 主要資料大小
	DWORD				m_dwSystemSize;		// 系統在主要資料後面所占用的空間
	DWORD				m_dwTotalSize;		// Buffer 實際上所暫用計憶體

	DWORD				m_dwPriority;
	DWORD				m_dwNextPriority;

	//CBuffer*			m_pLastBuffer;
	//CBuffer*			m_pNextBuffer;
};

class CNetSocket
{
public:
	CNetSocket()
	{

		//m_dwTimeToClose				= 0;
		m_dwSendBuf					= 0;
		m_dwNetID					= 0;
		m_pBuffer					= NULL;
		m_pBufferIncomplete			= NULL;
		m_emStatus					= EM_SOCKET_UNCONNECT;
		m_pvecMsg					= NULL;
		m_pEvent					= NULL;

		m_dwIP						= 0;
		m_wPort						= 0;
		m_dwTimer					= 0;

		m_MsgRecvCount				= 0;


		m_IsCompress				= false;
		m_IsEncryption				= false;

		m_AuthorizeIndex			= 0;

		//m_dwBytesBufferNeedProcess	= 0;
		ZeroMemory( &m_overlapped_Recv ,	sizeof( WSAOVERLAPPED )		);
		ZeroMemory( &m_overlapped_Send ,	sizeof( WSAOVERLAPPED )		);
		ZeroMemory( m_arrayTemp,			sizeof( m_arrayTemp )		);

	}
	WSAOVERLAPPED				m_overlapped_Send;		// as named

	// General
	//--------------------------------------------------------
	DWORD						m_dwNetID;
	SOCKET						m_tcp_socket;

	DWORD						m_dwIP;
	WORD						m_wPort;

	EM_SOCKET_STAUTS			m_emStatus;

	DWORD						m_dwTimer;

	EM_AUTHORIZE_STAUTS			m_emAuthorize;
	CEventObj*					m_pEvent;
	vector< CEventMsg* >*		m_pvecMsg;					// 指向目前 Socket 裝態對應的 queue;
	//DWORD						m_dwTimeToClose;

	CNetBridge_Base*			m_pNetBridge;				// 指向所屬的底層用

	//CCritcalsection				m_cs_queueSend;
	CCritcalsection				m_cs_SocketIO;				// 用在 Socket IO 動作時作執行緒安全	

	//--------------------------------------------------------
	//queue< CBuffer* >			m_queueAccept;				// 放置接收中的 Buffer 資料, 用來記錄順序
	vector< CBuffer* >			m_vecAccept;

	//--------------------------------------------------------
	//queue< CBuffer* >			m_queueRecv;				// 放置接收中的 Buffer 資料, 用來記錄順序
	vector< CBuffer* >			m_vecRecv;
	DWORD						m_MsgRecvCount;				// 還有多少訊息還未被處理




	CBuffer*					m_pBufferIncomplete;		// 放置處理仍無法判斷封包大小的不完整的資料
	CBuffer*					m_pBuffer;					// 放置處理中的不完整的資料

	// For Send
	//--------------------------------------------------------
	//queue< CBuffer* >			m_queueSend;				// 送出中的封包
	vector< CBuffer* >			m_vecWaitToSend;			// 等待打包及壓縮的封包
	//vector< CBuffer* >			m_vecSend;				// 已送出的封包,等待 IOCP 完工
	DWORD						m_dwSendBuf;				// 目前計憶體中有多少 Buffer 在傳送中
	CBuffer*					m_arrayTemp[ DF_NB_OVERLAPPEDCOUNTER ]; // 沒照 Buffer 順序取得時, 會先暫放這裡

	//queue< CPacket* >			m_queueSend;
	//queue< CBuffer* >			m_queueBuffer;
	
	// Compress
	//--------------------------------------------------------
	BOOL						m_IsCompress;
	
	// Encryption
	//--------------------------------------------------------
	BOOL						m_IsEncryption;
	BYTE						m_AuthorizeIndex;

	// IOCP
	//--------------------------------------------------------
	LPFN_ACCEPTEX				m_pfnAcceptEx;				// 指向 
	LPFN_GETACCEPTEXSOCKADDRS	m_pfnGetAcceptExSockaddrs;

	// OVERLAPPED
	//--------------------------------------------------------
	HANDLE						m_thread_Accept;	// 若 Socket 為 listen 狀態, 便會有一 Thread 為其等待 Accept
	HANDLE						m_thread_Recv;
	HANDLE						m_thread_Send;
	HANDLE						m_event_PreSend;

	WSAOVERLAPPED				m_overlapped_Recv;		// as named
	//	WSAOVERLAPPED				m_overlapped_Send;		// as named


	// For Accept Socket
	//--------------------------------------------------------


	//WSAEVENT	m_event;
};


class CEventMsg
{
public:
	CEventMsg()	{ emMsg = MSG_NULL; dwEventID = 0; pSocket = NULL; }

	//DWORD			m_dwMsgID;
	EM_MSG_TYPE		emMsg;
	//DWORD			m_dwNetID;			// 事件持有人

	DWORD			dwEventID;		// 通用的事件代號

	CNetSocket*		pSocket;



	union
	{
		struct 
		{
			//DWORD	dwNetID;
			CNetSocket*		pAcceptSocket;
		} MsgAccept;

		struct 
		{
			CBuffer* pBuffer;			// 這裡的這指標, 一但用用完便會被釋放
		} MsgRecv;

		struct 
		{
			DWORD	dwErrorID;
		} MsgError;

		struct 
		{
			DWORD	dwFailID;
		} MsgConnectFailed;

		struct  
		{
			BYTE	AuthorizeIndex;
			BOOL	IsCompress;
			BOOL	IsEncryption;
		} MsgAuthorize;
	};
};

struct Struct_PacketAuthorize
{
	BYTE AuthorizeIndex;
	BOOL IsEncryption;
	BOOL IsCompress;
};

struct Struct_PacketReplyAuthorize
{
	BYTE LastAuthorizeIndex;
};

/*
bool	CompareDeleteTime( const CNetSocket*& pScoket1 , const CNetSocket*& pScoket2 )
{
	return true;
}
*/


/*
struct CompareCloseTime : public binary_function <CNetSocket*, CNetSocket*, bool> 
{
	bool operator()(const CNetSocket*& _Left, 	const CNetSocket*& _Right ) const
	{
		if( _Left->m_dwTimeToClose < _Right->m_dwTimeToClose )
			return true;
		else
			return false;
	}
};
*/