/* -----------------------------------------------------------------------------
*
*  nptexmap.c
*
*  ANTz - realtime 3D data visualization tools for the real-world, based on NPE.
*
*  ANTz is hosted at http://openantz.com and NPE at http://neuralphysics.org
*
*  Written in 2010-2016 by Shane Saxon - saxon@openantz.com
*
*  Please see main.c for a complete list of additional code contributors.
*
*  To the extent possible under law, the author(s) have dedicated all copyright 
*  and related and neighboring rights to this software to the public domain
*  worldwide. This software is distributed without any warranty.
*
*  Released under the CC0 license, which is GPL compatible.
*
*  You should have received a copy of the CC0 Public Domain Dedication along
*  with this software (license file named LICENSE.txt). If not, see
*  http://creativecommons.org/publicdomain/zero/1.0/
*
* --------------------------------------------------------------------------- */

#include "nptexmap.h"

#include "../../npdata.h"
#include "../../os/npos.h"
#include "../npglut.h"
#include "../../data/npmapfile.h"
#include "../file/npfreeimage.h"	// needs to be after other includes
#include "../npfile.h"

#include "SOIL.h"					// used for DDS files and screengrab


///@todo: npTex
pNPtexmap npTex(int action, int* texId, char* file, char* path, void* dataRef)
{
	pNPtexmap tex = NULL;

	if(action == kNPtexlistAddFile)
	{
		tex = npTexlistAddFile(file, path, (*texId), dataRef);
		return tex;
	}

	if(action == kNPextTexIdUnused)
	{
		(*texId) = npGetUnusedExtTexId(dataRef);
		return tex;
	}

	if(action == kNPinitTexMap)
	{
		npInitTexMap(dataRef);	
		return NULL;
	}

	if(action == kNPtexMapIDext)
	{
		(*texId) = npTexMapIDext((*texId), dataRef);
		return NULL;
	}

	if(action == kNPtexMapIDint)
	{
		(*texId) = npTexMapIDint((*texId), dataRef);
		return NULL;
	}

	if(action == kNPtexMapIDis)
	{
		tex = npTexMapIDis((*texId), dataRef);
		return tex;
	}

	if(action == kNPtexMapIDload)
	{
		
	}

	if(action == kNPtexlistSearchFile)
	{
		tex = npTexlistSearchFile(file, path, dataRef);
		return tex;
	}

	if(action == kNPtexMapGet)
	{
		tex = npTexMapGet((*texId), dataRef);
		return tex;
	}

	return tex;
}

void npLoadTexturesLegacy(void* dataRef);
void npLoadTexturesLegacy(void* dataRef) 
{
	int i = 0;
	int result = 0;
	int fileType = 0;
	int textureSize = 0;
	int fileNumber = 1;

	pNPfileRef fRef = NULL;

	char* filename = (char*)malloc(4096);

	unsigned int textureID;		//zz debug, allow loading textures at runtime
									//detect changes to data->io.file.mapPath
	pData data = (pData) dataRef;


	glGetIntegerv (GL_MAX_TEXTURE_SIZE, &textureSize);
	data->io.gl.maxTextureSize = textureSize;
	printf ("\nMax Texture Size: %dx%d\n", textureSize, textureSize);
	printf ("Loading Textures...\n");
	//	printf ("Larger textures down converted\n", textureSize);

	fRef = nposNewFileRef( data );

	/// Legacy support where we first load map*.jpg files then all others
	result = nposFindFirstFile( fRef, "usr/images/", "map*.jpg", data );
	if( result != 1 )
		return;		// err or empty folder

	do
    {
		i++;

		// print a few of the filenames then dots for every 100 files
		if( i <= 5 )
			printf( "%.70s\n", fRef->name );
		else if( i < 100 || i % 100 == 0 )
			printf( "." );

		sprintf(filename, "%s%s/%s", data->io.file.appPath ,"usr/images/", fRef->name );

		// if Folder (not a file) then recursively call to create dir tree
		if( fRef->isDir )
		{
		//	npLoadTextures( sPath, data );			// recursion
		}
		else
			textureID = npLoadTexture( filename, 0, data );
    }
	while( nposFindNextFile( fRef ) );	// next file within limits

	/// Now we load all other textures
	result = nposFindFirstFile( fRef, "usr/images/", "*.*", data );
	if( result != 1 )
		return;		// err or empty folder

	do
    {
		// handle legacy support by skipping the ones we just laoded
		if( strncmp(fRef->name, "map", 3) == 0
			&& npGetFileTypeCat(NULL, fRef->name, data) == kNPfileJPG )
			continue;

		i++;

		// append current file/dir item to the basePath (parent dir)
 //       sprintf(sPath, "%s/%s", basePath, fRef->fdFile.cFileName);

		// print a few of the filenames then dots for every 100 files
		if( i <= 5 )
			printf( "%.70s\n", fRef->name );
		else if(  i < 100 || i % 100 == 0 )
			printf( "." );

		sprintf(filename, "%s%s/%s", data->io.file.appPath ,"usr/images/", fRef->name );

		// if Folder (not a file) then recursively call to create dir tree
		if( fRef->isDir )
		{
		//	npLoadTextures( sPath, data );			// recursion
		}
		else
			textureID = npLoadTexture( filename, 0, data );
    }
	while( nposFindNextFile( fRef ) );	// next file within limits

    nposFindClose( fRef, data );		// always clean up!

	if( data->io.gl.textureCount )
		printf ("\nDone Loading Textures\n\n");
	else
		printf ("No Textures Found!!!\n\n");
}

