/******************************************************************************/
/*!
    EasyTCP
    Copyright 2005 Electronic Arts Inc.

    \file
    \ingroup    Network
    \brief      Easy-to-use (simple) interface to a DirtySock TCP connection
*/
/******************************************************************************/

/*** Include guard ************************************************************/

#ifndef EASYTCP_CONNECTION_H
#define EASYTCP_CONNECTION_H

/*** Includes *****************************************************************/
#include <GameTalk/GameTalkBase.h>
#include <GameTalk/Utility.h>
#include <GameTalk/IGameTalkProtocol.h>

#include <stdio.h>
#include <assert.h>
/*** Macros *******************************************************************/
#ifndef USER_GAMETALK_CREATE_BINARY_GUID
	#define USER_GAMETALK_CREATE_BINARY_GUID(a,b,c,d) (((int)(a)<<24)|((int)(b)<<16)|((int)(c)<<8)|(int)(d))
#endif

/*** Interface ****************************************************************/

// --- Constants

// --- Forward declarations

struct SocketT;

/*** Implementation ***********************************************************/

namespace EasyTCP
{
class Connection
{
    public:
        explicit Connection(bool listener=false);
        ~Connection();

        void SetTimeout_InMilliseconds(uint16_t timeOut_InMilliseconds);    // defaults to 5 seconds

        struct EventCallback;
        void SetDisconnectedCallback(EventCallback newCallback);

		bool Connect(const char *hostname, uint16_t tcpPort);   // synchronous
		bool IsConnected() const;
		bool Listen();   // synchronous
        void IdlePulse();
		// Not certain - but we may want to check mConnectionError flag in this or SendWholeMsg(...)
        bool Send(const uint8_t *bytes, uint32_t numToSend);
        void Disconnect();
		int PollSocket();
		void SetParser(EA::GameTalk::Utility::Parser * parser) { mParser = parser; }
		bool ConnectionError();
		bool InitListenerSocket(uint16_t tcpPort);

		USE_GAMETALK_ALLOC("EA::EasyTCP::Connection")
    protected:
		void AcceptConnection();
        bool LookupIPAddress(const char *hostname, uint32_t *ipAddress);
        bool ConnectToServer(const uint32_t ipAddress, uint16_t tcpPort);

		// Not certain - but we may want to check mConnectionError flag in this or Send(...)
        bool SendWholeMsg(const uint8_t *bytes, int numToSend);

        SocketT					*mSocket;
        SocketT					*mListenerSocket;

		// idle timeout, in milliseconds - Only used when looking up an IP Address
		int mTimeout;

		// There are only two ways mConnectionError can be set to true:
		// 1. If there was an error sending data or
		// 2. if we receive less than 0 bytes of data off the wire - i.e. if SocketRecv function returns a negative number
		bool mConnectionError;

		EA::GameTalk::Utility::Parser * mParser;

		// The mReceiveBuffer is used to receive data "from the wire"
		char mReceiveBuffer[GAMETALK_RECEIVE_BUFFER_SIZE];
		// The mReceiveBufferIndex is used in case a user Poll's from within their callback (recurses on PollSocket)
		int mReceiveBufferIndex;

		bool mListener;
};

}   // namespace EasyTCP

/******************************************************************************/

#endif  //  EASYTCP_CONNECTION_H

