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

// --- Include guard
#ifndef EA_GAMETALK_IMESSAGE_H
#define EA_GAMETALK_IMESSAGE_H


namespace EA
{
    namespace GameTalk
    {
        class IConnection;

 		// 2 is serialized format because it combines string and GameTalkMessage (binary 01) whereas 3 is binary 11 - which means binary and GameTalkMessage
		enum FormatTypes
		{
			StringFormat=0,
			BinaryFormat=1,
			SerializedFormat=2,
			GameTalkMessageFormat=3,
			Char = 4,
			Int8 = 5,
			UInt8 = 6,
			Int16 = 7,
			UInt16 = 8,
			Int32 = 9,
			UInt32 = 10,
			Int64 = 11,
			UInt64 = 12,
			Float = 13,
			Double = 14,
			Decimal = 15,
		};

		typedef FormatTypes FormatType;

        class IMessage
        {
        public:
            // reference counting, the message is destroyed when it's internal count reaches 0 
            virtual int         AddRef() = 0;
            virtual int         Release() = 0;

            // returns the connection associated with this message
            virtual IConnection* GetConnection() const = 0;

            // returns number of keys present in message
            virtual int         GetNumberOfKeys() const = 0;

            // compares the key name to specified string, returns true if they match (todo: is this case sensitive or not?)
            virtual bool        CompareKey(int keyIndex, const char* compareTo) const = 0;

            // returns index of key with specified name, returns <0 if key not found (todo: is this case sensitive or not?)
            // It is possible to have multiple keys with the same name - thus the first key that matches will be returned
            virtual int         GetIndexOfKey(const char* key) const = 0;

            // returns name of key by key index
            virtual const char* GetKey(int keyIndex) const = 0;

            // returns pointer to raw value data, this data has not been de-serialized and is endian specific
            virtual const void* GetContent(int keyIndex) const = 0;

            // returns total size of value data in bytes
            virtual size_t      GetSize(int keyIndex) const = 0;

            // returns format of value data
            virtual int  GetFormat(int keyIndex) const = 0;

            // returns true if value is an array, false if scalar
            virtual bool        IsArray(int keyIndex) const = 0;

            // returns length of array
            virtual size_t      GetArrayLength(int keyIndex) const = 0;

            // clears all message contents, removes all keys
            virtual void        Clear() = 0;

            // was there any error when deserializing the message?
            virtual bool        HasError() const = 0;

            // clear any error conditions
            virtual void        ClearError() const = 0;

            // Add a scalar of <type> to the Message
            virtual void Add(const char* key, const char *string) = 0;
            virtual void Add(const char* key, const IMessage * message) = 0;
            virtual void Add(const char* key, bool value) = 0;
            virtual void Add(const char* key, float value) = 0;
            virtual void Add(const char* key, double value) = 0;
            virtual void Add(const char* key, int8_t value) = 0;
            virtual void Add(const char* key, uint8_t value) = 0;
            virtual void Add(const char* key, int16_t value) = 0;
            virtual void Add(const char* key, uint16_t value) = 0;
            virtual void Add(const char* key, int32_t value) = 0;
            virtual void Add(const char* key, uint32_t value) = 0;
            virtual void Add(const char* key, int64_t value) = 0;
            virtual void Add(const char* key, uint64_t value) = 0;

            // Add an array of <type> to the Message
            virtual void AddArray(const char* key, const float* valueArray, const int count) = 0;
            virtual void AddArray(const char* key, const double* valueArray, const int count) = 0;
            virtual void AddArray(const char* key, const int8_t* valueArray, const int count) = 0;
            virtual void AddArray(const char* key, const uint8_t* valueArray, const int count) = 0;
            virtual void AddArray(const char* key, const int16_t* valueArray, const int count) = 0;
            virtual void AddArray(const char* key, const uint16_t* valueArray, const int count) = 0;
            virtual void AddArray(const char* key, const int32_t* valueArray, const int count) = 0;
            virtual void AddArray(const char* key, const uint32_t* valueArray, const int count) = 0;
            virtual void AddArray(const char* key, const int64_t* valueArray, const int count) = 0;
            virtual void AddArray(const char* key, const uint64_t* valueArray, const int count) = 0;

