#pragma once

#include "..\DXFunctions\dllinterface.h"
#include "..\DXFunctions\quadtree.h"
#include "..\DXFunctions\dxmaterial.h"
#include "..\DXFunctions\shadermanager.h"
#include "..\DXFunctions\buffermanager.h"
#include "..\DXFunctions\RenderList.h"

#include "SceneObject.h"

class ShadowApp;
class Terrain;

struct STPatchVertex
{
	float x;
	float y;
	float height;
	D3DXFLOAT16 nx,ny;
	//DXVector3 n;
	//DWORD color;
};

class TerrainPatch : public SceneObject
{
	Terrain* m_Terrain;
	unsigned m_BX;
	unsigned m_BY;
	AABB	 m_AABB;
	//OBS		 m_OBS;
	float	 m_MinH;
	float	 m_MaxH;

	VertexBuffer* m_VB;

	RenderJobDrawCall m_DC;
	RenderJob m_RJ;
	RenderJob m_RJDS;
	RenderJob m_RJShadow;

	SHADERPARAMETER m_SMID;

	void InitVB(void);
	void BuildRenderJobs();

public :
	TerrainPatch(Terrain* const terrain, int bx, int by);
	~TerrainPatch(void);
	
	//void Render(const bool depthmap);
	//void Update(const float dt);
	//void UpdateShadow(void);

	void AddToRenderList(RenderList& rl);// { if(m_Terrain->m_App->UseDeferred()) rl.AddRJ(&m_RJDS); else rl.AddRJ(&m_RJ);}
	void AddToShadowRenderList(RenderList& rl) { rl.AddRJ(&m_RJShadow); }
	
	void OnRestoreIB(void);

	const OBS& GetOBS(void) const { return m_Bound; }
	const AABB& GetAABB(void) const { return m_AABB; }

	virtual void UpdateTechnique(void);
};

class Terrain : public DXRessource, SceneObject
{
	friend TerrainPatch;

	unsigned	m_TileShift;
	float		m_HeightScale;
	float		m_TileScale;
	int			m_HMSize;
	XString		m_HMFile;

	unsigned	m_HeightSamples;
	float*		m_HeightField;

	unsigned	m_PatchTile;
	unsigned	m_PatchCount;
	unsigned	m_PatchTiles;
	unsigned	m_PatchPrimitives;
	unsigned	m_PatchStride;
	unsigned	m_PatchHeightSamples;
	//float*		m_PatchMin;
	//float*		m_PatchMax;

	AABB		m_AABB;

	//D3DXHANDLE	m_hMatViewProj;
	//D3DXHANDLE	m_hMatWorld;
	//D3DXHANDLE	m_hLightDir;
	//D3DXHANDLE	m_hSunColor;
	//D3DXHANDLE	m_hAmbientColor;

	//Quadtree*	m_QT;
	//Quadtree*	m_QTShadow;

	TerrainPatch**	m_Patches;

	IndexBuffer*	m_IB;
	//VertexBuffer*	m_VB;
	VertexBuffer*	m_VBXY;
	//VertexBuffer**	m_VBPatch;
	VertexDeclaration* m_VDecl;
	ShaderEffect*	m_FXTerrain;	

	DXVector3 CalcNormal(int x, int y);
	void LoadHeightField(void);

	DXColor HeightToColor(const float z) const;

public:
	Terrain(ShadowScene* const pScene, const unsigned tileshift, const float heightscale, const float tilescale, const XString& hmfile, const int hmsize);
	~Terrain(void);

	//void Update(void);
	//void UpdateShadow(void);
	//void Render(const bool depthmap);

	TerrainPatch* GetPatch(const int x, const int y) const { return m_Patches[x + y * m_PatchTile]; }

	void DoRestore(void);

	float GetHeight(const float x, const float y);

	//Quadtree* GetQT(void) const {return m_QT;}
//	Quadtree* GetQTShadow(void) const {return m_QTShadow;}
	unsigned GetPatchTile(void) const { return m_PatchTile;}
	unsigned GetPatchStride(void) const {return m_PatchStride;}
	unsigned GetTileScale(void) const {return m_TileScale;}	

	const IBoundingVolume& GetBoundingVolume(void) const { return m_AABB; }
};
