#include "texture.h"

atexture		*texture[MAX_TEXTURES];

atexturedata *loadTGA(char *filename)
{
	atexturedata *newaux;
	newaux=new atexturedata;
	LoadFileTGA(filename,&newaux->data,&newaux->sizeX,&newaux->sizeY,&newaux->type);
	//newaux->type=GL_RGBA;
	if (newaux->data!=NULL)//loaded
		return newaux;

	delete newaux;
	return NULL;
}


int fgetLittleShort (FILE *f)
{
	unsigned char	b1, b2;

	b1 = fgetc(f);
	b2 = fgetc(f);

	return (short)(b1 + b2*256);
}

int fgetLittleLong (FILE *f)
{
	unsigned char	b1, b2, b3, b4;

	b1 = fgetc(f);
	b2 = fgetc(f);
	b3 = fgetc(f);
	b4 = fgetc(f);

	return b1 + (b2<<8) + (b3<<16) + (b4<<24);
}



void LoadFileTGA(char *name, unsigned char **pixels, int *width, int *height,GLuint *rgb_type)
{
	int				columns, rows, numPixels;
	unsigned char			*pixbuf;
	int				row, column;
	FILE			*fin;
	unsigned char			*targa_rgba;
	TargaHeader		targa_header;

	fin = fopen (name, "rb");

	if (fin)
	{

	targa_header.id_length = fgetc(fin);
	targa_header.colormap_type = fgetc(fin);
	targa_header.image_type = fgetc(fin);
	
	targa_header.colormap_index = fgetLittleShort(fin);
	targa_header.colormap_length = fgetLittleShort(fin);
	targa_header.colormap_size = fgetc(fin);
	targa_header.x_origin = fgetLittleShort(fin);
	targa_header.y_origin = fgetLittleShort(fin);
	targa_header.width = fgetLittleShort(fin);
	targa_header.height = fgetLittleShort(fin);
	targa_header.pixel_size = fgetc(fin);
	targa_header.attributes = fgetc(fin);

	if (targa_header.image_type!=2 
		&& targa_header.image_type!=10)
	{
		console("LoadTGA: Only type 2 and 10 targa RGB images supported");
		return;
	}
	
	if (targa_header.colormap_type !=0 
		|| (targa_header.pixel_size!=32 && targa_header.pixel_size!=24))
	{
		console("LoadTGA: Only 32 or 24 bit images supported (no colormaps)");
		return;
	}
	
	columns = targa_header.width;
	rows = targa_header.height;
	numPixels = columns * rows;

	*rgb_type=GL_RGBA;
	//if (targa_header.pixel_size!=32)
	//	*rgb_type=GL_RGBA;
	
	if (width)
		*width = columns;
	if (height)
		*height = rows;
	targa_rgba = (unsigned char *) malloc(numPixels*4);
	*pixels = targa_rgba;

	if (targa_header.id_length != 0)
		fseek(fin, targa_header.id_length, SEEK_CUR);  // skip TARGA image comment
	
	if (targa_header.image_type==2) {  // Uncompressed, RGB images
		for(row=rows-1; row>=0; row--) {
			pixbuf = targa_rgba + row*columns*4;
			for(column=0; column<columns; column++) {
				unsigned char red,green,blue,alphabyte;
				switch (targa_header.pixel_size) {
					case 24:
#define BRIGHT_TEX 0
							blue = getc(fin);
							green = getc(fin);
							red = getc(fin);
							*pixbuf++ = red+BRIGHT_TEX;
							*pixbuf++ = green+BRIGHT_TEX;
							*pixbuf++ = blue+BRIGHT_TEX;
							*pixbuf++ = 255;
							break;
					case 32:
							blue = getc(fin);
							green = getc(fin);
							red = getc(fin);
							alphabyte = getc(fin);
							*pixbuf++ = red+BRIGHT_TEX;
							*pixbuf++ = green+BRIGHT_TEX;
							*pixbuf++ = blue+BRIGHT_TEX;
							*pixbuf++ = alphabyte;
							break;
				}
			}
		}
	}
	else if (targa_header.image_type==10) {   // Runlength encoded RGB images
		unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
		for(row=rows-1; row>=0; row--) {
			pixbuf = targa_rgba + row*columns*4;
			for(column=0; column<columns; ) {
				packetHeader=getc(fin);
				packetSize = 1 + (packetHeader & 0x7f);
				if (packetHeader & 0x80) {        // run-length packet
					switch (targa_header.pixel_size) {
						case 24:
								blue = getc(fin);
								green = getc(fin);
								red = getc(fin);
								alphabyte = 255;
								break;
						case 32:
								blue = getc(fin);
								green = getc(fin);
								red = getc(fin);
								alphabyte = getc(fin);
								break;
					}
	
					for(j=0;j<packetSize;j++) {
						*pixbuf++=red;
						*pixbuf++=green;
						*pixbuf++=blue;
						*pixbuf++=alphabyte;
						column++;
						if (column==columns) { // run spans across rows
							column=0;
							if (row>0)
								row--;
							else
								goto breakOut;
							pixbuf = targa_rgba + row*columns*4;
						}
					}
				}
				else {                            // non run-length packet
					for(j=0;j<packetSize;j++) {
						switch (targa_header.pixel_size) {
							case 24:
									blue = getc(fin);
									green = getc(fin);
									red = getc(fin);
									*pixbuf++ = red;
									*pixbuf++ = green;
									*pixbuf++ = blue;
									*pixbuf++ = 255;
									break;
							case 32:
									blue = getc(fin);
									green = getc(fin);
									red = getc(fin);
									alphabyte = getc(fin);
									*pixbuf++ = red;
									*pixbuf++ = green;
									*pixbuf++ = blue;
									*pixbuf++ = alphabyte;
									break;
						}
						column++;
						if (column==columns) { // pixel packet run spans across rows
							column=0;
							if (row>0)
								row--;
							else
								goto breakOut;
							pixbuf = targa_rgba + row*columns*4;
						}						
					}
				}
			}
			breakOut:;
		}
	}
	
	fclose(fin);
	}
}


