#include <stdio.h>
#include "../headers/Input.h"
#include "../headers/GeTexture.h"
#include "../headers/targa.h"
#include "../headers/Settings.h"

map<string, GeTexture*> GeTexture :: textureMap;

GeTexture* GeTexture :: getTexture(const char* filename) {
	GeTexture* ret = NULL;
	string file(filename);

	if(textureMap.count(file) > 0) {
		ret = textureMap[file];
	}
	else {
		ret = new GeTexture(filename);
		if (!ret->valid) {
			delete(ret);
			ret = NULL;
		}
		else {
			textureMap[file] = ret;
		}
	}
	return ret;
}

void GeTexture :: freeTextures(void) {
	map<string, GeTexture*>::iterator i;
	for (i = textureMap.begin(); i != textureMap.end(); i++) {
		delete i->second;
	}
}


GeTexture :: GeTexture(const char* filename) {
	tga_image lTGAImage;
	textureid = 0;
	tga_result result = tga_read(&lTGAImage, filename);
	width = 0;
	height = 0;
	valid = false;
	highQuality = (settings.flags & FLAG_TEXTUREQUALITY_HIGH) != 0;
	mipmapQuality = settings.mipmapMode;
	
	if (result == TGA_NOERR)
	{
		// Make sure the image is left to right
		if (tga_is_right_to_left(&lTGAImage)) tga_flip_horiz(&lTGAImage);

		// Make sure the image is bottom to top
		if (tga_is_top_to_bottom(&lTGAImage)) tga_flip_vert(&lTGAImage);

		// Make the image BGR 24
		tga_convert_depth(&lTGAImage, 24);
		
		width = lTGAImage.width;
		height = lTGAImage.height;
		
		glGenTextures(1, &textureid);
		glBindTexture(GL_TEXTURE_2D, textureid);

		GLuint mode = getMode();
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mode);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mode);
		gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, GL_BGR_EXT, GL_UNSIGNED_BYTE, lTGAImage.image_data);

		tga_free_buffers(&lTGAImage);
		valid = true;
	}
	else {
		printf("Unable to load Texture %s: %s\n", filename, tga_error(result));
	}
}

GeTexture :: ~GeTexture() {
}
	
void GeTexture :: bind(void) {
	bool newQuality = (settings.flags & FLAG_TEXTUREQUALITY_HIGH) != 0;

	glBindTexture(GL_TEXTURE_2D, textureid);
	if ((highQuality != newQuality) ||
		(mipmapQuality != settings.mipmapMode)) {
		highQuality = newQuality;
		mipmapQuality = settings.mipmapMode;
		
		GLuint mode = getMode();
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mode);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mode);
	}
}
	
GLuint GeTexture :: getMode(void) {
	GLuint mode = 0;
	switch (mipmapQuality) {
		case MIPMAP_MODE_OFF: // Off
			mode = highQuality?GL_LINEAR:GL_NEAREST;
		break;
		
		case MIPMAP_MODE_LIN: // linear
			mode = highQuality?GL_LINEAR_MIPMAP_LINEAR:GL_NEAREST_MIPMAP_LINEAR;
		break;
		
		case MIPMAP_MODE_NN: // nearest neighbour
		default:
			mode = highQuality?GL_LINEAR_MIPMAP_NEAREST:GL_NEAREST_MIPMAP_NEAREST;
		break;
	}
	return mode;
}

unsigned int GeTexture :: getWidth(void) {
	return width;
}

unsigned int GeTexture :: getHeight(void) {
	return height;
}



