#pragma once

#include "dllinterface.h"
#include <d3d9.h>
#include <d3dx9.h>
#include "..\Utilities\util.h"
#include "..\Utilities\list.h"
#include "..\Utilities\XString.h"

class DeviceStateManager;
class TextureManager;

enum POOL 
{
    POOL_DEFAULT = 0,
    POOL_MANAGED = 1,
    POOL_SYSTEMMEM = 2
};

enum FORMAT
{
    FMT_UNKNOWN              =  0,

    FMT_R8G8B8               = 20,
    FMT_A8R8G8B8             = 21,
    FMT_X8R8G8B8             = 22,
    FMT_R5G6B5               = 23,
    FMT_X1R5G5B5             = 24,
    FMT_A1R5G5B5             = 25,
    FMT_A4R4G4B4             = 26,
    FMT_R3G3B2               = 27,
    FMT_A8                   = 28,
    FMT_A8R3G3B2             = 29,
    FMT_X4R4G4B4             = 30,
    FMT_A2B10G10R10          = 31,
    FMT_A8B8G8R8             = 32,
    FMT_X8B8G8R8             = 33,
    FMT_G16R16               = 34,
    FMT_A2R10G10B10          = 35,
    FMT_A16B16G16R16         = 36,

    FMT_A8P8                 = 40,
    FMT_P8                   = 41,

    FMT_L8                   = 50,
    FMT_A8L8                 = 51,
    FMT_A4L4                 = 52,

    FMT_V8U8                 = 60,
    FMT_L6V5U5               = 61,
    FMT_X8L8V8U8             = 62,
    FMT_Q8W8V8U8             = 63,
    FMT_V16U16               = 64,
    FMT_A2W10V10U10          = 67,

    FMT_D16_LOCKABLE         = 70,
    FMT_D32                  = 71,
    FMT_D15S1                = 73,
    FMT_D24S8                = 75,
    FMT_D24X8                = 77,
    FMT_D24X4S4              = 79,
    FMT_D16                  = 80,

    FMT_D32F_LOCKABLE        = 82,
    FMT_D24FS8               = 83,

    FMT_L16                  = 81,

    FMT_VERTEXDATA           =100,
    FMT_INDEX16              =101,
    FMT_INDEX32              =102,

    FMT_Q16W16V16U16         =110,

    FMT_R16F                 = 111,
    FMT_G16R16F              = 112,
    FMT_A16B16G16R16F        = 113,

    FMT_R32F                 = 114,
    FMT_G32R32F              = 115,
    FMT_A32B32G32R32F        = 116,

    FMT_CxV8U8               = 117
};

struct LOCKED_RECT
{
	int Pitch;
	void* pBits;

	int GetPointer(void) const {return (int)pBits;}
};

enum DXSURFACETYPE
{
	DXST_NONE = 0,
	DXST_TEXTURE,
	DXST_CUBETEXTURE,
	DXST_VOLUMETEXTURE
};

class DXFUNCTIONS_API DXSurface : public Ressource, protected DXRessource
{
protected:
	friend TextureManager;
	friend ListElement<DXSurface>;
	friend LList<DXSurface>;

	LPDIRECT3DBASETEXTURE9 m_pSurface;
	TextureManager* const m_pManager;

	const DXSURFACETYPE m_Type;

	unsigned	m_Usage;
	unsigned	m_MipLevels;
	FORMAT		m_Format;
	POOL		m_Pool;
	XString		m_strFileName;

	unsigned	m_MemoryUsage;

	DXSurface(TextureManager* const manager, const unsigned miplevels, const unsigned usage, const FORMAT format, const POOL pool, const XString& filename, const DXSURFACETYPE type);
	
	virtual ~DXSurface(void);
	
	void DoInvalidate(void);

	void UpdateMem(const unsigned xl, const unsigned yl, const unsigned zl);

public:
	LPDIRECT3DBASETEXTURE9 GetSurface(void) const { return m_pSurface; }
	TextureManager* GetManager(void) const { return m_pManager; }

	DXSURFACETYPE GetType(void) const { return m_Type; }

	unsigned GetLevels(void) const { return m_MipLevels; }
	unsigned GetUsage(void) const { return m_Usage; }
	FORMAT GetFormat(void) const { return m_Format; }
	POOL GetPool(void) const { return m_Pool; }
	XString GetFilename(void) const { return m_strFileName; }
};

class DXFUNCTIONS_API DXTexture : public DXSurface
{
	unsigned m_Xl;
	unsigned m_Yl;

	LOCKED_RECT m_LockedData;

protected:
	friend TextureManager;

	//the constructors
	DXTexture(TextureManager* const manager, const unsigned xl, const unsigned yl, const unsigned levels, const unsigned usage, const FORMAT format, const POOL pool);
	DXTexture(TextureManager* const manager, const XString& filename, const unsigned xl, unsigned yl, unsigned levels, unsigned usage,FORMAT format, const POOL pool);
	DXTexture(TextureManager* const manager, DXTexture* const tex, const unsigned xl, const unsigned yl, const unsigned levels, const unsigned usage, const FORMAT format, const POOL pool);
	~DXTexture(void) {}

	void DoRestore(void);

public:

	LPDIRECT3DTEXTURE9 GetTextureSurface(void) const { return (LPDIRECT3DTEXTURE9)m_pSurface; }

	unsigned GetXl(void) const { return m_Xl; }
	unsigned GetYl(void) const { return m_Yl; }
	
	const LOCKED_RECT* GetLockedData(void) const { if(m_LockedData.pBits) return &m_LockedData; else return NULL; }
	const LOCKED_RECT* Lock(void);
	void Unlock(void);
};

class DXFUNCTIONS_API DXCubeTexture : public DXSurface
{
	unsigned m_EdgeLength;

protected:
	friend TextureManager;

	DXCubeTexture(TextureManager* const manager, const unsigned edgelength, const unsigned levels, const unsigned usage, const FORMAT format, const POOL pool);
	DXCubeTexture(TextureManager* const manager, const XString& filename, const unsigned edgelength, const unsigned levels, const unsigned usage, const FORMAT format, const POOL pool);
	~DXCubeTexture(void) {}

	void DoRestore(void);

public:

	LPDIRECT3DCUBETEXTURE9 GetCubeTexture(void) const { return (LPDIRECT3DCUBETEXTURE9)m_pSurface; }

	unsigned GetEdgeLength(void) const { return m_EdgeLength; }
};

class DXFUNCTIONS_API DXVolumeTexture : public DXSurface
{
	unsigned m_XL;
	unsigned m_YL;
	unsigned m_ZL;

protected:
	friend TextureManager;

	//DXVolumeTexture();
	//~DXVolumeTexture(void) {}

	//void DoRestore(void);

public:

	LPDIRECT3DVOLUMETEXTURE9 GetVolumeTexture(void) const { return (LPDIRECT3DVOLUMETEXTURE9)m_pSurface; }

};