//------------------------------------------------------------------------------
#define kNPtexListMax 2000
void npInitTexMap (void* dataRef)
{
	pData data = (pData) dataRef;
	pNPtexmap texmap = NULL;
	int i = 0;

	data->io.gl.loadExtTexs = 0;
	data->io.gl.texmapCount = 0;

	for(i = 0; i < kNPtexListMax; i++)
	{
		texmap = &data->io.gl.texmap[i];
		texmap->loaded = 0;
		texmap->path[0] = '\0';
		texmap->filename[0] = '\0';
		texmap->filePath[0] = '\0';
		texmap->channels = 0;
		texmap->height = 0;
		texmap->width = 0;
		texmap->image = NULL;
		texmap->extTexId = 0;
		texmap->intTexId = 0;
		texmap->reserved = 0;
	}

	npLoadTexturesLegacy(dataRef);
	npLoadTextures(dataRef);

	return;
}

#define kNPextId 1
#define kNPintId 2

pNPtexmap npTexmapGetByIndex(int i, void* dataRef);
pNPtexmap npTexmapGetByIndex(int i, void* dataRef)
{
	pData data = (pData) dataRef;
	return &data->io.gl.texmap[i];
}

int npTexmapSearchIdForExtTexId(int intTexId, void* dataRef);
int npTexmapSearchIdForExtTexId(int intTexId, void* dataRef)
{
	int i = 0;
	pNPtexmap texmap = NULL;

	for(i = 1; i < 2000; i++)
	{
		texmap = npTexmapGetByIndex(i, dataRef);
		if(texmap->intTexId == intTexId)
		{
//			printf("---int %d to ext %d---\n", intTexId, texmap->extTexId);
//			printf("---%s %s---\n", texmap->path, texmap->filename);
			return texmap->extTexId;
		}
	}

	return 0;
}

int npTexmapSearchIdForIntTexId(int extTexId, void* dataRef);
int npTexmapSearchIdForIntTexId(int extTexId, void* dataRef)
{
	int i = 0;
	pNPtexmap texmap = NULL;

	for(i = 1; i < 2000; i++)
	{
	//	texmap = &data->io.gl.texmap[i];
		texmap = npTexmapGetByIndex(i, dataRef);
		if(texmap->extTexId == extTexId)
		{
//			printf("---int %d to ext %d---\n", intTexId, texmap->extTexId);
//			printf("---%s %s---\n", texmap->path, texmap->filename);
			return texmap->intTexId;
		}
	}

	return 0;
}

char* npTextureNewExtId( char* idVal, int* extId, void* dataRef);
char* npTextureNewExtId( char* idVal, int* extId, void* dataRef)
{
	pData data = (pData) dataRef;
	pNPtexmap tex = NULL;

	(*extId) = npstrtoi(&idVal);
	return idVal;
}

char* npTextureNewType(char* idVal, int* type, int extId, void* dataRef);
char* npTextureNewType(char* idVal, int* type, int extId, void* dataRef)
{
	pData data = (pData) dataRef;

	(*type) = npstrtoi(&idVal);
	return idVal;
}