            virtual const char *GetString(int keyIndex) const = 0;
            virtual const char *GetString(const char *key) const = 0;

            // accessors for scalar data by key index
            // returns true if succeeded, false if type-mismatch or invalid keyIndex
            virtual bool Get(int keyIndex, const char *&string) const = 0;
			// We'll hopefully find a way to simplify this interface to only take an index and an IMessage pointer reference
            virtual bool Get(int keyIndex, IMessage* message, char* userBuffer, size_t userBufferSize) const = 0;
            virtual bool Get(int keyIndex, bool &value) const = 0;
            virtual bool Get(int keyIndex, float &value) const = 0;
            virtual bool Get(int keyIndex, double &value) const = 0;
            virtual bool Get(int keyIndex, int8_t &value) const = 0;
            virtual bool Get(int keyIndex, uint8_t &value) const = 0;
            virtual bool Get(int keyIndex, int16_t &value) const = 0;
            virtual bool Get(int keyIndex, uint16_t &value) const = 0;
            virtual bool Get(int keyIndex, int32_t &value) const = 0;
            virtual bool Get(int keyIndex, uint32_t &value) const = 0;
            virtual bool Get(int keyIndex, int64_t &value) const = 0;
            virtual bool Get(int keyIndex, uint64_t &value) const = 0;

            // accessors for array data by key index
            // returns true if succeeded, false if type-mismatch, array index out of bounds, or invalid keyIndex
            // startIndex is the offset to read from the data in the payload of the message and count is the number of elements to read
            virtual bool GetArray(int keyIndex, float* outputArray, int startIndex, int count) const = 0;
            virtual bool GetArray(int keyIndex, double* outputArray, int startIndex, int count) const = 0;
            virtual bool GetArray(int keyIndex, int8_t* outputArray, int startIndex, int count) const = 0;
            virtual bool GetArray(int keyIndex, uint8_t* outputArray, int startIndex, int count) const = 0;
            virtual bool GetArray(int keyIndex, int16_t* outputArray, int startIndex, int count) const = 0;
            virtual bool GetArray(int keyIndex, uint16_t* outputArray, int startIndex, int count) const = 0;
            virtual bool GetArray(int keyIndex, int32_t* outputArray, int startIndex, int count) const = 0;
            virtual bool GetArray(int keyIndex, uint32_t* outputArray, int startIndex, int count) const = 0;
            virtual bool GetArray(int keyIndex, int64_t* outputArray, int startIndex, int count) const = 0;
            virtual bool GetArray(int keyIndex, uint64_t* outputArray, int startIndex, int count) const = 0;

            // templated accessor for scalar data by key name
            // returns true if succeeded, false if key not found or type-mismatch
            template <typename T>
            bool Get(const char *key, T &value) const
            {
                int keyIndex = GetIndexOfKey(key);
                return Get(keyIndex, value);
            }

            // templated accessor for array data by key name
            // startIndex is the offset to read from the data in the payload of the message and count is the number of elements to read
            // returns true if succeeded, false if key not found, type-mismatch or array index out of bounds
            template <typename T>
            bool GetArray(const char *key, T * outputArray, int startIndex, int count) const
            {
                int keyIndex = GetIndexOfKey(key);
                return GetArray(keyIndex, outputArray, startIndex, count);
            }

        protected:
            // all IMessages are created by a call to IConnection::CreateMessage()
            IMessage() {}
            // the user does not delete an IMessage but instead must call Release()
            virtual ~IMessage() {}

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

    } // namespace GameTalk
} // namespace EA


#endif // #ifndef EA_GAMETALK_IMESSAGE_H
