///////////////////////////////////////////////////////////////////////////////
/// @file deVBuffer_priv.hpp
///
/// @brief Private vertex buffer implementation header
///
/// @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 May 2002
/// @author Assassin
/// @remarks Creation
///
///////////////////////////////////////////////////////////////////////////////

#ifndef DEVBUFFER_PRIV_HPP
#define DEVBUFFER_PRIV_HPP

#include "deList.hpp"
#include "deDriver.hpp"

class deVertexBuffer;
class deSubVertexBuffer;

long IdeVertexBuffer_EntrySize(IdeVertexBuffer::BufferType Type);
IdeVertexBuffer::BufferDataType IdeVertexBuffer_FillBufferDataType(IdeVertexBuffer::BufferType Type, long *Size);

typedef struct DriverBufferEntry
{
	long ID;				//id of the driver
	long UpdateList;		//list of buffers that have changed since the last update
	void *Buffer;			//a pointer to data the driver wants to store
	IdeDriver * Driver;		// a pointer to the driver so that the buffer can be properly freed
} DriverBufferEntry;

class deVertexBuffer : public IdeVertexBuffer, public deRefCountBase
{
	//constructor and destructor
protected:
	~deVertexBuffer();
public:
	deVertexBuffer();

	//copy constructors
	deVertexBuffer(const IdeVertexBuffer &S);
	const IdeVertexBuffer& operator=(const IdeVertexBuffer &S);

	//buffer information
	void *GetBuffer(BufferType Type) const;

	//vertex information
	long GetVertexCount() const;
	long GetVertexStart() const;

	//index information
	long GetIndexCount() const;
	long GetIndexStart() const;

	//tri information
	long GetTriCount() const;
	deBoolean CalcTriCount();

	//static/dynamic information
	deBoolean GetDynamicStatusVertex() const;
	deBoolean GetDynamicStatusIndex() const;
	void SetDynamicStatus(deBoolean Vertex, deBoolean Index);

	//type of rendering we are doing
	RenderType GetRenderType() const;
	deBoolean SetRenderType(RenderType Type);

	//buffer functions
	deBoolean SetBufferSize(long EntryCount, deBoolean IndicesNotVertices = deFALSE);
	deBoolean CreateBuffer(BufferType Type, deBoolean Clear);
	deBoolean DestroyBuffer(BufferType Type);
	deBoolean FillBuffer(BufferType Type, const void *Buffer, long StartEntry, long EntryCount);
	void DirtyBuffer(BufferType Type);
	void DirtyBuffer(BufferType Type, deSubVertexBuffer* SubVBCaller);
	deBoolean BufferExists(BufferType Type) const;

	//for doing separate index and data buffers
	deBoolean BindDataBuffer(IdeVertexBuffer* DataBuffer);
	IdeVertexBuffer* GetBoundDataBuffer() const;

	//a function to obtain the buffer data type
	BufferDataType GetBufferDataType(BufferType Type, long *Size) const;

	//lock/unlock functions
	deBoolean Lock();
	deBoolean Unlock();

	//functions for the driver class to tell the vertex class of info to store
	deBoolean SetDriverBuffer(long ID, void *Buffer, IdeDriver * Driver);
	void *GetDriverBuffer(long ID, long *BufferUpdateList) const;

	//functions that affect the shader function applied to this vertex buffer
	deBoolean AddVertexShader(void *ShaderData, long ShaderSize);
	void * GetVertexShader(long *ShaderSize) const;
	deBoolean DestroyVertexShader();

	VBufferType GetVBufferType() const;
	IdeVertexBuffer* GetParentBuffer() const;

	// vbuffer-only interface
public:
	deBoolean AddSubVBuffer(deSubVertexBuffer * SubVB);
	deBoolean RemoveSubVBuffer(deSubVertexBuffer * SubVB);
	deBoolean AllocateVertexSpace(deSubVertexBuffer* SubVB, long Length, long &StartVertex, deBoolean resize = deFALSE);
	deBoolean AllocateIndexSpace(deSubVertexBuffer* SubVB, long Length, long &StartIndex, deBoolean resize = deFALSE);

private:
	//private functions
	void CopyInternalData(const deVertexBuffer &SourceVertexBuffer);
	
	//lock info
	long	m_Locked;	//a flag to know if we are "locked" by someone else or not

	//buffer info
	IdeVertexBuffer*m_DataBuffer;					//optional pointer to buffer that holds data streams
	void *			m_Buffer[BUFFER_COUNT];			//array of pointers to buffers
	deBoolean		m_WantsBuffer[BUFFER_COUNT];	//which buffers are needed
	long			m_VertexCount;					//number of items per array
	long			m_IndexCount;
	long			m_TriCount;						//number of tris the buffer holds info about
	RenderType		m_RenderType;					//type of rendering to do
	deBoolean		m_DynamicVertex;
	deBoolean		m_DynamicIndex;