char* npTextureNewFilename(char* stringVal, int maxSize, char* fileName, void* dataRef)
{	
	pData data = (pData) dataRef;
	pNPtexmap tex = NULL;
	char* curs = stringVal;
	char** read = NULL;
	int strLength = 0;
	int match = 0;
	char* ext = NULL;
	strLength = maxSize;
	
	if (strLength >= 200 )
		strLength = 200;
	
	fileName[0] = '\0';

	npCSVstrncpy(fileName, &curs, strLength);

	ext = strstr(fileName, ".");
	if( ext == NULL )
	{
		// texture file has no extension, cannot load
		printf("texture file has no extension, cannot load\n");
	}

	return curs;
}

char* npTextureNewFilePath(char* idVal, int maxSize, char* filePath, void* dataRef);
char* npTextureNewFilePath(char* idVal, int maxSize, char* filePath, void* dataRef)
{
	pData data = (pData) dataRef;
	char path[256] = {'\0'};
	char* curs = idVal;
	char** read = NULL;
	char* dslash = NULL;
	char* abs = NULL;
	int strLength = 0;
	int len = 0;
	int i = 0;
	int count = 0;
	strLength = maxSize;

	if (strLength >= 200 )
		strLength = 200;
	
	filePath[0] = '\0';

	npCSVstrncpy(filePath, &curs, strLength);

	if( npPathIsRel(filePath, dataRef) && strlen(filePath) > 0 )
	{
		abs = npFilePathRelToAbs(filePath, dataRef);
		filePath[0] = '\0';
		strcpy(filePath, abs);
		free(abs);
	}

	return curs;
}


void npTextureNew(char* tex_csvline, void* dataRef)
{
	pData data = (pData) dataRef;
	char* curs = tex_csvline;
	char fileName[256] = {'\0'};
	char filePath[256] = {'\0'};
	pNPtexmap tex = NULL;
	pNPtexmap extMap = NULL;
	int tempId = 0;
	int extId = 0;
	int type = 0;
	int i = 0;

	curs = npTextureNewExtId( curs, &extId, dataRef );
	curs = npTextureNewType( curs, &type, extId, dataRef );
	curs = npTextureNewFilename( curs, 20, &fileName[0], dataRef );
	curs = npTextureNewFilePath( curs, 200, &filePath[0], dataRef );

	for(i = 0; i < 100; i++)
	{
		//tex = npTexMapGet(i, dataRef);
		tex = npTex(kNPtexMapGet, &i, NULL, NULL, dataRef);
		if(tex)
		{
			if( (strcmp(tex->filename, fileName) == 0) && (strcmp(tex->path, filePath) == 0) )
			{
				printf("Found Match: %d & %d\n", i, extId);
				if( i != extId )
				{
					tex->extTexId = extId;
					data->io.gl.extMap[extId] = tex;
				}

				break;
			}
		}
	}

	if(i == 100)
	{
		// Not in list, add
		data->io.gl.texmapCount++;
		tex = &data->io.gl.texmap[data->io.gl.texmapCount];

		i = 1;
		while( data->io.gl.extMap[i] != NULL )
			i++;

		data->io.gl.extMap[i] = tex;
		tex->extTexId = i;
		tex->type = type;
		strcpy(tex->filename, fileName);
		strcpy(tex->path, filePath);
		sprintf(tex->filePath, "%s%s", tex->path, tex->filename);
	}

}

pNPtexmap npTexlistAddFile(char* filename, char* path, int extTexId, void* dataRef)
{
	pData data = (pData) dataRef;
	int count = data->io.gl.textureCount;
	pNPtexmap tex = NULL;
	int i = 0;

	for(;i < kNPtexListMax; i++)
	{
		tex = &data->io.gl.texmap[i];
		if( tex->filename[0] == '\0' && tex->path[0] == '\0' )
			break;
	}

	strcpy(tex->filename, filename);
	strcpy(tex->path, path);
	sprintf(tex->filePath, "%s%s", tex->path, tex->filename);
	tex->channels = 0;
	
	if(extTexId == 0)
	{	
		for(i = 1; i <= 100; i++)
		{
			if(data->io.gl.extMap[i] == NULL)
				break;
		}
		tex->extTexId = i;
		data->io.gl.extMap[i] = tex;
	}
	else
		tex->extTexId = extTexId;

	tex->height = 0;
	tex->image = NULL;
	tex->intTexId = 0;
	tex->loaded = 0;
	tex->reserved = 0;
	tex->type = 0;
	tex->width = 0;
	
	return tex;
}




