#ifndef IMAPPING_H
#define IMAPPING_H

namespace Salamander
{

/*
** Abstract base class for platform enum mapping. Used primarily for controller data, this
** class should be implemented for each platform.
**
** IMapping uses a static map and cast override for ease of use. To convert from an arbritrary
** mapping to a salamander mapping, the class can simply be instantiated and used as the required
** salamander mapping. ie.
**
** salamanderCode = KeyMapping(PLATFORM_KEY);
**
** Likewise, the mapping can be used in reverse, to convert from a salamander mapping to a platform
** specific mapping. ie.
**
** PLATFORM_BLEND_MODE = BlendMapping(salamanderBlendMode)
**
*/
template <typename SourceType, typename TargetType>
class IMapping
{
public:
	/*
	** Destructor.
	*/
	virtual ~IMapping();

	/*
	** When instantiated, we store the source type for later use in the lookup table.
	*/
	IMapping(const SourceType sourceType);

	/*
	** An implicit cast operator is defined so that IMapping can be used directly as the required
	** target mapping type without the user needing to worry about explicitly typecasting it to the
	** necessary enum.
	*/
	virtual operator TargetType();

protected:
	/*
	** Add an entry into the mapping table, is called to set everything up before the class is used.
	*/
	static bool addMapping(const SourceType sourceType, const TargetType targetType);

private:

	/*
	** This is called on first instantiation of the class to fill the mapping table. This method is required
	** be implemented by subclasses, and so is marked as pure.
	*/
	virtual void initialiseMapping() = 0;

private:
	/*
	** Each templated version of IMapping holds a different mapping table. This is shared between
	** all instantiations of the enum-specific version, for quick lookup when IMapping() is called.
	**
	** Implementations of this class should call 'addMapping' to add new enum pairs
	*/
	static std::map<SourceType, TargetType> mapping_;

	/*
	** We perform a lazy look-up to determine the target type when first requested. All requests
	** after this will return the pre-cached member.
	*/
	TargetType targetType_;

	/*
	** Upon instantiation, the source type is stored in this member.
	*/
	SourceType sourceType_;

};

}

#include "IMapping.inl"

#endif // IMAPPING_H