#pragma once
#define MLR_GOSVERTEXPOOL_HPP

#include <MLR\MLR.hpp>
#include <MLR\GOSVertex.hpp>
#include <MLR\GOSVertex2UV.hpp>
#include <MLR\GOSVertex3UV.hpp>

namespace MidLevelRenderer {

	//##########################################################################
	//######################    GOSVertexPool    ###############################
	//##########################################################################

	class GOSVertexPool
	{
		public:
			GOSVertexPool();
			
			void Reset();

//
//------------------------------------------------------------------------------------------------------------
//
			int GetLength () 
				{ 
					Check_Object(this); 
					return vertices.GetLength()-1; 
				}

			unsigned GetLast () 
				{ 
					Check_Object(this); 
					return lastUsed; 
				}

			int Increase (int add=1)
				{ 
					Check_Object(this); 
					lastUsed += add; 

					Verify(lastUsed<vertices.GetLength());
#ifdef LAB_ONLY
					UsedGOSVertices = UsedGOSVertices < lastUsed ? lastUsed : UsedGOSVertices;
#endif
					return lastUsed;
				}

			GOSVertex*
				GetActualVertexPool(bool db=false)
					{ 
						Check_Object(this); 

						if(db)
						{
							return verticesDB.GetData(); 
						}
						else
						{
//							PAUSE(("This code path in \"GOSVertexPool\" is no longer supported"));
							return (GOSVertex*)(vertices.GetData() + lastUsed); 
						}
					}

//
//------------------------------------------------------------------------------------------------------------
//
			int GetLength2UV () 
				{ 
					Check_Object(this); 
					return vertices2uv.GetLength()-1; 
				}

			unsigned GetLast2UV () 
				{ 
					Check_Object(this); 
					return lastUsed2uv; 
				}

			int Increase2UV (int add=1)
				{ 
					Check_Object(this); 
					lastUsed2uv += add; 
					Verify(lastUsed2uv<vertices2uv.GetLength());
#ifdef LAB_ONLY
					UsedGOSVertices2UV = UsedGOSVertices2UV < lastUsed2uv ? lastUsed2uv : UsedGOSVertices2UV;
#endif

					return lastUsed2uv;
				}

			GOSVertex2UV*
				GetActualVertexPool2UV(bool db=false)
					{ 
						Check_Object(this); 
						if(db)
						{
							return vertices2uvDB.GetData(); 
						}
						else
						{
//							PAUSE(("This code path in \"GOSVertexPool\" is no longer supported"));
							return (GOSVertex2UV*)(vertices2uv.GetData() + lastUsed2uv); 
						}
					}

//
//------------------------------------------------------------------------------------------------------------
//
			int GetLength3UV () 
				{ 
					Check_Object(this); 
					return vertices3uv.GetLength()-1; 
				}

			unsigned GetLast3UV () 
				{ 
					Check_Object(this); 
					return lastUsed3uv; 
				}

			int Increase3UV (int add=1)
				{ 
					Check_Object(this); 
					lastUsed3uv += add; 
					Verify(lastUsed3uv<vertices3uv.GetLength());
#ifdef LAB_ONLY
					UsedGOSVertices3UV = UsedGOSVertices3UV < lastUsed3uv ? lastUsed3uv : UsedGOSVertices3UV;
#endif

					return lastUsed3uv;
				}

			GOSVertex3UV*
				GetActualVertexPool3UV(bool db=false)
					{ 
						Check_Object(this); 
						if(db)
						{
							return vertices3uvDB.GetData(); 
						}
						else
						{
//							PAUSE(("This code path in \"GOSVertexPool\" is no longer supported"));
							return (GOSVertex3UV*)(vertices3uv.GetData() + lastUsed3uv); 
						}
					}

//
//------------------------------------------------------------------------------------------------------------
//
			unsigned GetLastIndex () 
				{ 
					Check_Object(this); 
					return lastUsedIndex; 
				}