void npTexlistSync(void* dataRef)
{
	pData data = (pData) dataRef;
	pNPtexmap tex = NULL;
	int i = 0;
	int x = 0;

	for(; i < kNPtexListMax; i++)
	{
		tex = &data->io.gl.texmap[i];
		if( tex->filename[0] != '\0' && tex->path[0] != '\0' && tex->filePath[0] != '\0' && tex->loaded == 0 )
		{
	//		printf("fn : %s | p : %s | loaded %d | extTexId : %d\n", tex->filename, tex->path, tex->loaded, tex->extTexId); //system("pause");
			x = npLoadTexture(tex->filePath, 0, dataRef);
			if(x)
			{
				tex->intTexId = x;
				tex->loaded = 1;
			}
			else
				tex->loaded = 2; // couldn't load
		}
	}
}

pNPtexmap npTexlistSearchFile(char* filename, char* path, void* dataRef)
{
	pData data = (pData) dataRef;
	int count = data->io.gl.textureCount;
	pNPtexmap tex = NULL;
	int i = 0;

	for(i = 0; i < kNPtexListMax; i++)
	{
		tex = &data->io.gl.texmap[i];
		if( ( strcmp(tex->filename, filename) == 0 ) && ( strcmp(tex->path, path) == 0 ) )
			return tex;
	}

	for(i = 0; i < kNPtexListMax; i++)
	{
		tex = &data->io.gl.texmap[i];
		if( ( strcmp(tex->filename, filename) == 0 ) )
			return tex;
	}

	return NULL;
}

int npGetUnusedExtTexId(void* dataRef)
{
	pData data = (pData) dataRef;
	pNPtexmap texmap = NULL;
	int i = 1;
	int extId = 1;

//	printf("NPgetUNUSEDextTEXid\n");
	for(i = 1; i < kNPtexListMax; i++)
	{
		texmap = &data->io.gl.texmap[i];
		if(texmap->extTexId == extId)
		{
			extId++;
			if(extId == kNPtexListMax)
				return 0;

			i = 1;
		}
	}

	for( i = 1; i < kNPtexListMax; i++)
	{
//		data->io.gl.texmap[i].extTexId = extId; // lv, temp
		if( data->io.gl.texmap[i].filename[0] == '\0' && data->io.gl.texmap[i].path[0] == '\0'
			&& data->io.gl.texmap[i].extTexId == 0 && data->io.gl.texmap[i].intTexId == 0 &&
			data->io.gl.texmap[i].loaded == 0)
			break;
		/*
		if( data->io.gl.texmap[i].extTexId == 0 )
			break;
		*/
	}

//	data->io.gl.texmap[i].extTexId = extId; // lv, temp
	printf("extMap assigning %d", extId);
	data->io.gl.extMap[extId] = &data->io.gl.texmap[i];
	data->io.gl.extMap[extId]->extTexId = extId;	

	printf("  New ext tex id : %d\n", extId);

	return extId;
}

pNPtexmap npGetUnusedTexMap(void* dataRef)
{
	pData data = (pData) dataRef;
	pNPtexmap texmap = NULL;
	pNPtexmap defTex = &data->io.gl.texmap[0];
	int i = 0;
	int res = 0;
	int texSize = sizeof(NPtexmap);


	/// texmap[0] is default

	for(i = 1; i < kNPtexListMax; i++)
	{
		texmap = &data->io.gl.texmap[i];
		res = memcmp(defTex,texmap,texSize);
		if(res == 0)
			return texmap;

	}

	return NULL;
}

pNPtexmap npTexTest(void* dataRef)
{
	pData data = (pData) dataRef;
	pNPtexmap t = NULL;
	pNPgeolist geo = NULL;
	int extId = 1;
	int geoId = 0;
	int i = 1;
	int intTexId = 0;

	t = npAddTexMap(&extId, "jeep1.jpg", "usr\\images\\", dataRef);
	t = npAddTexMap(&extId, "m_rifl.bmp", "", dataRef);
	extId = 2;
	t = npAddTexMap(&extId, "house.jpg", "", dataRef);
	t = npAddTexMap(&extId, "katze.jpg", "", dataRef);

	npUpdateTexMap(dataRef);
	

	extId = 1;

	npLoadModel(geo, dataRef);

	intTexId = npGeoTexId(geoId, dataRef);
	printf("intTexId for %d is %d\n", geoId, intTexId);

	extId = 0;
	npLoadModel(geo, dataRef);

	return t;
}

