#pragma once
#define MLR_MLRLIGHTMAP_HPP

#include "MLR.hpp"
#include "MLR_I_C_TMesh.hpp"

namespace MidLevelRenderer {

	//##########################################################################
	//#########################    MLRLightMap    ##############################
	//##########################################################################

	class MLRLightMap:
		public Stuff::RegisteredClass
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

		MLRLightMap(MLRTexture*);
		~MLRLightMap();

		enum MemoryStreamData {
			Matrix4D=0,
			ClippingState,
			MasterRenderState,
			CTMesh
		};

		static void
			DrawLightMaps(MLRSorter*, bool);

		static void
			 SetDrawData 
				(
					GOSVertexPool*,
					Stuff::Matrix4D*,
					MLRClippingState&,
					MLRStateBase&
				);

		static MLR_I_C_TMesh*
			CreateLightMapMesh();

		static void
			Reset();

		void
			SetState(MLRState new_state)
				{ Check_Object(this); state = new_state; }
		MLRState
			GetState()
				{ Check_Object(this); return state; }

		inline bool
			AddMesh(int priority, int vertexCount, int indexCount)
				{
					Check_Object(this);
					Check_Object(stream);
					*stream << (int)CTMesh;
					AddState(priority);

					*stream << currentVertex << vertexCount;
					*stream << currentIndex << indexCount;

#if _DEBUG
					for(int i=0;i<indexCount;i++)
					{
						Verify((*index)[currentIndex+i] < vertexCount);
					}
#endif
					currentVertex += vertexCount;
					currentIndex += indexCount;

					return true;
				}

		inline bool
			AddState(int priority)
				{
					Check_Object(this);
					Check_Object(stream);
					if(stream->GetBytesRemaining() < 256) // sizeof a saved state and then some
					{
						return false;
					}
					state.SetPriority(priority);
					state.Save(stream);

					stream->AdvanceToDwordBoundary();

				    return true;
				}

		inline bool
			AddVertex(int index, const Stuff::Point3D& p, const Vector2DScalar& t, const ColorType& c)
				{
					Check_Object(this); 
					if(index+currentVertex >= coords->GetLength()) 
					{
						return false; 
					}
					(*coords)[index+currentVertex] = p;
					(*texCoords)[index+currentVertex] = t;
					(*colors)[index+currentVertex] = c;

					return true;
				}

		inline bool
			AddIndex(int i, BYTE _index)
				{
					Check_Object(this); 
					if(i+currentIndex >= index->GetLength()) 
					{
						return false; 
					}
					(*index)[currentIndex+i] = _index;

					return true;
				}

		const Vector2DScalar*
			GetCurrentUVPointer()
				{ Check_Object(this); Check_Object(stream); return Cast_Pointer(Vector2DScalar*, stream->GetPointer()); }

		bool
			IsFull()
				{ Check_Object(this); return full; }

		static bool
			IsFull(int);

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

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Reference counting
	//
	public:
		void
			AttachReference()
				{Check_Object(this); ++referenceCount;}
		void
			DetachReference()
				{
					Check_Object(this); Verify(referenceCount > 0);
					if ((--referenceCount) == 0)
					{
						Unregister_Object(this);
						delete this;
					}
				}

		int
			GetReferenceCount()
				{return referenceCount;}

	protected:
		int
			referenceCount;

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

	protected:
		static ClipPolygon2
			*clipBuffer;

		MLRState
			state;

		static bool
			full;
		static Stuff::MemoryStream
			*stream;
		static GOSVertexPool*
			vertexPool;

		static int currentVertex;
		static Stuff::DynamicArrayOf<Stuff::Point3D> *coords;	// Base address of coordinate list 
		static Stuff::DynamicArrayOf<Vector2DScalar> *texCoords;	// Base address of texture coordinate list 
		static Stuff::DynamicArrayOf<ColorType> *colors;	// Base address of color list

		static int currentIndex;
		static Stuff::DynamicArrayOf<BYTE>	*index;	// List of color indexes 

		static int currentCTMesh;
		static DynamicArrayOf<MLR_I_C_TMesh*> *ctmeshs;
	};

}
