// DWBS ------------------------------------------------------------------ DWBS
//
// PLATFORM		: ALL
// PRODUCT		: BIT_DEMON
// VISIBILITY	: PUBLIC
//
// DWBS ------------------------------------------------------------------ DWBS

#ifndef BD_ADDRESS_MAP_H
#define BD_ADDRESS_MAP_H

#include <bdCore/bdCore.h>

#include <bdSocket/bdSocketConfig.h>

/// The address map is a singleton that maps address handles to real address information.
/// The address handles are used to refer to endpoints before the correct address has
/// been resolved by the NAT traversal.
class bdAddressMapImpl
{
	public:

		BD_DECLARE_NEW_AND_DELETE_OPERATORS

		bdAddressMapImpl();

		/// Converts a common address and security id to an address handle. The address
		/// handle can then be used to send data to the client that the common address
		/// specified and will be returned when data is received from that client.
		/// \param ca[in] The common address of the remote client.
		/// \param id[in] The security id to be used.
		/// \param addrHandle[out] Address handle ref that receives the created address handle.
		/// \return True if success
		bdBool commonAddrToAddr(bdCommonAddrRef ca,
								const bdSecurityID &id,
								bdAddrHandleRef &addrHandle);

		/// Returns the common address and security id associated with the address handle.
		/// \param addrHandle[in] A reference to a valid address handle.
		/// \param ca[out] A reference to a common address. This will be changed to point to
		/// the common address for the address handle.
		/// \param id[in] A reference to where the security id for the address handle
		/// will be copied.
		bdBool addrToCommonAddr(const bdAddrHandleRef &addrHandle,
								bdCommonAddrRef &ca,
								bdSecurityID &id) const;

		/// Unregisters any data associated with the address handle. If a secure association
		/// exists it will also be torn down.
		bdBool unregisterAddr(bdAddrHandleRef &addrHandle);

		/// The the local game's common address.
		/// \return True if success
		bdBool getTitleCommonAddr(bdCommonAddrRef &ca);

		/// Set the local game's common address.
		void setTitleCommonAddr(bdCommonAddrRef ca);

		/// Converts the address handle into a string. If the address handle has not
		/// yet been resolved by the NAT traversal then it will return "not_resolved" as
		/// the string. If the address is a local loopback str is set to "loopback".
		/// \param addrHandle[in] The valid address handle.
		/// \param str[out] A pointer to where the string will be written.
		/// \param size[in] The size of the char array pointed to by \c str.
		/// \return The number of characters in the address string.
		bdUWord addrToString(const bdAddrHandleRef &addrHandle,
							bdNChar8 *const str,
							const bdUWord size) const;

		/// Clears the address map completely.
		/// This will result in all entries in the map being
		/// removed. Calling this function will connected to remote
		/// nodes has undefined behaviour.
		void clear();

	protected:

		friend class bdDTLSAssociation;
		friend class bdSocketRouter;

		bdBool getAddressMapping(const bdAddr &realAddr,
								 bdAddrHandleRef &addrHandle) const;

		void remove(bdCommonAddrRef ca);

	protected:

		bdCommonAddrRef m_me;

#if !defined BD_PLATFORM_XBOX && !defined BD_PLATFORM_PSP_ADHOC

		class bdCommonAddrRefWrapper
		{
			public:

				BD_DECLARE_NEW_AND_DELETE_OPERATORS;

				bdBool operator == (const bdCommonAddrRefWrapper &other) const
				{
					return m_ca->getHash() == other.m_ca->getHash();
				}


				inline bdUInt getHash(const bdCommonAddrRefWrapper &other) const
				{
					return other.m_ca->getHash();
				}

				bdCommonAddrRef m_ca;
		};

		bdHashMap<bdCommonAddrRefWrapper, bdAddrHandleRef, bdCommonAddrRefWrapper> m_caToAddr;
#endif
};


class bdAddressMap : public bdSingleton<bdAddressMapImpl>
{
	BD_DECLARE_NEW_AND_DELETE_OPERATORS

	protected:
		/// Default constructor.
		bdAddressMap();
};

#endif // BD_ADDRESS_MAP_H
