#pragma once

#include "FeatureGrid.hpp"
#include <MLR\MLR.hpp>
#include <MLR\GOSVertex.hpp>

namespace MidLevelRenderer {
	class MLR_Terrain2;
	class MLRTexture;
}

namespace ElementRenderer {class GridElement;}

//	#define THE03HACK

namespace Compost
{
	struct CompostQueueStruct {
		CompostQueueStruct() { featureGrid=NULL; row=0; column=0; textureHolder=NULL; downSample=0; type=0; done = -1; }

		FeatureGrid *featureGrid;
		int row, column;
		TextureHolder *textureHolder;
		int downSample;
		int type;
		int done;

		bool
			Compose() {
				Check_Pointer(this);
				Check_Pointer(featureGrid);
				Check_Pointer(textureHolder);
				return featureGrid->ComposeGrid(row, column, textureHolder, downSample, type);
			}

	};

	class CompostQueue {
		public:
			CompostQueue();

		bool SetCompostQueue(
				FeatureGrid *featureGrid,
				int row, 
				int column,
				TextureHolder *textureHolder,
				int downSample,
				int type
			);

		void
			EraseCompostQueueFlag(int index)
			{
				if(index<0)
				{
					return;
				}
				Verify(index<Length_Of_Compost_Queue);
				compostQueueTracker[index>>5] &= ~(1<<(index & (32-1)));
				compostQueue[index].done = -1;
			}

		void
			Restart();
		void
			DoWork();

		CompostQueueStruct*
			IsInQueue(int row, int column, int downSample);

		protected:
			int GetFirstFreeSpot();

			int firstInQueue;
			int lastInQueue;
			int flipAround;

			CompostQueueStruct compostQueue[Length_Of_Compost_Queue];
			CompostQueueStruct *compostQueuePointer[Length_Of_Compost_Queue];
			DWORD compostQueueTracker[Length_Of_Compost_Queue_Tracker];
	};

	class TerrainTextureLogistic
	{
		public:
			TerrainTextureLogistic(int, int, Scalar, Scalar, Stuff::MemoryStream*);
			TerrainTextureLogistic(int, int, Scalar, Scalar, Stuff::NotationFile*);
			TerrainTextureLogistic(int, int, Scalar, Scalar, const char*);
			~TerrainTextureLogistic();

			void
				Restart();

			void
				AttachZone(ElementRenderer::GridElement*, BYTE, BYTE);
			void
				DetachMeshes(int, int, int, int);

			void
				SetNewPosition(
					const Stuff::LinearMatrix4D *now,
					const Stuff::LinearMatrix4D *soon,
					const Stuff::LinearMatrix4D *later
				);

			static void
				SetResolution(int res) { MidLevelRenderer::terrainTextureResolution = res; }
			static int
				GetResolution() {return MidLevelRenderer::terrainTextureResolution;}

#ifdef LAB_ONLY
			static void
				TurnOnBorder(RGBAColor color) { borderColor = MidLevelRenderer::GOSCopyColor(&color); borderKey = true; }
			static void
				TurnOffBorder() { borderKey = false; }
#endif

			void
				NextUnusedTexture(int res, int lastUnused);
			void
				FreeUsedTexture(int res, int lastUsed);

			static TerrainTextureLogistic *Instance;

			//==================================================================================
			//	these 2 functions are for adding features during run-time
			//	the feature will be centered at x, z (x and z rounded to the next power of 4 !!!)
			//	index = MString.GetHashValue(), please use this function
			//	scale is the factor by what the feature gets stretched
			//==================================================================================
			bool
				AddFeature(const char *name, Scalar x, Scalar z, int scale=1) 
					{ return AddFeature(MString(name).GetHashValue(), x, z, scale); };
			bool
				AddFeature(int index, Scalar x, Scalar z, int scale=1);



			void
				SetOffset(Stuff::Scalar xo, Stuff::Scalar zo)
					{ x_offset = xo; z_offset = zo; }

			void
				TestInstance()
					{}

		protected:
			enum {
				DesiredResolution=0,
				CurrentResolution=1,
				Priority=2,
				DirtyFlag=3
			};

#ifdef LAB_ONLY
			static DWORD borderColor;
			static bool borderKey;
#endif

			int x_grid, z_grid;
			Stuff::Scalar x_grid_length, z_grid_length;
			Stuff::Scalar x_offset, z_offset;

			unsigned char nrOfAllocatedTexture[5], nrOfUsedTextures[5];
			unsigned char firstUnusedTexture[5];
			bool textureAvailable[5];

			Stuff::DynamicArrayOf<MidLevelRenderer::MLRTexture*> textures[5];
			Stuff::DynamicArrayOf<int> textureFlags[5];

			Stuff::DynamicArrayOf< Stuff::DynamicArrayOf<MidLevelRenderer::MLR_Terrain2*> > terrainMeshes;

			Stuff::DynamicArrayOf<BYTE> resolutionTracker[4];

			Stuff::DynamicArrayOf<TextureHolder> textureHolder[3];

			FeatureGrid *featureGrid;
			FeaturePool *featurePool;

			CompostQueue compostQueue;
	};

}