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

		MCSocket.h
		Copyright: (c) 2001 Eovia Corp. All rights reserved.

		Author:	Charles
		Date:	5/10/2004

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

#ifndef __MCSocket__
#define __MCSocket__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "MCBasicTypes.h"
#include "MCArray.h"
#include "MCPtrArray.h"
#include "MCSMPCountedObject.h"

#include "IMCSocket.h"

class TMCString;
class TMCDynamicString;


/// \addtogroup MCCore
/// \{


/// TMCSocket is a simple abstraction of the bsd sockets
///
class TMCSocket : public TMCSMPCountedObject, public IMCSocket
{
public:

	struct IPAddress
	{
		uint32	fIPAddress;
		uint32  fSubNetMask;
	};
public:
	/// should be called once before using any of the socket code
	///
	static void Initialize();

	// ****************************************************************************
	//								GetHostIPAddress
	// 
	/// Returns the IP address of the local machine on a given sub net. If no address
	/// matches the given subnet then the first ip address is returned.
	/// 
	/// \param ipAddress   The IP Address
	/// \param subNetID    The ID of the sub Net
	/// \param subNetMask  The mask of the sub Net
	/// 
	static void GetHostIPAddress(uint32& ipAddress,uint32 subNetID,uint32 subNetMask);

	// ****************************************************************************
	//								IPtoString
	// 
	/// Returns the string that corresponds to an IP address.
	/// 
	/// \param address  The IP address
	/// \param string   The string
	/// 
	static void IPtoString(uint32 address,TMCString& string);

	// ****************************************************************************
	//								StringtoIP
	// 
	/// Returns the IP address corresponding to a string
	/// 
	/// \param address  The IP address
	/// \param string   The string
	/// 
	static void StringtoIP(const TMCString& string,uint32& address);

	// ****************************************************************************
	//								GetDefaultSubNet
	// 
	/// Returns the default the subnet info (the first adapter found on the system)
	/// 
	/// \param subNetID    The ID of the sub Net
	/// \param subNetMask  The mask of the sub Net
	/// 
	static void GetDefaultSubNet(uint32& subNetID,uint32& subNetMask);


	// ****************************************************************************
	//								GetHostName
	// 
	/// Returns a string that contains the name of the local machine
	/// 
	/// \param name  The name of the local machine
	/// 
	static void GetHostName(TMCString& name);


	static int32 CheckForRead(const TMCCountedPtrArray<IMCSocket>& socketArray,real timeOutInSeconds);

	static void Create(IMCSocket** socket);
protected:
	TMCSocket();
	~TMCSocket();
public:
	virtual MCErr	MCCOMAPI QueryInterface	(const MCIID& riid, void** ppvObj)		{ return TMCSMPCountedObject::QueryInterface(riid,ppvObj); }
	virtual uint32	MCCOMAPI AddRef			()										{ return TMCSMPCountedObject::AddRef(); }
	virtual uint32	MCCOMAPI Release		()										{ return TMCSMPCountedObject::Release(); }

	// IMCSocket methods

	virtual void MCCOMAPI Init(EProtocol protocol,int32 portNumber);
	virtual void MCCOMAPI SendBroadcast(uint32 broadcastAddress,const TMCString& message);
	virtual void MCCOMAPI BindToPort();
	virtual boolean MCCOMAPI WaitForReadableData(float timeOutInSeconds);
	virtual void MCCOMAPI ListenForConnections();
	virtual bool MCCOMAPI Accept(IMCSocket* outSocket,float timeOutInSeconds);
	virtual bool MCCOMAPI Connect(const char* serverAddress,float timeOut);
	virtual int32 MCCOMAPI GetData(char* buffer,int32 bufferSize);
	virtual int32 MCCOMAPI PutData(const char* buffer,int32 bytesCount);
	virtual boolean MCCOMAPI IsClosed();
	virtual void MCCOMAPI Close();

protected:
	static boolean sInitialized;

	int32			fPortNumber;
	uintpointer		fSocketID;
	EProtocol		fProtocol;
};

/// Simple class to send or get strings on a socket.
///
class TMCMessageStream
{
	enum
	{
		kBufferSize = 256
	};
public:
	/// create a stream on a connected socket
	///
	TMCMessageStream(TMCSocket& socket);

	/// sends 0 terminated message
	///
	void Send(const TMCString& message);

	/// reads 0 terminated message
	///
	void Receive(TMCDynamicString& message);
protected:
	TMCSocket&			fSocket;
	TMCArray<int8>		fBuffer;

	int32					fBufferCount;			///< number of characters read in the buffer
	int32					fCurrentPosition;		///< position in the buffer
};

/// \}

#endif