/*
	npTexMapFind(0, fName, path, dataRef) 

	pNPtexmap npTexFind(int* extId, char* fName, char* path, void* dataRef);
	behavior:
	- first searches for fName/path pair
	- if found
	    return tex;
*/
pNPtexmap npTexFind(int* extId, char* fName, char* path, void* dataRef);
pNPtexmap npTexFind(int* extId, char* fName, char* path, void* dataRef)
{
	pData data = (pData) dataRef;
	pNPtexmap t = &data->io.gl.texmap[0];
	int i = 1;

	/*
	if( (fName == NULL) && (path == NULL) )
	{
		for(i = 1; i < 2000; i++)
		{
			t = &data->io.gl.texmap[i];
			if(t->extTexId == (*extId))
				return t;
		}

		return NULL;
	}
	*/

	for(i = 1; i < 2000; i++)
	{
		t = &data->io.gl.texmap[i];

		if( (t->filename[0] !=  '\0') && (t->path[0] != '\0') )
		{
			if( (strcmp(t->filename, fName) == 0) && (strcmp(t->path, path) == 0) )	
			{
				//(*extId) = t->extTexId; // lv temp
				return t;
			}
		}	
	}

	for(i = 1; i < 2000; i++)
	{
		t = &data->io.gl.texmap[i];

		if( t->filename[0] !=  '\0' )
		{
			if( strcmp(t->filename, fName) == 0 )
			{
				//(*extId) = t->extTexId; // lv temp
				return t;
			}
		}	
	}

	return NULL;
}

// returns index into texlist :: if failure, then 0
int npUsedTex(int extId, void* dataRef);
int npUsedTex(int extId, void* dataRef)
{
	pData data = (pData) dataRef;
	pNPtexmap t = NULL;
	int i = 1;

	for(i = 1; i < 2000; i++)
	{
		t = &data->io.gl.texmap[i];
		if(t->extTexId == extId)
			return i;
	}

	return 0;
}


pNPtexmap npTexNew(int* extId, char* fName, char* path, void* dataRef);
pNPtexmap npTexNew(int* extId, char* fName, char* path, void* dataRef)
{
	pData data = (pData) dataRef;
	pNPtexmap t = NULL;
	int i = 1;

	if( (*extId) > 0 )
	{ // check if extId is used, if so, replace entry with new data
		if( (i = npUsedTex((*extId), dataRef)) )
		{
			// replace
			t = &data->io.gl.texmap[i];
			t->filename[0] = '\0';
			t->path[0] = '\0';
			strcpy(t->filename, fName);
			strcpy(t->path, path);
			t->intTexId = 0;
			t->loaded = 0;
		}
		else
		{
			// didn't find extId, safe to use
			t = npGetUnusedTexMap(dataRef);
			if(t)
			{
				t->extTexId = (*extId);
				printf("Using t->extTexId : %d\n", t->extTexId);
				t->filename[0] = '\0';
				t->path[0] = '\0';
				strcpy(t->filename, fName);
				strcpy(t->path, path);
				t->intTexId = 0;
				t->loaded = 0;
			}
			else
			{
				printf("could not get texmap\n");
			}
		}

	}
	else if( (*extId) == 0 )
	{
		//t->extTexId
		t = npGetUnusedTexMap(dataRef);
		//	t->extTexId = (*extId);
			t->extTexId = npGetUnusedExtTexId(dataRef);
			(*extId) = t->extTexId;
			t->filename[0] = '\0';
			t->path[0] = '\0';
			strcpy(t->filename, fName);
			strcpy(t->path, path);
			t->intTexId = 0;
			t->loaded = 0;
	}

	if( (*extId) == 0 )
	{
		t->extTexId = npGetUnusedExtTexId(dataRef);
	}


	return t;
}

pNPtexmap npAddTexMap(int* extId, char* fName, char* path, void* dataRef);
pNPtexmap npAddTexMap(int* extId, char* fName, char* path, void* dataRef)
{
	pData data = (pData) dataRef;
	pNPtexmap t = NULL;
	int i = 1;
	int oldId = (*extId);
	char* abs = NULL;
	char intPath[256] = {'\0'};

	if( npPathIsRel(path, dataRef) )
	{
		abs = npFilePathRelToAbs(path, dataRef);
		strcpy(intPath, abs);
	}
	else
		strcpy(intPath, path);

	// check if filename / path pair already exists in list
	// if npTexFind can't find pair then it looks for only an fName match
	t = npTexFind(extId, fName, intPath, dataRef);
	if(t)
	{
	//	printf("npTexFind Found\n");
	//	printf("fName %s || path %s\n", fName, intPath);
		return t;
	}

//	printf("npTexFind Not Found\n");
//	printf("fName %s || path %s\n", fName, intPath);


	t = npTexNew(extId, fName, intPath, dataRef);
	

	return t;
}

