/*
	ZDataBufferBase.hpp
	Author: James Russell <jcrussell@762studios.com>
	Created: 3/20/2011

	Purpose: 

	The ZDataBufferBase class is meant to be used by implementations that are 
	required to handle threading and concurrency problems that are not solved by
	the graphics library.

	License:

	TODO
*/

#pragma once

#ifndef _ZDATABUFFERBASE_HPP
#define _ZDATABUFFERBASE_HPP

#include <ZRenderer/ZDataBuffer.hpp>

/*
Base class implementation for the Data Buffer.
*/
class ZDataBufferBase : public ZDataBuffer
{
protected:
	//Default Constructor
	ZDataBufferBase(ZDataBufferType _type, ZDataBufferUsage _usage, size_t _size);

	//Type of the Data Buffer
	ZDataBufferType Type;

	//Usage setting for the Data Buffer
	ZDataBufferUsage Usage;

	//Size (in bytes) of the Data Buffer
	size_t Size;

	//Array of DataBufferBlocks held by this DataBuffer
	ZArray<ZDataBufferBlock*> Blocks;

	//Array of DataBufferStreams held by this DataBuffer
	ZArray<ZDataBufferStream*> Streams;

	//Backing buffer, used to double-buffer the graphics device buffer
	void* MemBuffer;

	//Flag indicating this buffer was mapped or filled
	bool bIsDirty;

	//Gets the buffer data from graphics memory
	virtual void GetDeviceData(void* _buffer) = 0;

	//Gets the next block offset we should use from the subclass
	virtual size_t GetNextBlockOffset(size_t _size) = 0;

	//Resets the block offset to zero
	virtual void ResetBlockOffset() = 0;

public:
	//Destructor
	virtual ~ZDataBufferBase();

	/*
	public ZDataBufferBase::GetMemBufferResetDirty

	Gets the backing memory buffer for this device.  This will return
	NULL if the buffer has not been modified since the last call to
	this function, and in the case it has been modified, a call to this 
	resets the 'dirty' flag for the buffer.

	@return (void*) - the backing memory buffer, NULL if not modified
	@context (renderer)
	*/
	void* GetMemBufferResetDirty();

	//Subclass Implementation
	virtual const ZDataBufferBlock* DefineBlock(ZDataBufferBlockType _type,
												size_t _size
												);

	//Subclass Implementation
	virtual const ZDataBufferStream* DefineStream(ZDataBufferStreamType _type,
												  size_t _elemCount,
												  size_t _offset,
												  size_t _stride,
												  bool _normalize
												  );
	//Subclass Implementation
	virtual bool Fill(const void* _data, size_t _offset, size_t _byteCount);

	//Subclass Implementation
	virtual const ZDataBufferBlock* GetBlock(size_t index) { return Blocks[index]; }

	//Subclass Implementation
	virtual const ZDataBufferStream* GetStream(size_t index) { return Streams[index]; }

	//Subclass Implementation
	virtual size_t GetBlockCount() const { return Blocks.Size(); }

	//Subclass Implementation
	virtual size_t GetStreamCount() const { return Streams.Size(); }

	//Subclass Implementation
	virtual size_t GetSize();

	//Subclass Implementation
	virtual ZDataBufferType GetType();

	//Subclass Implementation
	virtual ZDataBufferUsage GetUsage();

	//Subclass Implementation
	virtual void* Map( bool _discard = false );

	//Subclass Implementation
	virtual void UndefBlocks();

	//Subclass Implementation
	virtual void UndefStreams();

	//Subclass Implementation
	virtual void Unmap();

};

#endif