/*

atexturedata *loadTGA(char *filename)
{
	GLubyte		TGAheader[12]={0,0,2,0,0,0,0,0,0,0,0,0};		// Uncompressed TGA Header
	GLubyte		TGAcompare[12];						// Used To Compare TGA Header
	GLubyte		header[6];						// First 6 Useful Bytes From The Header
	GLuint		bytesPerPixel;						// Holds Number Of Bytes Per Pixel Used In The TGA File
	GLuint		imageSize;						// Used To Store The Image Size When Setting Aside Ram
	GLuint		temp;							// Temporary Variable

	FILE *file = fopen(filename, "rb");					// Open The TGA File

	if (file==NULL)
	{
		console("file %s wasnt opened",filename);
		return NULL;
	}

	if(	fread(TGAcompare,1,sizeof(TGAcompare),file)!=sizeof(TGAcompare) ||	// Are There 12 Bytes To Read?
		memcmp(TGAheader,TGAcompare,sizeof(TGAheader))!=0 ||		// Does The Header Match What We Want?
		fread(header,1,sizeof(header),file)!=sizeof(header))		// If So Read Next 6 Header Bytes
	{
		console("bad type %s",filename);
		fclose(file);						// If Anything Failed, Close The File
		return NULL;						// Return False
	}


	atexturedata *newaux;
	newaux=new atexturedata;

	newaux->sizeX=header[1] * 256 + header[0];
	newaux->sizeY=header[1] * 256 + header[0];
//	texture->width  = header[1] * 256 + header[0];				// Determine The TGA Width	(highbyte*256+lowbyte)
//	texture->height = header[3] * 256 + header[2];				// Determine The TGA Height	(highbyte*256+lowbyte)
    
 	if(	newaux->sizeX	<=0 ||						// Is The Width Less Than Or Equal To Zero
		newaux->sizeY	<=0 ||						// Is The Height Less Than Or Equal To Zero
		(header[4]!=24 && header[4]!=32))				// Is The TGA 24 or 32 Bit?
	{
		console("bad header...");
		fclose(file);							// If Anything Failed, Close The File
		free(newaux);
		return NULL;							// Return False
	}

	int bpp;

	bpp	= header[4];						// Grab The TGA's Bits Per Pixel (24 or 32)
	bytesPerPixel	= bpp/8;					// Divide By 8 To Get The Bytes Per Pixel
	imageSize		= newaux->sizeX*newaux->sizeY*bytesPerPixel;	// Calculate The Memory Required For The TGA Data

	newaux->data=(GLubyte *)malloc(imageSize);			// Reserve Memory To Hold The TGA Data

	if(	newaux->data==NULL ||					// Does The Storage Memory Exist?
		fread(newaux->data, 1, imageSize, file)!=imageSize)	// Does The Image Size Match The Memory Reserved?
	{
		if(newaux->data!=NULL)					// Was Image Data Loaded
			free(newaux->data);				// If So, Release The Image Data

		console("mem problem");

		fclose(file);
		free(newaux);
		return NULL;
	}

	for(GLuint i=0; i<int(imageSize); i+=bytesPerPixel)			// Loop Through The Image Data
	{									// Swaps The 1st And 3rd Bytes ('R'ed and 'B'lue)
		temp=newaux->data[i];					// Temporarily Store The Value At Image Data 'i'
		newaux->data[i] = newaux->data[i + 2];		// Set The 1st Byte To The Value Of The 3rd Byte
		newaux->data[i + 2] = temp;				// Set The 3rd Byte To The Value In 'temp' (1st Byte Value)
	}

	fclose (file);								// Close The File

	if (bpp==24)							// Was The TGA 24 Bits
		newaux->type=GL_RGB;							// If So Set The 'type' To GL_RGB
	else
		newaux->type=GL_RGBA;							// If So Set The 'type' To GL_RGB

	return newaux;

}
*/