//------------------------------------------------------------------------------
void npCloseTexMap (void* dataRef)		//clean-up
{
	return;
}

//------------------------------------------------------------------------------
void npUpdateTexMap (void* dataRef)							//add to ctrl loop, debug zz
{
	pData data = (pData) dataRef;
	pNPtexmap texmap = NULL;
	char filepath[256] = {'\0'};
	char* foundPath = NULL;
	int i = 0;

	if(data->io.gl.loadExtTexs == 1 && data->io.gl.loadExtTexs != 2)
	{
		for( i = 1; i < 2000; i++ )
		{
			texmap = &data->io.gl.texmap[i];
			if(texmap->intTexId == 0 && texmap->loaded == 0 &&
				texmap->filename[0] != '\0' && texmap->path[0] != '\0')
			{
			//	printf("Loading extTexId : %d -- intTexId : %d -- %s%s\n", texmap->extTexId, texmap->intTexId, texmap->path, texmap->filename);
				/*
				printf("texmap->extTexId : %d\n", texmap->extTexId);
				printf("texmap->path : %s\n", texmap->path);
				printf("texmap->filename : %s\n", texmap->filename);
				*/
				sprintf(filepath, "%s%s", texmap->path, texmap->filename);
				texmap->intTexId = npLoadTexture(filepath, 0, dataRef);

				if(texmap->intTexId > 0)
					texmap->loaded = 1;
				else if(texmap->intTexId == 0)
				{
					texmap->loaded = 0;
					foundPath = npSearchPathsForFile(texmap->filename, dataRef);
					if(foundPath != NULL)
					{
						foundPath[strlen(foundPath)-strlen(texmap->filename)] = '\0';
						texmap->path[0] = '\0';
						strcpy(texmap->path, foundPath);
						free(foundPath);
					}
				}
			}
	}
			data->io.gl.loadExtTexs = 2;
			return;
	}

	return;
}

void npLoadExtTexMaps(void* dataRef)
{
	pData data = (pData) dataRef;
	char fp[256] = {'\0'};
	int i;

	
	for(i = 1; i < 2000; i++)
	{
		if( data->io.gl.extMap[i] &&
			data->io.gl.extMap[i]->loaded == 0
			&&
			data->io.gl.extMap[i]->filename[0] != '\0'
			&&
			data->io.gl.extMap[i]->path[0] != '\0'
			&&
			data->io.gl.extMap[i]->intTexId == 0)
		{
			sprintf(fp, "%s%s", data->io.gl.extMap[i]->path, data->io.gl.extMap[i]->filename);
			data->io.gl.extMap[i]->intTexId = npLoadTexture(fp, 0, dataRef);
			if(data->io.gl.extMap[i]->intTexId > 0)
				data->io.gl.extMap[i]->loaded = 1;
		}
	}

}

/// Load a texture map from the specified file path of specified image type.
/// If fileType = 0 then image type determined by the file extension.
//------------------------------------------------------------------------------
int npLoadTexture( const char* filePath, int fileType, void* dataRef);
int npLoadTexture( const char* filePath, int fileType, void* dataRef)
{
	pData data = (pData) dataRef;
	int textureID = 0;

	if( !fileType )
		fileType = npGetFileTypeCat( NULL, filePath, dataRef );

	/// Use SOIL for efficient direct memory DDS file loading.
	if( fileType == kNPfileDDS )
	{
		textureID = SOIL_load_OGL_texture ( filePath,
			SOIL_LOAD_AUTO,
			SOIL_CREATE_NEW_ID,
			SOIL_FLAG_INVERT_Y |
			SOIL_FLAG_MIPMAPS * kNPglMipmaps );	// multiply to turn ON/OFF
			// | SOIL_FLAG_NTSC_SAFE_RGB	// we want the entire RGB spectrum
	}
	else
	{	/// Use FreeImage (addon) for all other (non-DDS) images.
#ifdef NP_ADDON_FREEIMAGE
		textureID = npfiLoadTexture( filePath, data );
#else
		textureID = SOIL_load_OGL_texture ( filePath,
			SOIL_LOAD_AUTO,
			SOIL_CREATE_NEW_ID,
			SOIL_FLAG_INVERT_Y |
			SOIL_FLAG_MIPMAPS * kNPglMipmaps );
#endif
	}

	// If success then increment the texture count.
	if( textureID )
	{
//		data->io.gl.textureCount++;
		data->io.gl.textureCount = textureID;
	}
	else
		printf ("err 4301 - failed to load image: %s\n", filePath);

	return textureID;

}

