/*
    Copyright 2004-2005 Electronic Arts Inc.
*/

// --- Include guard
#ifndef EA_GAMETALK_ICONNECTION_H
#define EA_GAMETALK_ICONNECTION_H

#include "GameTalk/IMessage.h"

namespace EA
{
    namespace GameTalk
    {
        class IConnection;
		class ITimer;


        class ITimer
        {
        public:
            ITimer() { }
            virtual ~ITimer() { }

            virtual bool HasExpired() = 0;
        };

        // MessageHandler is a callback function for receiving messages from connection
        //  connection   - to the connection that received the message
        //  sender       - the name of the target that sent the message
        //  channel      - the channel name associated with the message
        //  message      - the received message
        //  replyMessage - non-null if this is a sync message, this message will be used to contain the sync-reply
        //  userData     - user data provided when handler was registered
        typedef void (*MessageHandler)(IConnection *connection, const char *sender, const char *channel, const IMessage *message, IMessage *replyMessage, void *& userData);

        // base interface for message transport
        class IConnection
        {
        public:
            /// returns true if we are connected to the message router
            virtual bool            IsConnected() const = 0;

            /// returns the local target name
            virtual const char *    TargetName() = 0;

            /// create a new message
            //      \return         - a new IMessage which must be released with a call to IMessage::Release()
            virtual IMessage *      CreateMessage() = 0;

            // create a new message using the tempBuffer as optional storage. 
            // this function can be used to reduce the number of memory allocations required for holding message data.
            // for example, stack space could be used. it is up to the user to ensure that tempBuffer remains 
            // valid for the lifetime of the IMessage.
            // if the storage requirements of the message end up exceeding the tempBuffer size then
            // underlying memory allocations will occur.
            //
            //     tempBuffer     - pointer to temporary buffer to use
            //     tempBufferSize - size of temporary buffer
            virtual IMessage *      CreateMessage(uint8_t *tempBuffer, size_t tempBufferSize) = 0;

            // send a message to a target on a specified channel
            // returns true if the send was successful, this does not mean that the target actually 
            // received the message though. the target could not exist or may not be listening on the specified channel.
            //    target      - target to send message to
            //    channel     - channel name to send message on
            //    message     - message to send
            virtual bool            Send(const char* target, const char *channel, const IMessage * message) = 0;

			// send a synchronous message to a target on the specified channel
            // returns true if a reply was received from the remote target, false if error occurred
            // this method will block until a reply-message or an error is received.
            // the ITimer class specifies an optional timer to be used to handle timeouts, if NULL this function will block forever
            // This can only be called by one thread at a time (like all parts of IConnection)
            //    target      - target to send message to
            //    channel     - channel name to send message on
            //    message     - message to send
            //    reply       - reference to message to hold sync-reply 
            //                  if a message is supplied this function will clear it and use it as storage for the reply
            //                  if this is NULL the this function will create a message to hold message data
            //    timer       - optional timer class that will be polled when waiting for sync-reply
            virtual bool            SendSynchronous(const char * target, const char *channel, const IMessage * message, IMessage *reply, ITimer* timer) = 0;

            // Poll the network for messages
            // returns the number of messages received and dispatched
            //    blocking    - if true, this function will not return until a message has actually been received
            //                  if false, this function will return immediately if no messages are available
            virtual int             Poll(bool blocking=false) = 0;

            /// Register a message handler 
            ///   channelFilter - describes a pattern for matching received message channels against (todo: document filter pattern)
            ///   userData      - void * that can be used to store user context
            virtual bool            RegisterMessageHandler(MessageHandler handlerFunc, const char* channelFilter, void * userData) = 0;

            /// Unregister a message handler (by function/filter)
			virtual void            UnregisterMessageHandler(MessageHandler handlerFunc, const char * channelFilter) = 0;

		protected:
			IConnection(){}
            virtual ~IConnection() {}

        private:
            IConnection(const IConnection& other);              //disabled copy ctor
            IConnection& operator=(const IConnection& other);   //disabled assignment operator
        };


        // factory for connections
        class IConnectionProvider
        {
        public:
            // creates a new connection with the provided target name
            virtual IConnection *       CreateConnection(const char *targetName);

            // this function returns a connection associated with the current thread
            // this may return NULL if none is associated
            virtual IConnection *       GetThreadConnection() = 0;

        protected:
            IConnectionProvider(){}
            virtual ~IConnectionProvider() {}

        private:
            IConnectionProvider(const IConnectionProvider& other);              //disabled copy ctor
            IConnectionProvider& operator=(const IConnectionProvider& other);   //disabled assignment operator
        };

    } // namespace GameTalk
} // namespace EA


#endif // #ifndef EA_GAMETALK_ICONNECTION_H