	//driver buffer information
	deTList <DriverBufferEntry>	m_DriverBuffer;		//info that drivers can store

	// items for keeping track of sub-vbuffers
	long			m_UnusedVertices;
	long			m_UnusedIndices;
	deBoolean		m_HasChildren;
	deTList <deSubVertexBuffer*> m_ChildBuffers;
	deTList <deSubVertexBuffer*> m_IndexUsers;
	deTList <deSubVertexBuffer*> m_VertexUsers;
};

class deSubVertexBuffer : public IdeVertexBuffer, public deRefCountBase
{
	//constructor and destructor
protected:
	~deSubVertexBuffer();
public:
	deSubVertexBuffer(deVertexBuffer * Composite);

	//copy constructors
	deSubVertexBuffer(const IdeVertexBuffer &S);
	const IdeVertexBuffer& operator=(const IdeVertexBuffer &S);

	//buffer information
	void *GetBuffer(BufferType Type) const;

	//vertex information
	long GetVertexCount() const;
	long GetVertexStart() const;

	//index information
	long GetIndexCount() const;
	long GetIndexStart() const;

	//tri information
	long GetTriCount() const;
	deBoolean CalcTriCount();

	//static/dynamic information
	deBoolean GetDynamicStatusVertex() const;
	deBoolean GetDynamicStatusIndex() const;
	void SetDynamicStatus(deBoolean Vertex, deBoolean Index);

	//type of rendering we are doing
	RenderType GetRenderType() const;
	deBoolean SetRenderType(RenderType Type);

	//buffer functions
	deBoolean SetBufferSize(long EntryCount, deBoolean IndicesNotVertices = deFALSE);
	deBoolean CreateBuffer(BufferType Type, deBoolean Clear);
	deBoolean DestroyBuffer(BufferType Type);
	deBoolean FillBuffer(BufferType Type, const void *Buffer, long StartEntry, long EntryCount);
	void DirtyBuffer(BufferType Type);
	deBoolean BufferExists(BufferType Type) const;

	//for doing separate index and data buffers
	deBoolean BindDataBuffer(IdeVertexBuffer* DataBuffer);
	IdeVertexBuffer* GetBoundDataBuffer() const;
	
	//a function to obtain the buffer data type
	BufferDataType GetBufferDataType(BufferType Type, long *Size) const;

	//lock/unlock functions
	deBoolean Lock();
	deBoolean Unlock();

	//functions for the driver class to tell the vertex class of info to store
	deBoolean SetDriverBuffer(long ID, void *Buffer, IdeDriver * Driver);
	void *GetDriverBuffer(long ID, long *BufferUpdateList) const;

	//functions that affect the shader function applied to this vertex buffer
	deBoolean AddVertexShader(void *ShaderData, long ShaderSize);
	void * GetVertexShader(long *ShaderSize) const;
	deBoolean DestroyVertexShader();

	VBufferType GetVBufferType() const;
	IdeVertexBuffer* GetParentBuffer() const;

	// vbuffer-only interface
public:
	void SetVertexStart(long Start);
	void SetIndexStart(long Start);
	void*GetVertexEntry();
	void*GetIndexEntry();
	void*GetListEntry();
	void SetVertexEntry(void* Entry);
	void SetIndexEntry(void* Entry);
	void SetListEntry(void* Entry);
	
private:
	//private functions
	void CopyInternalData(const deVertexBuffer &SourceVertexBuffer);
	
	//lock info
	long			m_Locked;	//a flag to know if we are "locked" by someone else or not

	//buffer info
	IdeVertexBuffer*m_DataBuffer;					//optional pointer to buffer that holds data streams
//	deBoolean		m_WantsBuffer[BUFFER_COUNT];	//which buffers are needed
	long			m_VertexCount;					//number of items per array
	long			m_IndexCount;
	long			m_TriCount;						//number of tris the buffer holds info about
	RenderType		m_RenderType;					//type of rendering to do

	//driver buffer information
	deTList <DriverBufferEntry>	m_DriverBuffer;		//info that drivers can store

	// real/sub-vbuffer linkage
	deVertexBuffer*	m_CompositeBuffer;
	long			m_CompositeVertexStart;
	long			m_CompositeIndexStart;
	void*			m_VertexEntry;
	void*			m_IndexEntry;
	void*			m_ListEntry;
};

#endif
