///////////////////////////////////////////////////////////////////////////////
/// @file deRender_priv.hpp
///
/// @brief specialization of IdeRender
///
/// @author Assassin
///
/// This file is the intellectual property of Novus Delta, LLC.. Usage of the
/// contents of this file is subject to the Destiny3D Member License which
/// can be found at http://www.destiny3d.com.  Any other usage is prohibited.
///
/// This file is distributed "AS IS" without warranty of any kind.  Novus
/// Delta, LLC. does not guarantee the fitness of the contents of this file
/// for any particular purpose.
///
/// Copyright (C) 2001-2003 Novus Delta, LLC. All Rights Reserved.
///
/// <hr>
///                                 Change History
/// <hr>
///
/// @date Feb 2002
/// @author Assassin
/// @remarks Initial Creation
///
///////////////////////////////////////////////////////////////////////////////

#ifndef DERENDER_PRIV_HPP
#define DERENDER_PRIV_HPP

#include "deBST.hpp"
#include "deRender.hpp"
#include "deString.hpp"
#include "deStack.hpp"
#include "deWorld.hpp"

#define DESTINY3D_FREEWARE
#define DESTINY3D_WATERMARK
#define MAX_LIGHTS_PER_PASS (8)

extern long RenderProfileID;

class IdeSceneGraph;

class deRender : public IdeRender
{
public:
	deRender(void);
	~deRender(void);

	friend IdeRender* IdeRender_GetPtr();
	friend deBoolean IdeRender_Initialize();
	friend void IdeRender_Destroy();
	friend void IdeRender_DestroyDriverLinkages();
		
	deBoolean SetRenderFlag(IdeRender::RenderFlag_t Flag);
	
	deBoolean SetStencilState(	IdeDriver * pDriver, StencilType_t Stencil, DWORD Ref, DWORD X = 0,
								IdeDriver::RenderCmpFunc Comparison = IdeDriver::COMPARE_ALWAYS,
								IdeDriver::RenderState StencilTest = IdeDriver::RENDER_STENCILPASS,
								DWORD StencilMask = 0xff, DWORD WriteMask = 0xff);
	
	// Renders the current world with the position and viewport of a camera
	// Specify BeginFrame=DE_TRUE for the first camera being rendered
	// Specify EndFrame=DE_TRUE for the last camera being rendered
	// If you only have one camera, both must be true
	deBoolean Render(IdeCamera * cam, deDouble DeltaTime, deBoolean UseSG, deBoolean ClearColorBuffer, deBoolean BeginFrame, deBoolean EndFrame);
	deBoolean RenderTexture(IdeBitmap * Target, IdeCamera * cam, deDouble DeltaTime);
	deBoolean BeginFrame(HWND WindowHandle, deBoolean ClearColorBuffer);
	deBoolean EndFrame(HWND WindowHandle, deDouble DeltaTime);

	void RenderPrepBuffer(deRenderObject & obj);
	IdeDriver * CurrentPassDriver();
	void RenderPrepBatch(long Level, IdePortal * Portal, deRect & Viewport, deTransformInfo * PortalPos, deTransformInfo * Concat);
	deDouble GetTimeStep();
	
	void SetDriverPath(const char * RelativePath);
	IdeDriverLoad* GetDriverLoad();
	// Attaches to an hWnd and forces a driver to be created for it
	IdeDriver * AttachToWindow(HWND hWnd, char * DriverName = "Direct3D8");
	deBoolean DetachFromWindow(HWND hWnd);
	void UpdateWindow(HWND hWnd);
	void UpdateDisplay();

	deBoolean LoadDriver(HWND hWnd, IdeDriver::deDisplay * Display, char * DriverName);
	deBoolean GetResolution(IdeDriver * pDriver, long Adapter, long EntryNum, long * Width, long * Height, long * RefreshRate);
	deBoolean QueryFormat(IdeDriver * pDriver, IdeDriver::deDisplay * Display, deBoolean PreferStencil);
	
	void SetBGColor(deARGB color);
	void SetMaxTPortalDepth(long Depth);
	void SetMaxLights(long MaxHWLights, long MaxTexLights);
	deBoolean ClearBackground(HWND hWnd, deARGB color = 0x00000000, deBoolean ClearZ = DE_TRUE);
	void EnableTexturing(deBoolean Enabled);

