// __author__ = Juan Carlos De Abreu (jcabreur@gmail.com)

/**
 * TODO(jcabreur): write a general comment here
 */

#ifndef UTIL_TEXTURE_H__
#define UTIL_TEXTURE_H__

#include "../Includes/Opengl.h"
#include "../Includes/Basic.h"
#include "../Includes/FreeImage.h"
#include "../Base/Singleton.h"
#include "../Base/LogManagement.h"

#pragma comment(lib, "lib/FreeImage.lib")	// Search for FreeImage.lib while linking

BEGIN_TEG_NAMESPACE();

/*  NOTE: la primera texture que se cargue sera la utilizada por defecto para cuando no se
 *        logre cargar una textura y tener un indicativo visual de que algo fallo, esta textura
 *        deberia ser algo como una cuadricula de diferentes colores ...
 *        tal vez tambien deba tener un metodo init el cual se encargara de cargar esta textura..
 *        y ademas la textura tambien la podria generar por codigo, para mo tener una dependencia con
 *        otro archivo ...
 */ 

// TODO: definir en un namespace

// TODO: deberia tener un map con los nombres de las texturas cargadas para qeu cuando manden a cargar 
// una textura que ya esta cargada simplemente se busca en el map y se retorna su identificador..

//
#define LOAD_TEXTURE(path) TextureManagement::GetInstance().load(path)

// Definition of the structure of Texture Management
class TextureManagement : public Singleton<TextureManagement> {
protected:
  // Attributes.
  int m_iMode;									// Texture environment parameter
  int m_iMethod;								// Method to use in the generation of texture coordinate
  int m_iQuality;								// Filter to use by the texture
  int m_iOptionS;								// Wrap parameter of the coordinate s
  int m_iOptionT;								// Wrap parameter of the coordinate t
  int m_iOptionR;								// Wrap parameter of the coordinate r
  bool m_bSupport[14];							// Extensions supported by the hardware
  std::map<std::tstring, GLuint> vTextureNames; // Id of the texture names

  // Definition of the enum of filter textures
  enum TextureFilterEnum {
      FILTER_LINEAR = 1,
      FILTER_BILINEARR,
      FILTER_TRILINEAR,
      FILTER_ANISOTROPY_2X,
      FILTER_ANISOTROPY_4X,
      FILTER_ANISOTROPY_8X,
      FILTER_ANISOTROPY_16X,
      FILTER_ANISOTROPY_MAX
  };

  // Definition of the enum of mode textures
  enum TextureModeEnum {
      MODE_DECAL = 1,
      MODE_MODULATE,
      MODE_BLEND,
      MODE_COMBINE,
      MODE_REPLACE
  };

  // Definition of the enum of option textures 
  enum TextureOptionEnum {
      OPTION_CLAMP = 1,
      OPTION_REPEAT,
      OPTION_CLAMP_TO_EDGE,
      OPTION_CLAMP_TO_BORDER
  };

  // Definition of the enum of mapping texture
  enum TextureMapEnum {
      EYE_LINEAR = 1,
      OBJECT_LINEAR,
      SPHERE_MAP,
      SPHERE_NORMAL,
      SPHERE_CENTROIDE,
      CUBICO_NORMAL,
      CUBICO_CENTROIDE,
      PLANAR
  };

  // Definition of the enum of extension texture supported by hardware
  enum TextureExtensionEnum {
      MULTITEXTURE = 1,
      TEXTURE_FLOAT,
      TEXTURE_ENV_ADD,
      TEXTURE_CUBE_MAP,
      TEXTURE_ENV_DOT3,
      TEXTURE_RECTANGLE,
      TEXTURE_COMPRESSION,
      TEXTURE_ENV_COMBINE,
      TEXTURE_BORDER_CLAMP,
      TEXTURE_ENV_CROSSBAR,
      TEXTURE_MIRRORED_REPEAT,
      TEXTURE_NON_POWER_OF_TWO
  };

public:
  // Standard TextureManagement constructor.
  TextureManagement();

  // TextureManagement destructor.
  ~TextureManagement();

  // Methods.
  void setMode();							// Method to set the texture environment mode parameter
  void setMethod();							// Method to set generation of texture coordinates
  void setQuality();						// Method to set the filter to use by the texture				
  void setOptionS();						// Method to set wrap parameter of the coordinate s
  void setOptionT();						// Method to set wrap parameter of the coordinate t
  void setOptionR();						// Method to set wrap parameter of the coordinate r
  GLfloat maxQuality();						// Method to obtain the max quality supported by the hardware
  void extensionSupported();				// Method to check the extensions suppoted by the hardware
  GLuint load(const char* lpszPathName);	// Method to load a image of any format

  void set_option(int option);
  // TODO: method to unload a texture
  // TODO: add a method to set the propierties of the texture
};

END_TEG_NAMESPACE();

#endif  // UTIL_TEXTURE_H__
