#include "OpenGLTextureMap.h"
#include "glext.h"
#include "FreeImage.h"

OpenGLTextureMap* OpenGLTextureMap::instance = NULL;

OpenGLTextureMap* OpenGLTextureMap::getInstance()
{
	if (instance == NULL)
		instance = new OpenGLTextureMap();
	return instance;
}

OpenGLTextureMap::OpenGLTextureMap()
{
}

OpenGLTextureMap::~OpenGLTextureMap()
{
	instance = NULL;
}

GLuint OpenGLTextureMap::GetTextureID(string strTextureName, string strTextureBasePath, bool bIgnorePath, bool bClamp)
{
	if (bIgnorePath)
	{
		size_t index = strTextureName.find_last_of("/\\");

		if (index != string::npos)
		{
			strTextureName = strTextureName.substr(index+1);
		}
	}

	string tmp = strTextureBasePath;
	strTextureName = tmp.append(strTextureName);

	if (!bClamp)
	{
		// busco la textura por si ya esta cargada
		map<string, GLuint>::iterator iter;
		iter = _oTexturesMapNoClamp.find(strTextureName);

		if(iter != _oTexturesMapNoClamp.end())
		{
			return iter->second;
		}
		else
		{
			//si no esta cargo la textura e inserto el ID
			GLuint idTextura= LoadTexture(strTextureName, bClamp);

			//si cargo correctamente => idTextura != 0
			if (idTextura != 0)
			{
				_oTexturesMapNoClamp.insert ( make_pair ( strTextureName, idTextura ) );
				return idTextura;
			}
			else
				return 0;
		}
	}
	else
	{
		// busco la textura a ver si ya esta cargada
		map<string, GLuint>::iterator iter;
		iter = _oTexturesMapClamp.find(strTextureName);

		if(iter != _oTexturesMapClamp.end())
		{
			return iter->second;
		}
		else
		{
			//si no esta cargo la textura e inserto el ID
			GLuint idTextura= LoadTexture(strTextureName, bClamp);

			//si cargo correctamente => idTextura != 0
			if (idTextura != 0)
			{
				_oTexturesMapClamp.insert ( make_pair ( strTextureName, idTextura ) );
				return idTextura;
			}
			else
				return 0;
		}
	}
}

GLuint OpenGLTextureMap::LoadTexture(string strTextureName, bool bClamp)
{
	FREE_IMAGE_FORMAT formato = FreeImage_GetFileType(strTextureName.c_str(),0); // Detecta automaticamente el formato
	FIBITMAP* imagen = FreeImage_Load(formato, strTextureName.c_str());
	
	FIBITMAP* temp = imagen;
	imagen = FreeImage_ConvertTo32Bits(imagen);
	FreeImage_Unload(temp);
	
	int w = FreeImage_GetWidth(imagen);
	int h = FreeImage_GetHeight(imagen);
	char* pixeles = (char*)FreeImage_GetBits(imagen);
	
	// FreeImage carga en BGR, entonces hay que usar GL_BGR.
	// Se genera la textura de opengl
	GLuint id;

	glGenTextures(1, &id);
	if (id != GL_INVALID_OPERATION && w != 0 && h != 0 )
	{
		glBindTexture(GL_TEXTURE_2D, id);
		glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

		glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
		glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

		
		if (bClamp)
		{
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		
		}
		else
		{
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
		}

		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA, w, h, 0, GL_BGRA_EXT,GL_UNSIGNED_BYTE,(GLvoid*)pixeles );

		FreeImage_Unload(imagen);

		return id;
	}
	else
	{
		return 0;
	}
}
