// © Copyright 2008 Vladimir Frolov, Moscow State University Graphics & Media Lab
#pragma once

#ifndef __CUDACC__
	#include "MGML_ERROR.h"
#endif

#ifndef MGML_GUARDIAN
	#include "MGML.h"
#endif


#include <windows.h>
#include <glut.h>




/* размер заголовка BMP-файла */

#define BMP_SIZE_FILEHEADER 14 
#define NUM_OF_LISTS 8

/* размер информационного заголовка BMP-файла */
#define BMP_SIZE_INFOHEADER 40  
#define BMP_COLOR_BITS_24 24 


namespace IMAGES
{


typedef MGML_GRAPHICS::RGB256 RGB256;

// BAD-BAD CLASS!
//////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////      IMAGE        ////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////////////////////////
class IMAGE
{

public:
  IMAGE();
  ~IMAGE();

  unsigned int width()  const {return _width;} 
  unsigned int height() const {return _height;} 
  
  inline unsigned int* getBuffer() 
	{return (unsigned int*)data;}

  inline const unsigned int* getConstBuffer() const  
	{ return (unsigned int*)data; }

  inline unsigned int getPixel(int x,int y) const
  { 
		ASSERT(x>=0);
		ASSERT(y>=0);
		ASSERT((unsigned)x < width());
		ASSERT((unsigned)y < height());
		return getConstBuffer()[x+width()*y];
  }

  inline unsigned int getPixelWraped(int x,int y) const
  { 
		ASSERT(x>=0);
		ASSERT(y>=0);

		if((unsigned)x > width())
			x = x % width();

		if((unsigned)y > height())
			y = y % height();

		return getConstBuffer()[x+width()*y];
  }

  void setSize(unsigned int w,unsigned int h);  
  void CopyFromBuffer(const unsigned char* buff,unsigned int size);

  int         LoadBMP(const char* file);
  //#CHECK_THAT
  void        LoadToGPU();				  // Загрузить текстуру в видеокарту
  inline void SetAsActiveTexture() const; // Установить эту текстуру как активную.

  IMAGE& operator=(const IMAGE&);

protected:

    inline void	rgb_setPixel(unsigned int x,unsigned int y,RGB256 &clr);
    inline RGB256 rgb_getPixel(unsigned int x,unsigned int y) const;

	void convertToRGBA32();
	int ReadFileHeader(FILE* f, int* bitmap_pos);
	unsigned int uInt16Number(unsigned char buf[2]);
	unsigned int uInt32Number(unsigned char buf[4]);

	static int tosTexId;
	unsigned int _width;
	unsigned int _height;
	unsigned char* data;

	GLUquadricObj* QuadrObj;
	GLuint TexId;
	bool   first_load;
	std::string gfname;
 
};


};
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
//=================================================================
// 
//=================================================================
inline void IMAGES::IMAGE::rgb_setPixel(unsigned int x,unsigned int y,RGB256 &clr)
{   
 unsigned int a = 3*(x*_width + y);
 data[a]     = clr.M[0];
 data[a + 1] = clr.M[1];
 data[a + 2] = clr.M[2];
}

//=================================================================
//
//=================================================================
inline IMAGES::RGB256 IMAGES::IMAGE::rgb_getPixel(unsigned int x,unsigned int y) const
{
 RGB256 color;
 unsigned int a = 3*(x*_width + y);
 color.M[0] = data[a];
 color.M[1] = data[a+1];
 color.M[2] = data[a+2];
 return color;
}
//=================================================================
//
//=================================================================
inline void IMAGES::IMAGE::SetAsActiveTexture() const
{
  glBindTexture (GL_TEXTURE_2D,TexId);
}