/*
void npSyncTex(void* dataRef)
{
	pData data = (pData) dataRef;


}
*/


//Textures, fonts, display lists, etc... can all be shared provided that:
//All rendering contexts of a shared display list must use an identical pixel format.
//http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=79299&page=1
//wglShareLists() supports texture sharing across GL contexts
/// @ todo update legacy support to use texture table to match map*.jpg to id
//------------------------------------------------------------------------------
/// Each texture needs to be referenced by the extMap 
void npLoadTextures(void* dataRef)
{
	int i = 0;
	int result = 0;
	int fileType = 0;
	int textureSize = 0;
	int fileNumber = 1;
	int fileCat = 0;

	pNPfileRef fRef = NULL;

	char* filename = (char*)malloc(4096);
	char fName[256] = {'\0'};

	unsigned int textureID;		//zz debug, allow loading textures at runtime
									//detect changes to data->io.file.mapPath
	pData data = (pData) dataRef;


	glGetIntegerv (GL_MAX_TEXTURE_SIZE, &textureSize);
	data->io.gl.maxTextureSize = textureSize;
	printf ("\nMax Texture Size: %dx%d\n", textureSize, textureSize);
	printf ("Loading Textures...\n");
	printf ("App Path : %s", data->io.file.appPath);
	//	printf ("Larger textures down converted\n", textureSize);

	fRef = nposNewFileRef( data );

	//------------------------------------------------------------------
	/// Now we load all other textures
	result = nposFindFirstFile( fRef, "usr/global/images/", "*.*", data );
	if( result != 1 )
		return;		// err or empty folder

	do
    {
		// legacy support by skipping the ones we just laoded
		if( strncmp(fRef->name, "map", 3) == 0
			&& npGetFileTypeCat(&fileCat, fRef->name, data) == kNPfileJPG )
			continue;

		npGetFileTypeCat(&fileCat, fRef->name, data);

		i++;


		// print a few of the filenames then dots for every 100 files
		if( i <= 5 )
			printf( "%.70s\n", fRef->name );
		else if(  i < 100 || i % 100 == 0 )
			printf( "." );

//		printf("fRef->name : %s\n", fRef->name);
		sprintf(filename, "%s%s%s", data->io.file.appPath ,"usr\\global\\images\\", fRef->name );
		printf("2 filename :F %s\n", filename);

		// if Folder (not a file) then recursively call to create dir tree
		if( fRef->isDir )
		{
		//	npLoadTextures( sPath, data );			// recursion
		}
		else
		{
			if(fileCat == kNPfileCatImage)
				textureID = npLoadTexture( filename, 0, data );
		}
	}
	while( nposFindNextFile( fRef ) );	// next file within limits

    nposFindClose( fRef, data );		// always clean up!

	if( data->io.gl.textureCount )
		printf ("\nDone Loading Textures\n\n");
	else
		printf ("No Textures Found!!!\n\n");
}

pNPtexmap npTexMapGet(int extTexId, void* dataRef)
{
	pData data = (pData) dataRef;
	return data->io.gl.extMap[extTexId];
}

//data->io.gl.extMap[extTexId]
pNPtexmap npTexMapIDis(int extTexId, void* dataRef)
{
	pData data = (pData) dataRef;
	return data->io.gl.extMap[extTexId];
}


int npTexMapIDint(int extTexId, void* dataRef)
{
	pData data = (pData) dataRef;
	return data->io.gl.extMap[extTexId]->intTexId;
}

int npTexMapIDext(int intTexId, void* dataRef)
{
	pData data = (pData) dataRef;
	return npTexmapSearchIdForIntTexId(intTexId, dataRef);
}




