#pragma once

#include "ElementProxies.hpp"

namespace ElementProxies {

	class MLRIndexProxy;
	class ElementPolygonMeshProxy;

	//
	//#########################################################################
	//######################    MLRPolygonProxy    #############################
	//#########################################################################
	//
	class MLRPolygonProxy:
		public Proxies::PolygonProxy
	{
		friend class MLRIndexProxy;

	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

		static ClassData
			*DefaultData;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Constructors
	//
	public:
		static MLRPolygonProxy*
			MakeProxy(
				ElementPolygonMeshProxy *mesh,
				int primitive_index,
				int polygon_index
			)
				{
					return
						new MLRPolygonProxy(
							mesh,
							primitive_index,
							polygon_index
						);
				}

		void
			Destroy();

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

	protected:
		MLRPolygonProxy(
			ElementPolygonMeshProxy *mesh,
			int primitive_index,
			int polygon_index
		);
		~MLRPolygonProxy();

		static Stuff::MemoryBlock
			*AllocatedMemory;

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

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Polygon management functions
	//
	public:
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// multi layer support
	//
	public:
		unsigned
			UseMultiState(Proxies::MultiState *states);
		void
			SetStatesToMatch(
				const Proxies::MultiState &states
			);

		//
		// Traversal functions
		//
		ElementPolygonMeshProxy*
			GetPolygonMeshProxy()
				{
					Check_Object(this);
					return Cast_Pointer(ElementPolygonMeshProxy*, meshProxy);
				}

		Proxies::PolygonProxy*
			UseNextPolygonProxy();
		Proxies::PolygonProxy*
			UsePreviousPolygonProxy();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Polygon functions
	//
	public:
		//
		// Get the number of vertices in the polygon
		//
		unsigned
			UseIndexArray(Stuff::DynamicArrayOf<Proxies::IndexProxy*> *indices);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Polygon functions
	//
	public:
		//
		// group functions
		//
		void
			AddToCollection(const char *collection);
		void
			AddToCollections(Proxies::MStringChain &collection_list);
		void
			RemoveFromCollection(const char *collection);
		void
			RemoveFromCollections(Proxies::MStringChain &collection_list);
		void
			GetCollections(Proxies::MStringChain *collection_list);
		bool
			IsMemberOf(const char *collection);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Helper functions
	//
	public:
		Proxies::IndexProxy*
			GetIndexProxy(unsigned index);

	protected:
		int
			primitiveIndex,
			polygonIndex,
			indexStart;
	};

}