atexturedata *loadtexturefromfile(char *filename)
{
	atexturedata *textureimage=0;

	textureimage=loadTGA(filename);

	if (textureimage==NULL)
		console("[tga] texture %s not loaded",filename);
	else
		console("texture %s loaded",filename);


	return textureimage;
}


int loadtex(atexture *thistexture)
{

	if (thistexture==NULL) 
	{
		console("^1texture is null");
		return false;
	}

//	if (strlen(thistexture->filename)<1||strlen(thistexture->name)<1) return false;

	//return true;
	atexturedata *textureimage;

	textureimage=loadtexturefromfile(thistexture->filename);
	if (textureimage==NULL)
	{
		console("^1unable to load file %s",thistexture->filename);
		return false;
	}

	glGenTextures(1,&thistexture->data);

	glBindTexture(GL_TEXTURE_2D, thistexture->data);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
//	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
//	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
	glTexImage2D(GL_TEXTURE_2D, 0, textureimage->type, textureimage->sizeX, textureimage->sizeY,0, textureimage->type, GL_UNSIGNED_BYTE, textureimage->data);

	glBindTexture(GL_TEXTURE_2D, 0);//0==texnull

	if (textureimage->data)
			free(textureimage->data);
	free(textureimage);

	console("loadtex() true");

	return true;
}


//---------texture has table routines
//1 <--- old entry
//2 <--- empty
int addtexture(char *texturename,char *filename)
{
	if (strlen(filename)==0) return false;
	if ((texture[0]!=NULL) && (texturename[0]==0||strlen(texturename)==0)) return false;

	
	//find empty spot
	byte n,home,i,place;
	n=texturename[0]; //first char represents place
	home=n%MAX_TEXTURES; //home is remainder from 256
	i=home;
	//while not empty & not gone through all &
//	while (texture[i]->name[0]>2 && i!=home-1 && strcmp(texture[i]->name,texturename)!=0)

	
	while (texture[i]!=NULL && i!=home-1)
	{
		if (texture[i]!=NULL)
		{
			if (strcmp(texture[i]->name,texturename)==0)
				return true;//texture exists, no problem
			if (texture[i]->name[0]==1||texture[i]->name[0]==2)
				break;//found match space
		}
		
		i++;
		if (i==MAX_TEXTURES)
			i=0;
	}
	if (i==home-1)
		return false;//looped through all entries, no spaces


	//must have a space!
	place=i;
	if (texture[place]==NULL)
		texture[place]=new atexture;
	
	strcpy(texture[place]->name,texturename);	//fill name
	strcpy(texture[place]->filename,filename);	//fill name
	
	texture[place]->linear=1;

	
//fill with texture
	return (loadtex(texture[place]));
	

}



int findtexture(char *texturename,int *position) //linear/nearest
{
	if (strlen(texturename)<2) return false;

	byte n,home,i;
	n=texturename[0]; //first char represents place
	home=n%MAX_TEXTURES; //home is remainder from 256
	i=home;
	//while not *EMPTY PLACE* & not gone through all 
	if (texture[i]==NULL) return false;
	while (texture[i]->name[0]!=2 && i!=home-1)
	{
		if (strcmp(texturename,texture[i]->name)==0) //match!
			break;
		i++;
		if (i==MAX_TEXTURES)
			i=0;
		if (texture[i]==NULL) return false;

	}
	if (i==home-1)
		return false;//looped through all entries, no spaces
	if (texture[i]==NULL) return false;
	if (texture[i]->name[0]==2)
		return false; //not found
	//must have found!
	*position=i;
	return true;
}


int deletetexture(int position)
{
//	if (texture[position]!=NULL)
//		delete texture[position];
	if (texture[position]==NULL) return true;
	texture[position]->name[0]=1;
	texture[position]->filename[0]=0;
	return true;
}


int freetexture(int position)
{
	if (texture[position]!=NULL)
		delete texture[position];
	return true;
}

