#ifndef __NV_DDS_H__
#define __NV_DDS_H__

#include <string>
#include <vector>

using namespace std;

#define DDS_FOURCC 0x00000004
#define DDS_RGB    0x00000040
#define DDS_RGBA   0x00000041

#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT  0x83F1
#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT  0x83F2
#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT  0x83F3

#define GL_BGR_EXT  0x80E0
#define GL_BGRA_EXT 0x80E1

#define FOURCC_DXT1 0x31545844 //(MAKEFOURCC('D','X','T','1'))
#define FOURCC_DXT3 0x33545844 //(MAKEFOURCC('D','X','T','3'))
#define FOURCC_DXT5 0x35545844 //(MAKEFOURCC('D','X','T','5'))

#define DDS_CUBEMAP_POSITIVEX 0x00000600 
#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 
#define DDS_CUBEMAP_POSITIVEY 0x00001200 
#define DDS_CUBEMAP_NEGATIVEY 0x00002200 
#define DDS_CUBEMAP_POSITIVEZ 0x00004200 
#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 

#define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\
                               DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\
                               DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ )

struct DDS_PIXELFORMAT
{
    unsigned long dwSize;
    unsigned long dwFlags;
    unsigned long dwFourCC;
    unsigned long dwRGBBitCount;
    unsigned long dwRBitMask;
    unsigned long dwGBitMask;
    unsigned long dwBBitMask;
    unsigned long dwABitMask;
};

struct DXTColBlock
{
	unsigned short col0;
	unsigned short col1;

	unsigned char row[4];
};

struct DXTAlphaBlock
{
	unsigned short row[4];
};

struct DDS_HEADER
{
    unsigned long dwSize;
    unsigned long dwHeaderFlags;
    unsigned long dwHeight;
    unsigned long dwWidth;
    unsigned long dwPitchOrLinearSize;
    unsigned long dwDepth;
    unsigned long dwMipMapCount;
    unsigned long dwReserved1[11];
    DDS_PIXELFORMAT ddspf;
    unsigned long dwSurfaceFlags;
    unsigned long dwCubemapFlags;
    unsigned long dwReserved2[3];
};

class CSurface
{
    public:
        CSurface();
        CSurface(int w, int h, int imgsize);
        CSurface(const CSurface &copy);
        CSurface &operator= (const CSurface &rhs);
        ~CSurface();

        operator char*(void);

        void create(int w, int h, int imgsize);
        void clear();

        int width;
        int height;
        int size;
    private:
        char *pixels;       
};

class CImage
{
    public:
        CImage();
        CImage(int w, int h, int imgSize);
        CImage(const CImage &copy);
        ~CImage();

        operator char*(void);

        int width;
        int height;
        int size;
        vector<CSurface> mipmaps;
    private:
        CSurface image;
};

class CDDSImage
{
	public:
		CDDSImage();
		~CDDSImage();

        void clear();
        CImage &operator[](int i);
        bool load(string filename);

        int components;
        bool compressed;
        bool cubemap;
		int format;
        
    private:
        void flip(char *image, int width, int height, int size);
        int size_dxtc(int width, int height);
        int size_rgb(int width, int height);
        vector<CImage> images;
};

#endif
