#pragma once
#define MLR_MLRTEXTUREPOOL_HPP

#include <MLR\MLR.hpp>
#include <MLR\GOSImagePool.hpp>
#include <MLR\MLRMovieTexture.hpp>

namespace MidLevelRenderer {

#undef TEXTURE_HUNT

	class MLRTexturePool:
		public Stuff::RegisteredClass

	{
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Initialization
	//
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();
		static ClassData
			*DefaultData;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Constructors/Destructors
	//
	protected:
		MLRTexturePool(Stuff::MemoryStream *stream);

	public:
	//	insDep == nr of lower bits used for image instancing
		MLRTexturePool(GOSImagePool *image_pool, int insDep=3);

		~MLRTexturePool();

		static MLRTexturePool*
			Make(Stuff::MemoryStream *stream);

		void
			Save(Stuff::MemoryStream *stream);

		MLRTexture*
			Add(const char *textureName, int instance=0);
		MLRTexture*
			AddMovie(const char *textureName, int nrOfFrames, Stuff::Scalar frameTime);

		MLRTexture*
			Add(GOSImage*);

		MLRTexture*
			Add(const char* imageName, gos_TextureFormat format, int size, gos_TextureHints hints);

	// only removes the texture from the texture pool, it doesnt destroy the texture
		void
			Remove(MLRTexture*);

		void
			LoadImageGOS(MLRTexture*);
		unsigned
			LoadImages();

		MLRTexture*
			operator() (const char *name, int=0);

		MLRTexture*
			operator[] (int index)
				{
					Check_Object(this); Verify(index-1 < MLRState::TextureMask);

					if (index<=0)
					{
						return NULL;
					}

#if defined(TEXTURE_HUNT) && defined(LAB_ONLY)
					if(textureArray[index-1]==NULL)
					{
						SPEWALWAYS((0, "Couldnt find Textureindex \"%x\"", index));
					}
#endif

		
					return textureArray[index-1];
				}

		MLRTexture*
			operator[] (const MLRStateBase *state)
				{
					Check_Object(this);
#if defined(TEXTURE_HUNT) && defined(LAB_ONLY)
					if(textureArray[state->GetTextureHandle()-1]==NULL)
					{
						SPEWALWAYS((0, "Couldnt find Textureindex \"%x\"", state->GetTextureHandle()));
					}
#endif
					return (*this)[state->GetTextureHandle()];
				}

		GOSImage*
			GetImage(const char* imageName)
				{ Check_Object(this); return imagePool->GetImage(imageName);	}

		const GOSImagePool*
			GetGOSImagePool()
				{ Check_Object(this); return imagePool;	}

		unsigned
			GetLastHandle()
				{Check_Object(this); return lastHandle;}

		unsigned 
			GetNumStoredTextures()
				{Check_Object(this); return storedTextures;}

		int
			GetInstanceDepth() const
				{ Check_Object(this); return instanceDepth; }


		static MLRTexturePool
			*Instance;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Skin support
	//
		typedef const char* (*Skinner)(const char* old_name);

		void
			SetSkinner(Skinner skinner)
				{Check_Object(this); theSkinner = skinner;}
		Skinner
			GetSkinner()
				{Check_Object(this); return theSkinner;}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Testing
	//
	public:
		void
			TestInstance() const
				{}

		Stuff::ChainOf<MLRTexture*>
			unloadedTextures;

	protected:
		int	instanceDepth, // bits used for image instancing
			instanceMax; // max for image instancing

		int	handleDepth, // bits used for image instancing
			handleMax; // max for image instancing

		int lastHandle;
		int storedTextures;
		
		Stuff::StaticArrayOf<MLRTexture*, MLRState::TextureMask+1> textureArray;

		int *freeHandle;
		int firstFreeHandle;
		int lastFreeHandle;

		GOSImagePool
			*imagePool;

		Skinner
			theSkinner;

	};

}
