#pragma once

#include "MAXProxies.hpp"

namespace MAXProxies {

	class MAXScene;
	class MAXTextureLibrary;
	class MAXStateLibrary;

	//
	//#########################################################################
	//#######################    MAXTexture    ##############################
	//#########################################################################
	//
	class MAXTexture:
		public Proxies::TextureProxy
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Constructors
	//
	public:
		static MAXTexture*
			MakeProxy(
				MAXTextureLibrary *library,
				MAXScene *scene,
				int texture_index
			)
				{return new MAXTexture(library, scene, texture_index);}

		void
			Destroy();

		void*
			operator new(size_t)
				{return AllocatedMemory->New();}
		void
			operator delete(void *where)
				{AllocatedMemory->Delete(where);}

	protected:
		MAXTexture(
			MAXTextureLibrary *library,
			MAXScene *scene,
			int texture_index
		);
		~MAXTexture();

		static Stuff::MemoryBlock
			*AllocatedMemory;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Class Data Support
	//
	public:
		static ClassData
			*DefaultData;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Testing
	//
	public:
		void
			TestInstance() const;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Texture management functions
	//
	public:
		MAXTextureLibrary*
			GetTextureLibrary()
				{
					Check_Object(this);
					return Cast_Pointer(MAXTextureLibrary*, libraryProxy);
				}

		Proxies::TextureProxy*
			UseNextTextureProxyInLibrary();
		
		Proxies::TextureProxy*
			UsePreviousTextureProxyInLibrary();

		bool GetFormat(FormatType*);
		void SetFormat(FormatType);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Texture functions
	//
	public:
		//
		// name functions
		//
		bool
			GetName(Stuff::MString *name);
		void
			SetName(const char* name);

		//
		// Get the bitmap size
		//
		void
			GetImageSize(Stuff::Vector2DOf<int> *size);

		//
		// Get pixel sizes per channel
		//
		void
			GetChannelDepth(
				unsigned *red_depth,
				unsigned *blue_depth,
				unsigned *green_depth,
				unsigned *alpha_depth
			);
		void
			GetChannels(
				Stuff::DynamicArrayOf<BYTE> *red,
				Stuff::DynamicArrayOf<BYTE> *green,
				Stuff::DynamicArrayOf<BYTE> *blue,
				Stuff::DynamicArrayOf<BYTE> *alpha
			);

		void
			SetChannels(
				const Stuff::DynamicArrayOf<BYTE> *red,
				const Stuff::DynamicArrayOf<BYTE> *green,
				const Stuff::DynamicArrayOf<BYTE> *blue,
				const Stuff::DynamicArrayOf<BYTE> *alpha
			);

//		//
//		// Get channel values
//		//
//		void
//			GetChannel(
//				Stuff::DynamicArrayOf<BYTE> *values,
//				unsigned channel
//			);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Helper functions
	//
	public:
		unsigned
			GetTextureIndex()
				{return textureIndex;}
		void
			ReadTexture();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Implementation details
	//
	protected:
		int
			textureIndex;
		char
			*textureName;
		char
			*origtextureName;
		Stuff::Vector2DOf<int>
			textureSize;
		unsigned
			redDepth,
			greenDepth,
			blueDepth,
			alphaDepth;
		Stuff::DynamicArrayOf<BYTE>
			redChannel,
			greenChannel,
			blueChannel,
			alphaChannel;


		MAXScene
			*proxiedScene;

	public:
		int formatHint;
		FormatType textureFormat;
	};

	//
	//#########################################################################
	//######################    MAXTextureLibrary    ###########################
	//#########################################################################
	//
	class MAXTextureLibrary:
		public Proxies::TextureLibrary
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Constructors
	//
	protected:
		MAXTextureLibrary(MAXStateLibrary *state_library);
		~MAXTextureLibrary();

	public:
		static MAXTextureLibrary*
			MakeProxy(MAXStateLibrary *states)
				{return new MAXTextureLibrary(states);}
		void
			Destroy();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Class Data Support
	//
	public:
		static ClassData
			*DefaultData;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Testing
	//
	public:
		void
			TestInstance() const;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Texture management functions
	//
	public:
		MAXStateLibrary*
			GetStateLibrary()
				{
					Check_Object(this);
					return Cast_Pointer(MAXStateLibrary*, stateLibrary);
				}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Texture functions
	//
	public:
		//
		// Gets the current number of children
		//
		unsigned
			GetTextureCount();

		//
		// Child creation functions
		//
		Proxies::TextureProxy*
			UseNewTextureProxy();
		Proxies::TextureProxy*
			UseMatchingTextureProxy(Proxies::TextureProxy *texture);
		Proxies::TextureProxy*
			UseTextureProxy(const char* texture_name);

		//
		// Child traversal functions
		//
		Proxies::TextureProxy*
			UseFirstTextureProxy();
		Proxies::TextureProxy*
			UseLastTextureProxy();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// SoftImage helper functions
	//
	public:
		MAXTexture*
			UseTextureProxy(int texture_index);

		void
			CloseLibrary();

	protected:
		Stuff::DynamicArrayOf<MAXTexture*>
			textureProxies;
		unsigned
			textureCount;
		int
			lastTextureSearched;
	};
}