			int IncreaseIndex (int add=1)
				{ 
					Check_Object(this); 
					lastUsedIndex += add; 
					Verify(lastUsedIndex<indices.GetLength());
#ifdef LAB_ONLY
					UsedGOSIndicies = UsedGOSIndicies < lastUsedIndex ? lastUsedIndex : UsedGOSIndicies;
#endif

					return lastUsedIndex;
				}

			WORD*
				GetActualIndexPool(bool db=false)
					{ 
						Check_Object(this); 
						if(db)
						{
							return indicesDB.GetData(); 
						}
						else
						{
//							PAUSE(("This code path in \"GOSVertexPool\" is no longer supported"));
							return (WORD*)(indices.GetData() + lastUsedIndex); 
						}
					}

//
//------------------------------------------------------------------------------------------------------------
//
			void
				TestInstance()
					{
						Verify(lastUsed < Limits::Max_Number_Vertices_Per_Frame);
						Verify(lastUsed2uv < Limits::Max_Number_Vertices_Per_Frame);
						Verify(lastUsed3uv < Limits::Max_Number_Vertices_Per_Frame);
						Verify(lastUsedIndex < Limits::Max_Number_Vertices_Per_Frame);
					}

		protected:
			unsigned lastUsed;
			unsigned lastUsed2uv;
			unsigned lastUsed3uv;
			unsigned lastUsedIndex;

			Stuff::DynamicArrayOf<GOSVertex> vertices; // , Max_Number_Vertices_Per_Frame+4*Max_Number_ScreenQuads_Per_Frame
			Stuff::DynamicArrayOf<GOSVertex2UV> vertices2uv; // , Max_Number_Vertices_Per_Frame+4*Max_Number_ScreenQuads_Per_Frame
			Stuff::DynamicArrayOf<GOSVertex3UV> vertices3uv; // , Max_Number_Vertices_Per_Frame+4*Max_Number_ScreenQuads_Per_Frame
			Stuff::DynamicArrayOf<WORD> indices; // , Max_Number_Vertices_Per_Frame

			Stuff::DynamicArrayOf<GOSVertex> verticesDB; // , Max_Number_Vertices_Per_Mesh
			Stuff::DynamicArrayOf<GOSVertex2UV> vertices2uvDB; // , Max_Number_Vertices_Per_Mesh
			Stuff::DynamicArrayOf<GOSVertex3UV> vertices3uvDB; // , Max_Number_Vertices_Per_Mesh
			Stuff::DynamicArrayOf<WORD> indicesDB; // , Max_Number_Vertices_Per_Mesh

		private:
			GOSVertexPool(const GOSVertexPool&);
	};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	inline
		GOSVertexPool::GOSVertexPool() 
	{ 
		Verify(gos_GetCurrentHeap() == ClipperHeap);
		lastUsed = 0;
		lastUsed2uv = 0;
		lastUsed3uv = 0;
		lastUsedIndex = 0;
		
		gos_PushCurrentHeap(StaticHeap);

		vertices.SetLength(Limits::Max_Size_Of_Vertex_Buffer);
		vertices2uv.SetLength(Limits::Max_Size_Of_Vertex_Buffer);
		vertices3uv.SetLength(Limits::Max_Size_Of_Vertex_Buffer);
		indices.SetLength(Limits::Max_Size_Of_Index_Buffer);

		verticesDB.SetLength(Limits::Max_Size_Of_Vertex_Buffer);
		vertices2uvDB.SetLength(Limits::Max_Size_Of_Vertex_Buffer);
		vertices3uvDB.SetLength(Limits::Max_Size_Of_Vertex_Buffer);
		indicesDB.SetLength(Limits::Max_Size_Of_Index_Buffer);

		gos_PopCurrentHeap();
	}


	inline void
		GOSVertexPool::Reset()
	{
		Check_Object(this);
		lastUsed = 0;
		lastUsed2uv = 0;
		lastUsedIndex = 0;
	}

}