/// grabs back buffer from current OpenGL context
/// this function needs to be called just before glSwapBuffers()
//------------------------------------------------------------------------------
int npScreenGrab( char* filePath, int type, int x, int y, int w, int h,  void* dataRef )
{
	int i = 0;
	int err = 0;
	int temp = 0; //store console level
	unsigned char* pixelBuf = NULL;
//	char filePath[kNPmaxPath];
	static char timeStamp[64];

	static unsigned char tempLine[65535];	//max fixed array size is 65535

	w = glutGet( GLUT_WINDOW_WIDTH );
	h = glutGet( GLUT_WINDOW_HEIGHT );

	pixelBuf = (unsigned char*)npMalloc( 0, w*h*3, dataRef );
	if (!pixelBuf) return 1;

    glPixelStorei( GL_PACK_ALIGNMENT, 1 );
    glReadPixels( 0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, pixelBuf );

	//RGBA is good for DB thumbnails... see-through dataset snapshot
	//backbuffer needs to be black with alpha = 0
	//glReadPixels( 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, &buf[0] );

	for (i=0; i < (h / 2); i++);
	{
		memcpy( tempLine, &pixelBuf[i * w * 3], w );
		memcpy( &pixelBuf[i * w * 3], &pixelBuf[(h-i) * w * 3], w );
		memcpy( &pixelBuf[(h-i) * w * 3], tempLine, w );
	}

	nposTimeStampName( timeStamp );
	sprintf( filePath, "usr/images/%s.bmp", timeStamp );
    SOIL_save_image
		(
        filePath,
        SOIL_SAVE_TYPE_BMP, //SOIL_SAVE_TYPE_TGA, //SOIL_SAVE_TYPE_DDS
        w, h, 3,
        pixelBuf
        );

	return 0; //zz debug add error handling
}
/*
{
	w = glutGet( GLUT_WINDOW_WIDTH );
	h = glutGet( GLUT_WINDOW_HEIGHT );

	w = tempW = data->io.gl.width;
	h = tempH = data->io.gl.height;

	//construct the filename path
	nposTimeStampName( timeStamp );
	strcpy( filePath, data->io.file.mapPath );
	strcat( filePath, timeStamp );

	//resize to thumbnail and turn off HUD
	if( data->io.gl.screenGrab == 2 )
	{
		filePath[0] = '\0';
		strncat( filePath, data->io.gl.datasetName, kNPmaxPath - 4  );
		strcat( filePath, ".dds" );

		w = 480; // 320 // 160 // data->map.thumbSize.width
		h = 270; // 180 // 90  // data->map.thumbSize.height
		temp = data->io.gl.hud.console.level;
		data->io.gl.hud.console.level = 0;
		npGLResizeScene( w, h );
		npGLDrawScene( data );

		err = SOIL_save_screenshot		//grab backbuffer and write to file
			(
			filePath,
			//SOIL_SAVE_TYPE_BMP,
			//SOIL_SAVE_TYPE_TGA,
			SOIL_SAVE_TYPE_DDS,
			0, 0, w, h
			);

		//restore screen size and re-render
		data->io.gl.hud.console.level = temp;
		npGLResizeScene(tempW, tempH);
		npGLDrawScene (data);
		sprintf(msg, "Saved Thumbnail: %s", filePath);
	}
	else
	{
		strcat( filePath, ".bmp" );
	//	strcat( filePath, ".tga" );

		npGLDrawScene (data);

		err = SOIL_save_screenshot		//grab backbuffer and write to file
			(
			filePath,
			SOIL_SAVE_TYPE_BMP,
			//SOIL_SAVE_TYPE_TGA,
			//SOIL_SAVE_TYPE_DDS,
			0, 0, w, h
			);
		sprintf(msg, "Saved Screenshot: %s", filePath);
	}
	npPostMsg( msg, kNPmsgFile, data );

	data->io.gl.screenGrab = false;
}
*/

/// Grab a screenshot of the window and save it to a file as a thumbnail.
int npScreenGrabThumb( char* name, int type, int x, int y, int w, int h, void* dataRef )
{
	pData data = (pData) dataRef;

	char pathName[kNPmaxPath];

	pathName[0] = '\0';
	strncat( pathName, data->io.file.mapPath, kNPmaxPath );
	strncat( pathName, name, kNPmaxPath - strlen( pathName ) );

	data->io.gl.datasetName[0] = '\0';
	strncat( data->io.gl.datasetName, pathName, kNPmaxPath );
	data->io.gl.screenGrab = 2;	//zz debug triggers a screenGrab timestamp not synced!!!

	return 0; //zz add error handling
}
