#pragma once

#include "Proxies.hpp"
#include "GenericProxy.hpp"

namespace Proxies {

	class IndexProxy;
	class StateProxy;
	class TextureProxy;
	class PolygonMeshProxy;


	//
	//#########################################################################
	//########################    MultiState    #############################
	//#########################################################################
	//
	class MultiState :
		public Stuff::DynamicArrayOf<StateProxy*>
	{
		public:
			MultiState() { isInverted = false; }
			MultiState(const MultiState&);
			~MultiState() { Check_Object(this); DetachReferences(); }

			bool
				IsEqualTo(const MultiState& multi_state);
//			unsigned
//				UseStateArray(MultiState *states);
			void
				DetachReferences();
			MultiState&
				operator=(const MultiState&);

			bool isInverted;
	};

	//
	//#########################################################################
	//########################    PolygonProxy    #############################
	//#########################################################################
	//
	class PolygonProxy:
		public GenericProxy
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

		static ClassData
			*DefaultData;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Constructors
	//
	protected:
		~PolygonProxy();
		PolygonProxy();
		PolygonProxy(
			ClassData *class_data,
			PolygonMeshProxy *mesh
		);

		static Stuff::MemoryBlock
			*AllocatedMemory;

	public:
		static PolygonProxy*
			MakeProxy()
				{return new PolygonProxy;}
		void
			Destroy();

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

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

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Process support
	//
	public:
		virtual int
			FindErrors(FindErrorsProcess *process);

		virtual void
			GetNormal(Stuff::Normal3D *normal);
		virtual Stuff::Scalar
			GetArea();
		virtual void
			GetVertexCentroid(Stuff::Point3D *center);
		virtual Stuff::Scalar
			GetSurfaceAreaAndCentroid(Stuff::Point3D *center);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Polygon management functions
	//
	public:
		//
		// Traversal functions
		//
		PolygonMeshProxy*
			GetPolygonMeshProxy()
				{Check_Object(this); return meshProxy;}

		//
		// polygons dont get names
		//
		bool
			GetName(class Stuff::MString *name)
				{Check_Object(this); Check_Object(name); return false;}
		void
			SetName(const char* name)
				{Check_Object(this); Check_Pointer(name);}

	protected:
		PolygonMeshProxy
			*meshProxy;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// multi layer support
	//
	public:
		virtual unsigned
			UseMultiState(MultiState *states);
		virtual void
			SetStatesToMatch(
				const MultiState &states
			);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Polygon index functions
	//
	public:
		//
		// Get the number of vertices in the polygon
		//
		virtual unsigned
			UseIndexArray(Stuff::DynamicArrayOf<IndexProxy*> *indices);
		void
			DetachArrayReferences(Stuff::DynamicArrayOf<IndexProxy*> *indices);
		void
			SetPolygonIndices(
				const Stuff::DynamicArrayOf<VertexProxy*> &vertices
			);

		void
			AttachIndexProxy(IndexProxy *proxy)
				{
					Check_Object(this);
					AttachReference(); activeIndexProxies.Add(proxy);
				}
		void
			DetachIndexProxy(IndexProxy* proxy);

	protected:
		Stuff::ChainOf<IndexProxy*>
			activeIndexProxies;
		Stuff::DynamicArrayOf<VertexProxy*>
			vertexArray;
		MultiState
			stateArray;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Polygon functions
	//
	public:
		//
		// group functions
		//
		virtual void
			AddToCollection(const char *group);
		virtual void
			AddToCollections(MStringChain &group_list);
		virtual void
			RemoveFromCollection(const char *group);
		virtual void
			RemoveFromCollections(MStringChain &group_list);
		virtual void
			GetCollections(MStringChain *group_list);
		virtual bool
			IsMemberOf(const char *group);
	};

}
