#ifndef BUFFER_H
#define BUFFER_H
namespace fw
{
	class Buffer
	{
	public:	
		friend class GameResourcesManager;
		enum Type
		{
			File,
			GPU,
			Network,
			Zip
		};
		Buffer(Type type) :
			m_pBuffer(nullptr),
			m_iSize(0),
			m_sName(NONE),
			m_bEmpty(true),
			m_type(type),
			m_bDone(false)
		{
		}
		Buffer(Type type, char* pData) :
			Buffer(type)
		{
			if (pData != nullptr)
			{
				m_pBuffer = pData;
			}
		}
		virtual ~Buffer()
		{
			if (m_bDone)
			{
				SAFE_DELETE(m_pBuffer);
			}
		}
		void Delete()
		{
			SAFE_DELETE(m_pBuffer);
			SetEmpty(true);
		}
		bool IsDeleted()
		{
			return m_pBuffer == nullptr;
		}
		void SetName(const std::string& sName)
		{
			m_sName = sName;
		}
		char* GetBuffer()
		{
			return m_pBuffer;
		}
		const char* GetBuffer() const
		{
			return m_pBuffer;
		}
		fw::size_t32 GetSize()
		{
			return m_iSize;
		}
		void SetSize(fw::size_t32 iSize)
		{
			m_iSize = iSize;
		}
		std::string GetName() const
		{
			return m_sName;
		}
		bool operator== (const Buffer& f) const
		{
			bool resultat = (f.GetBuffer() == GetBuffer()) && (f.GetName() == GetName());
			return resultat;
		}
		bool IsEmpty() const
		{
			return m_bEmpty;
		}
		void Done()
		{
			m_bDone = true;
		}
	protected:
		char** AccessBuffer()
		{
			SetEmpty(false);
			return &m_pBuffer;
		}
		void SetBuffer(char* pBuffer)
		{
			m_pBuffer = pBuffer;
					
			if (pBuffer != nullptr)
			{
				SetEmpty(false);
			}
		}
		Buffer& Get()
		{
			return *this;
		}
	private:
		void SetEmpty(bool bEmpty)
		{
			m_bEmpty = bEmpty;
		}
	private:
		char* m_pBuffer;
		fw::size_t32 m_iSize;
		std::string m_sName;
		bool m_bEmpty;
		Type m_type;
		bool m_bDone;
	};
	class ChunkedBuffer : public Buffer
	{
	public:
		ChunkedBuffer(Type type) :
			Buffer(type)
		{
		}
		ChunkedBuffer(Type type, char* pData) :
			Buffer(type, pData)
		{
		}
		size_t32 GetChunkSize() const
		{
			return m_iChunkSize;
		}
		size_t32 GetElementsCount() const
		{
			return m_iElementsCount;
		}
	protected:
		void SetElementsCount(size_t32 iElementsCount)
		{
			m_iElementsCount = iElementsCount;
		}
		void SetChunkSize(size_t32 iChunkSize)
		{
			m_iChunkSize = iChunkSize;
		}
	private:
		size_t32 m_iChunkSize = 0;
		size_t32 m_iElementsCount = 0;
	};
	class FileBuffer : public Buffer
	{
	public:
		friend class FileSystemManager;
		FileBuffer() :
			Buffer(Buffer::Type::File)
		{
		}
		FileBuffer& Get()
		{
			return *this;
		}
	};
	class CursorFileBuffer : public FileBuffer
	{
	public:
		friend class GameResourcesManager;
		CursorFileBuffer()
		{
			m_iImageWidth = 0;
			m_iImageHeight = 0;
		}
		virtual ~CursorFileBuffer()
		{
		}
		size_t GetCursorWidth()
		{
			return m_iImageWidth;
		}
		size_t GetCursorHeight()
		{
			return m_iImageHeight;
		}
		CursorFileBuffer& Get()
		{
			return *this;
		}
	private:
		size_t32 m_iImageWidth;
		size_t32 m_iImageHeight;
	};
	class TextureFileBuffer : public FileBuffer
	{
	public:
		friend class GameResourcesManager;
		TextureFileBuffer()
		{
		}
		TextureFileBuffer& Get()
		{
			return *this;
		}
		
	private:
		size_t32 m_iImageWidth;
		size_t32 m_iImageHeight;
	};
	class ShaderFileBuffer : public FileBuffer
	{
	public:
		friend class GameResourcesManager;
		friend class D3DIncludeHandlerZIP;
		ShaderFileBuffer()
		{
		}
		ShaderFileBuffer& Get()
		{
			return *this;
		}
	};
	class MeshFileBuffer : public FileBuffer
	{
	public:
		friend class GameResourcesManager;
		MeshFileBuffer()
		{
		}
		MeshFileBuffer& Get()
		{
			return *this;
		}
	};
}
#endif