#pragma once

#include "MAXProxies.hpp"

namespace MAXProxies {

	class MAXScene;
	class MAXStateLibrary;

	//
	//#########################################################################
	//###########################    MAXState    ###############################
	//#########################################################################
	//
	class MAXState:
		public Proxies::StateProxy
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

		static ClassData
			*DefaultData;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Constructors
	//
	public:
		static MAXState*
			MakeProxy(
				MAXStateLibrary *library,
				INode *mesh,
				Mtl *material,
				BitmapTex *texture,
				int indice
			)
				{
					return
						new MAXState(
							library,
							mesh,
							material,
							texture,
							indice
						);
				}

		void
			Destroy();

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

	protected:
		MAXState(
			MAXStateLibrary *library,
			INode *mesh,
			Mtl *material,
			BitmapTex *texture,
			int indice
		);
		~MAXState();

		static Stuff::MemoryBlock
			*AllocatedMemory;

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

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

#if 0	// was input to fix a bug in the lower level proxies that has since been
		// solved "we think"

		bool
			IsEqualTo(Proxies::StateProxy *material);

		bool
			GetAlphaSetting(void);
#endif

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

		//
		// specular color functions
		//
		bool
			GetSpecularColor(Stuff::RGBColor *color);
		void
			SetSpecularColor(const Stuff::RGBColor &color);
		Stuff::Scalar
			GetSpecularShininess();
		void
			SetSpecularShininess(Stuff::Scalar shininess);

		//
		// texture functions
		//
		Proxies::TextureProxy*
			UseTextureProxy();
		Proxies::TextureProxy*
			SetToMatchTextureProxy(Proxies::TextureProxy *texture);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Render States
	//
	public:
		bool
			GetAlpha(Proxies::StateProxy::AlphaMode*);
		void
			SetAlpha(Proxies::StateProxy::AlphaMode);
		bool
			GetAlphaChildPermission();
		void
			SetAlphaChildPermission(bool override);

		bool
			GetFilter(FilterMode*);
		void
			SetFilter(FilterMode);
		bool
			GetFilterChildPermission();
		void
			SetFilterChildPermission(bool override);

		bool
			GetFog(FogMode*);
		void
			SetFog(FogMode);
		bool
			GetFogChildPermission();
		void
			SetFogChildPermission(bool override);

		bool
			GetDither(bool*);
		void
			SetDither(bool);
		bool
			GetDitherChildPermission();
		void
			SetDitherChildPermission(bool override);

		bool
			GetSpecular(bool*);
		void
			SetSpecular(bool);
		bool
			GetSpecularChildPermission();
		void
			SetSpecularChildPermission(bool override);

		bool
			GetTextureCorrection(bool*);
		void
			SetTextureCorrection(bool);
		bool
			GetTextureCorrectionChildPermission();
		void
			SetTextureCorrectionChildPermission(bool override);

		bool
			GetTextureWrap(TextureWrapMode*);
		void
			SetTextureWrap(TextureWrapMode);
		bool
			GetTextureWrapChildPermission();
		void
			SetTextureWrapChildPermission(bool override);

		bool
			GetWireFrame(WireFrameMode*);
		void
			SetWireFrame(WireFrameMode);
		bool
			GetWireFrameChildPermission();
		void
			SetWireFrameChildPermission(bool override);

		bool
			GetZBufferCompare(bool*);
		void
			SetZBufferCompare(bool);
		bool
			GetZBufferCompareChildPermission();
		void
			SetZBufferCompareChildPermission(bool override);

		bool
			GetZBufferWrite(bool*);
		void
			SetZBufferWrite(bool);
		bool
			GetZBufferWriteChildPermission();
		void
			SetZBufferWriteChildPermission(bool override);

		bool
			GetFlatColoring(bool*);
		void
			SetFlatColoring(bool);
		bool
			GetFlatColoringChildPermission();
		void
			SetFlatColoringChildPermission(bool override);


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Process state
	//
		bool
			GetMatTwoSided(bool *onOff);
		void
			SetMatTwoSided(bool onOff);
		bool
			GetMatTwoSidedChildPermission();
		void
			SetMatTwoSidedChildPermission(bool override);

		bool
			GetBackface(bool *onOff);
		void
			SetBackface(bool onOff);
		bool
			GetBackfaceChildPermission();
		void
			SetBackfaceChildPermission(bool override);


		bool
			GetPriority(int*);
		void
			SetPriority(int);
		bool
			GetPriorityChildPermission();
		void
			SetPriorityChildPermission(bool override);

		bool
			GetLighting(int*);
		void
			SetLighting(int);
		bool
			GetLightingChildPermission();
		void
			SetLightingChildPermission(bool override);


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Helper functions
	//
	public:
		Mtl*
			GetMaterialState()
				{return materialState;}
		BitmapTex*
			GetTextureState()
				{return textureState;}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Implementation details
	//
	protected:
		INode
			*meshState;
		Mtl *
			materialState;
		BitmapTex *
			textureState;
		int 
			mapIndice;
		bool
			bFlatShaded,
			bAlphaMode;
	public:
		int matID;
		int mipmapHint;
	};

	//
	//#########################################################################
	//######################    MAXStateLibrary    ##########################
	//#########################################################################
	//
	class MAXStateLibrary:
		public Proxies::StateLibrary
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Constructors
	//
	protected:
		MAXStateLibrary(MAXScene *scene);
		~MAXStateLibrary();

	public:
		static MAXStateLibrary*
			MakeProxy(MAXScene *scene)
				{return new MAXStateLibrary(scene);}
		void
			Destroy();

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

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

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// State management functions
	//
	public:
		MAXScene*
			GetSceneProxy()
				{Check_Object(this); return Cast_Pointer(MAXScene*, sceneProxy);}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// State functions
	//
	public:
		//
		// Child creation functions
		//
		Proxies::StateProxy*
			UseMatchingStateProxy(Proxies::StateProxy *state,Proxies::TextureProxy *texture);
		void
			CalculateMaxState(
				MAXState *state,
				Proxies::StateProxy *proxy,
				Proxies::TextureProxy *texture
			);
		MultiMtl *GetMultiMtl();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Openflight helper functions
	//
	public:
		MAXState*
			UseStateProxy(
				Mtl *material,
				BitmapTex *texture,
				INode* mesh,
				int indice
			);

		void
			CloseLibrary();

	protected:
		MultiMtl *multiMtl;
	};
}