	deBoolean Use2DCollection(HWND hWnd, Ide2DCollection * Collection);
	Ide2DCollection * Get2DCollection(HWND hWnd);

	void SetStatStruct(deRenderStats * StatStruct);

	deBoolean Screenshot(HWND hWnd, const char* filename, long ScreenSizes);

	long GetFrameNum();

private:
	// internal functions
	deBoolean RenderWaterMark(IdeDriver* pDriver);
	static void DestroyDriverLinkages();
	IdeDriver * GetDriver(HWND hWnd);
	deBoolean InitDriver(IdeDriver * driver, HWND hWnd, IdeDriver::deDisplay * display, deBoolean ResetOnly);
	void SetInFrame(HWND hWnd, deBoolean InFrame);
	deBoolean IsInFrame(HWND hWnd, deBoolean ErrorVal);
	IdeDriver* SetupRenderTarget(IdeBitmap * Target, IdeCamera * cam);
	deBoolean SetSubViewport(IdeDriver * pDriver, IdeCamera * cam, deRect SubRect);
	deBoolean SetScissorRect(IdeDriver* pDriver, deRect ScissorRect);
	deBoolean RenderGeometry(IdeDriver * pDriver, IdeSceneGraph * SG, IdeCamera * c, deDouble DeltaTime, deBoolean ClearColorBuffer, deBoolean BeginFrame, deBoolean EndFrame);
	deBoolean CheckColorFormat(IdeDriver::BPP Bpp);
	deBoolean CheckDepthFormat(IdeDriver::ZPP Zpp, deBoolean Windowed);

	typedef deTBST <deRenderObject, 3> t_ObjectTree;
	struct deRenderBatch
	{
		t_ObjectTree ObjectTree;
		IdePortal * TPortal;
		deRect Viewport;
		long PortalLevel;
		deTransform Position;
		deTransform Concat;
	};
	
	struct deRenderPassInfo
	{
		IdeDriver*		pDriver;
		deRenderBatch*	pBatch;
		IdeCamera*		pCam;

		deBoolean		DepthWrite;
		deBoolean		ColorWrite;
	};
	
	struct DriverInfo
	{
		IdeDriver*			pDriver;
		deString			Name;
		HWND				DriverWindow;
		Ide2DCollection*	_2D;
		u32					FullWidth;
		u32					FullHeight;
		deBoolean			SettingMode;
		deBoolean			InFrame;
		deBoolean			DisplaySet;
//		deRenderFuncs		RenderFuncs;
	};

	struct deLightEntry_t
	{
		const deRenderObject*		Geometry;
		const IdeRenderLight*		Light;
		deBoolean					TexLight;
	};
	struct LightArray_t
	{
		deRenderObject* pRenderObject;
		char Active[MAX_LIGHTS_PER_PASS];
	};

	deBoolean RenderBatch(deRenderPassInfo* pInfo);

	IdeRenderTexture*	m_WaterMarkTex;
	IdeVertexBuffer*	m_WaterMarkVB;
	
	static deRenderStats s_RenderStats;
	static deRender *			s_deRenderSingleton;
	static IdeDriverLoad *		s_DriverLoad;
	static IdeRenderTexture *	s_BlankTex;
	static IdeRenderMaterial *	s_BlankMat;

	static deTArray <DriverInfo>		m_DriverList;
//	deTBST <deRenderObject, 2>			m_ValidObjects;
	deTList <deRenderBatch>				m_RenderBatches;
		
	deTStack<IdeDriver*>m_CurrentPassDriver;
	deDouble			m_CurrentTimeStep;
	deBoolean			m_TexturesEnabled;
	deBoolean			m_RenderMeshOverFill;
	deBoolean			m_RenderSolidWireframe;
	long				m_FillState;
	long				m_CullState;
	deARGB				m_BGColor;
	deRenderStats*		m_RenderStats;
	deString			m_DriverPath;
	long 				m_FrameNum;
	long				m_TPortalDepth;
	long				m_MaxHWLights;
	long				m_MaxTexLights;
	long				m_LightsEncountered;
	IdeRenderLight*		m_LightsPerPass[MAX_LIGHTS_PER_PASS];
	IdeRenderTexture*	m_PassTexture;
#if !defined(DESTINY3D_FREEWARE)
	deBoolean			m_EnableWaterMark;
	deBoolean			m_EnableWaterMarkFade;
#endif
};


#endif
