#pragma once

#include "Proxies.hpp"
#include "TextureProxy.hpp"

namespace Proxies {

	class SceneProxy;
	class StateLibrary;

	//
	//#########################################################################
	//#######################    StateProxy    #############################
	//#########################################################################
	//
	class _declspec(novtable) StateProxy:
		public GenericProxy
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Constructors
	//
	protected:
		StateProxy(
			ClassData *class_data,
			StateLibrary *library
		);
		~StateProxy();

	public:
		//
		// Copies the elements of the given material into this material
		//
		virtual void
			Copy(
				CopyProcess *copy,
				StateProxy *state
			);
		//
		// gives informations about this state
		//
		virtual void
			GetInfo(
				GetInfoProcess *process
			);

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

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

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Material management functions
	//
	public:
		StateLibrary*
			GetStateLibrary()
				{Check_Object(this); return libraryProxy;}

		virtual bool
			IsEqualTo(StateProxy *material);

	protected:
		StateLibrary
			*libraryProxy;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// State functions
	//
	public:

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Render state
	//
		enum AlphaMode {
			OneZeroMode = 0,
			OneOneMode,
			AlphaOneMode,
			OneAlphaMode,
			AlphaInvAlphaMode,
			OneInvAlphaMode,
			KeyedAlphaMode
		};

		virtual bool
			GetAlpha(AlphaMode*) = 0;
		virtual void
			SetAlpha(AlphaMode) = 0;
		virtual bool
			GetAlphaChildPermission() = 0;
		virtual void
			SetAlphaChildPermission(bool override) = 0;

		enum FilterMode {
			NoFilterMode = 0,
			BiLinearFilterMode,
			TriLinearFilterMode
		};

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

		enum FogMode {
			DisableFogMode = 0,
			GeneralFogMode,
			LightFogMode,
			CustomFogMode
		};

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


		virtual bool
			GetDither(bool*) = 0;
		virtual void
			SetDither(bool) = 0;
		virtual bool
			GetDitherChildPermission() = 0;
		virtual void
			SetDitherChildPermission(bool override) = 0;

		virtual bool
			GetSpecular(bool*) = 0;
		virtual void
			SetSpecular(bool) = 0;
		virtual bool
			GetSpecularChildPermission() = 0;
		virtual void
			SetSpecularChildPermission(bool override) = 0;

		virtual bool
			GetTextureCorrection(bool*) = 0;
		virtual void
			SetTextureCorrection(bool) = 0;
		virtual bool
			GetTextureCorrectionChildPermission() = 0;
		virtual void
			SetTextureCorrectionChildPermission(bool override) = 0;

		enum TextureWrapMode {
			TextureWrap = 0,
			TextureClamp
		};

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

		enum WireFrameMode {
			WireFrameOffMode = 0,
			WireFrameOnlyMode,
			WireFrameAddMode
		};

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

		virtual bool
			GetZBufferCompare(bool*) = 0;
		virtual void
			SetZBufferCompare(bool) = 0;
		virtual bool
			GetZBufferCompareChildPermission() = 0;
		virtual void
			SetZBufferCompareChildPermission(bool override) = 0;

		virtual bool
			GetZBufferWrite(bool*) = 0;
		virtual void
			SetZBufferWrite(bool) = 0;
		virtual bool
			GetZBufferWriteChildPermission() = 0;
		virtual void
			SetZBufferWriteChildPermission(bool override) = 0;

		virtual bool
			GetFlatColoring(bool*) = 0;
		virtual void
			SetFlatColoring(bool) = 0;
		virtual bool
			GetFlatColoringChildPermission() = 0;
		virtual void
			SetFlatColoringChildPermission(bool override) = 0;


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

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

		enum {
			DefaultPriority = 0,
			DetailPrority,
			AlphaPriority,
			EffectPriority0=4,
			EffectPriority1,
			EffectPriority2,
			EffectPriority3,
			WeatherPriority,
			CagePriority,
			CageEffectsPriority,
			FlarePriority,
			HUDPriority0,
			HUDPriority1,
			HUDPriority2,
			HUDPriority3,
			PriorityCount
		};

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

		enum LightingMode {
			LightingOffMode = 0,
			LightingLightMapMode=1,
			LightingVertexMode=2,
			LightingLookupMode=4,
			LightingFaceMode=8
		};

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

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


		//
		// texture functions
		//
		virtual TextureProxy*
			UseTextureProxy() = 0;
		virtual TextureProxy*
			SetToMatchTextureProxy(TextureProxy *texture) = 0;
	};

	//
	//#########################################################################
	//######################    StateLibrary    ############################
	//#########################################################################
	//
	class _declspec(novtable) StateLibrary:
		public GenericProxy
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Constructors
	//
	protected:
		StateLibrary(
			ClassData *class_data,
			SceneProxy *scene
		);
		~StateLibrary();

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

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

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Material management functions
	//
	public:
		SceneProxy*
			GetSceneProxy()
				{Check_Object(this); return sceneProxy;}

	protected:
		SceneProxy
			*sceneProxy;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Material functions
	//
	public:
		//
		// name functions
		//
		bool
			GetName(Stuff::MString *name)
				{return false;}
		void
			SetName(const char* name)
				{}

		//
		// state functions
		//
		virtual StateProxy*
			UseMatchingStateProxy(
				StateProxy *material,
				TextureProxy *texture=NULL
			) = 0;

		TextureLibrary*
			GetTextureLibrary()
				{Check_Object(this); return textureLibrary;}

		void
			AttachStateProxy(StateProxy *proxy)
				{
					Check_Object(this);
					AttachReference(); activeStateProxies.Add(proxy);
				}
		void
			DetachStateProxy(StateProxy* proxy);

	protected:
		TextureLibrary*
			textureLibrary;
		Stuff::ChainOf<StateProxy*>
			activeStateProxies;
	};

}
