#pragma warning (disable:4949)
#include "NetBridge_OLDENGINE.h"
//#include <crtdbg.h>
#pragma unmanaged


//-----------------------------------------------------------------
CNetBridge_OLDENGINE::CNetBridge_OLDENGINE(void)
{
	m_pFun					= NULL;
	m_pObjnet				= NULL;    
	m_dwPacketCollectIndex	= 0;
}
//-----------------------------------------------------------------
CNetBridge_OLDENGINE::~CNetBridge_OLDENGINE(void)
{
	DestroyObjNet( m_pObjnet );
}
//-----------------------------------------------------------------
int	CNetBridge_OLDENGINE::Init ()
{
	m_pObjnet = CreateObjNet();
	return true;
}
//-----------------------------------------------------------------
int	CNetBridge_OLDENGINE::Host ( DWORD dwIP , WORD wPort, CEventObj* pEventObj, BOOL bCompress, BOOL bEncryption )
{
	// 有 MainThread 呼叫

	if( pEventObj == NULL )
		return -1;

	sockaddr_in		addr;

	addr.sin_family			= AF_INET;
	
	addr.sin_port 			= htons( wPort );

	if( dwIP == 0 )
		addr.sin_addr.s_addr = INADDR_ANY;
	else
		addr.sin_addr.s_addr = dwIP;
	
	CObjEvent* pObjEvent	= new CObjEvent( this, pEventObj );

	return (int)m_pObjnet->Host( &addr, pObjEvent );
}
//-----------------------------------------------------------------
int CNetBridge_OLDENGINE::Connect ( DWORD dwIP, WORD wPort, CEventObj* pEventObj ) 
{
	if( pEventObj == NULL )
		return -1;

	sockaddr_in		addr;

	addr.sin_family			= AF_INET;
	addr.sin_addr.s_addr	= dwIP;
	addr.sin_port 			= htons( wPort );

	CObjEvent* pObjEvent	= new CObjEvent( this, pEventObj );

	return m_pObjnet->Connect( &addr, pObjEvent );
}

//-----------------------------------------------------------------

void CNetBridge_OLDENGINE::_Send( DWORD dwNetID, DWORD dwSize, PVOID pData, DWORD dwPriority, DWORD dwFlag )
{	
	if( dwSize < 32768 )
	{
		m_pObjnet->Send( dwNetID, (int)dwSize, pData, 0 );
	}
	else
	{
		BYTE* ptr = (BYTE*)pData;
		DWORD dwTotal = ( dwSize / 32000 ) + 1;
		DWORD dwCount = 0;
		// 拆封包
		Struct_PacketCollect Packet;

		Packet.dwID			= 0x12341234;
		Packet.dwCollectID	= m_dwPacketCollectIndex;
		Packet.dwTotalSize	= dwSize;
		Packet.dwTotal		= dwTotal;

		m_dwPacketCollectIndex++;

		DWORD dwRemain = dwSize;

		while( dwCount < dwTotal )
		{
			Packet.dwIndex	= dwCount;
			dwCount++;

			if( dwRemain >= 32000 )
			{
				memcpy( Packet.Buffer, ptr, 32000 );
				Packet.dwBufferSize = 32000;
				dwRemain -= 32000;
				ptr += 32000;
			}
			else
			{
				memcpy( Packet.Buffer, ptr, dwRemain );
				Packet.dwBufferSize = dwRemain;
			}



			_Send( dwNetID, sizeof( Struct_PacketCollect ), &Packet );
		}
	}
}


//-----------------------------------------------------------------
void CNetBridge_OLDENGINE::SendToAll ( DWORD dwSize, PVOID pPacket, DWORD dwPriority )
{
	m_pObjnet->SendToAll( (int)dwSize, pPacket );
}
//-----------------------------------------------------------------
void CNetBridge_OLDENGINE::Flush ()
{
	timeval t1 = {0,0};
	m_pObjnet->Flush( &t1 );
}
//-----------------------------------------------------------------
DWORD CNetBridge_OLDENGINE::Wait ( DWORD dwTime )
{
	SleepEx( 10, true );
	return WAIT_OBJECT_0;
}
//-----------------------------------------------------------------
INetEventListener* LSAPI	CObjEvent::OnNewConnection	( LNETID NetID ) 
{
	CEventObj* pEventObj = m_pEventObj->OnAccept( NetID );
	if( pEventObj == m_pEventObj )
	{
		return this;
	}
	else
	{
		CObjEvent* pObjEvent = new CObjEvent( m_pEngine, pEventObj );
		return pObjEvent;
	}
}
//-----------------------------------------------------------------
void LSAPI CObjEvent::OnConnected     ( LNETID NetID )
{
	m_pEventObj->OnConnect( NetID );
}
//-----------------------------------------------------------------
void LSAPI CObjEvent::OnDisconnected  ( LNETID NetID )
{
	m_pEventObj->OnDisconnect( NetID );
	m_pEngine->m_vecDelEvent.push_back( this );	
}
//-----------------------------------------------------------------
bool LSAPI CObjEvent::OnPacket        ( LNETID NetID, HBUFFER hIncomingData )
{
	int		Size;
	void	*pData;

	//取得封包資料
	ObjNetGetBuffer(hIncomingData,Size,pData);

#ifdef DF_PACKET_LOG
	Struct_PacketLog* pLog = (Struct_PacketLog*)pData;
	if( pLog->dwID == 0x12345678 )
	{
		// 收到要求, 發送回去
		pLog->dwID = 0x87654321;
		m_pEngine->_Send( NetID, sizeof( Struct_PacketLog ), pLog );

		char szOut[255];

		DWORD dwTime	= GetTickCount();
		DWORD dwSpend	= dwTime - pLog->dwTime;

		sprintf( szOut, "\nNB: RECV ECHO REQUEST ( %d ), spend( %d )ms", pLog->dwPacketID, dwSpend );

		if( m_pEngine->m_pFun )
			m_pEngine->m_pFun( szOut );
		return true;
	}
	else
		if( pLog->dwID == 0x87654321 )
		{
			// Echo Packet
			DWORD dwTime	= GetTickCount();
			DWORD dwSpend	= dwTime - pLog->dwTime;

			char szOut[255];

			m_pEngine->m_dwPacketLog--;
			sprintf( szOut, "\nNB: RECV ECHO ANSWER ( %d ), spend( %d )ms", pLog->dwPacketID, dwSpend );
			if( m_pEngine->m_pFun )
				m_pEngine->m_pFun( szOut );

			return true;

		}
#endif

		DWORD dwID = *((DWORD*)pData);
		
		if( dwID == 0x12341234 )
		{
			// 集合封包

			Struct_PacketAllCollect Collect;	
			Struct_PacketCollect* pPacket = (Struct_PacketCollect*)pData;

			map< DWORD, Struct_PacketAllCollect >::iterator it = m_pEngine->m_mapCollect.find( pPacket->dwCollectID );
			
			if( it == m_pEngine->m_mapCollect.end() )
			{
				// First One 
				
				Collect.dwSize	= pPacket->dwTotalSize;
				Collect.pBuff	= new BYTE[ pPacket->dwTotalSize ];
				Collect.dwCount = 0;

				m_pEngine->m_mapCollect[ pPacket->dwCollectID ] = Collect;
			}
			else
			{
				Collect = it->second;
			}



			Collect.dwCount++;
			BYTE* ptr = Collect.pBuff;

			ptr = ptr + ( 32000 * pPacket->dwIndex );
			memcpy( ptr, pPacket->Buffer, pPacket->dwBufferSize );

			m_pEngine->m_mapCollect[ pPacket->dwCollectID ] = Collect;

			// 檢查是否完畢
			if( Collect.dwCount == pPacket->dwTotal )
			{
				m_pEventObj->OnRecv( NetID, Collect.dwSize, Collect.pBuff );
				
				delete [] Collect.pBuff;				
				m_pEngine->m_mapCollect.erase( it );
			}

		}
		else
		{
			m_pEventObj->OnRecv( NetID, (Size-1), pData );
		}


	return true;
}
//-----------------------------------------------------------------
void LSAPI CObjEvent::OnConnectFailed ( int NetID )
{
	m_pEventObj->OnConnectFailed( NetID );
}
//-----------------------------------------------------------------
void CNetBridge_OLDENGINE::Close				( DWORD dwNetID )
{
	m_pObjnet->Close( dwNetID );
}
//-----------------------------------------------------------------
void CNetBridge_OLDENGINE::GetConnectInfo		( DWORD dwNetID, DWORD* pdwIP, WORD* pwPort )
{
	sockaddr_in Addr;
	m_pObjnet->GetPeerAddress( dwNetID, &Addr );

	if( pdwIP != NULL )
	{
		*pdwIP = Addr.sin_addr.s_addr;
	}

	if( *pwPort != NULL )
	{
		*pwPort = ntohs( Addr.sin_port );
	}
}
//-----------------------------------------------------------------
void CNetBridge_OLDENGINE::GetStatusInfo		( char* pszOut )
{ 
	char szOut[255];
#ifdef DF_PACKET_LOG
	sprintf( szOut, "WaitEcho( %d )p", m_dwPacketLog );
#else
	sprintf( szOut, "----No Comment----" );
#endif

	strcpy( pszOut, szOut );
}

#pragma managed