/*
 *	Client speed control
 *	With special thanks to Adrian "Fireball" LaVallee
 */

#include "hud.h"
#include "cl_util.h"
#include "parsemsg.h"

#include <windows.h>
#include <gl\gl.h>							
#include <gl\glu.h>							
#include <gl\glaux.h>
						
#include <string>
#include <fstream>
#include "../common/com_model.h"
#include "../glpng/include/gl/glpng.h"
#include "r_studioint.h"

using namespace std;

extern engine_studio_api_t IEngineStudio;
extern cvar_t *cl_hightexture;
void COM_FileBase ( const char *in, char *out);

int CHudWorld::Init(void)
{	m_iFlags |= HUD_ACTIVE;
	
	// Edited by Pcjoe
//	Reset();
	m_flLastSetting = 0.0;
	InitHUDMap();

	gHUD.AddHudElem(this);
	return 1;
}

/* Removed by Pcjoe
void CHudWorld::Reset()
{
	m_fTexturesSet = false;
}
*/

// Added by Pcjoe
void CHudWorld::InitHUDMap( void )
{	m_fTexturesSet = false;
	SetTextureMode();
}

// Added by Pcjoe
void CHudWorld::SetTextureMode( void )
{	if((m_flLastSetting != 1.0 && cl_hightexture->value == 1.0) ||
	   (m_flLastSetting == 1.0 && cl_hightexture->value != 1.0))
	{	m_fTexturesSet = false;
		m_flLastSetting = cl_hightexture->value;
	}
}

int CHudWorld::Draw(float flTime)
{
	// Added by Pcjoe
	SetTextureMode();

	//only set high-color textures when not done before, hardware mode and requested by user(TODO)
	if (!m_fTexturesSet)
	{
		cl_entity_t *world = gEngfuncs.GetEntityByIndex( 0 );
		model_t *model = world->model;
		
		//find out about the worlds size
		vec3_t vecMins=vec3_t(4096,4096,4096);
		vec3_t vecMaxs=vec3_t(-4096,-4096,-4096);
		for(int i=0;i<model->numvertexes;i++)
		{
			mvertex_t vertex = model->vertexes[i];
			for (int j=0;j<3;j++)
			{	if (vertex.position[j]<vecMins[j])
				{	vecMins[j]=vertex.position[j];
				}
				else if (vertex.position[j]>vecMaxs[j])
				{	vecMaxs[j]=vertex.position[j];
				}
			}
		}
		model->maxs = vecMaxs;
		model->mins = vecMins;

		if (IEngineStudio.IsHardware()==1 && cl_hightexture->value==1.0)
		{	
			for(int i=0;i<model->numtextures;i++)
			{
				texture_t *texture = model->textures[i];
				// Added by Pcjoe: This may sometimes be null, check!
				if(texture == NULL)
				{	continue;
				}
				
				char szMapName[64];
				COM_FileBase( gEngfuncs.pfnGetLevelName(), szMapName );

				string sFileName=gEngfuncs.pfnGetGameDirectory();
				sFileName += "/textures/";
				sFileName += szMapName;
				sFileName += "/";
				sFileName += texture->name;
				sFileName += ".png";

				bool fHasTexture = false;
				fstream f;
				f.open(sFileName.c_str());

				if(f.is_open())
				{
					f.close();
					fHasTexture = true;
				}
				else
				{	sFileName=gEngfuncs.pfnGetGameDirectory();
					sFileName += "/textures/";
					sFileName += texture->name;
					sFileName += ".png";
					f.open(sFileName.c_str());
					if(f.is_open())
					{
						f.close();
						fHasTexture = true;
					}
				}	

				if (fHasTexture)
				{	glBindTexture  ( GL_TEXTURE_2D, texture->gl_texturenum);
					
					glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
					glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);					

					pngInfo info;
					if (!pngLoad(sFileName.c_str(), PNG_BUILDMIPMAPS, PNG_ALPHA , &info))
					{	return 1;
					}					
					texture->width = info.Width;
					texture->height = info.Height;					
				}			
			}

			// Pcjoe: High quality model textures
			fstream fstr;
			model_s *pModel = IEngineStudio.GetModelByIndex(1);
			for(int i = 2; pModel; i++)
			{	int iLen = strlen(pModel->name);
				// not a model, must be something else
				if(iLen < 5 || pModel->type != mod_studio)
				{	pModel = IEngineStudio.GetModelByIndex( i );
					continue;
				}

				int iSlashStart = -1;
				for(int x = iLen-1; x > 0; x--)
				{	if(pModel->name[x] == '/')
					{	iSlashStart = x+1;
						break;
					}
				}
				if(iSlashStart == -1)
				{	pModel = IEngineStudio.GetModelByIndex( i );
					continue;
				}
				std::string strName;
				char szAdd[2];
				szAdd[1] = '\0';
				for(int y=iSlashStart; pModel->name[y] != '.' && pModel->name[y] != '\0'; y++)
				{	szAdd[0] = pModel->name[y];
					strName.append(szAdd);			
				}

				studiohdr_t			*pStudioHeader;
				mstudiotexture_t	*pTexture;

				pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata (pModel);
				if(pStudioHeader)
				{	pTexture = (mstudiotexture_t *)((byte *)pStudioHeader + pStudioHeader->textureindex);
					std::string strFileName;
					char szTexName[64];

					if(pTexture)
					{	for(int t = 0; t < pStudioHeader->numtextures; t++)
						{	// Copy texture name
							memcpy(szTexName,pTexture[t].name,strlen(pTexture[t].name)-4);
							szTexName[strlen(pTexture[t].name)-4] = '\0';

							// get complete path to texture
							strFileName = gEngfuncs.pfnGetGameDirectory();
							strFileName += "/textures/";
							strFileName += strName;
							strFileName += "/";
							strFileName += szTexName;
							strFileName += ".png";

							// Open texture and see if it exist
							fstr.open(strFileName.c_str());
							// It exist, get new texture
							if(fstr.is_open())
							{	fstr.close();

								// Bind new model texture
								GLuint iTex;
								glGenTextures(1, &iTex);
								pTexture[t].index = iTex;
								glBindTexture( GL_TEXTURE_2D, pTexture[t].index );
								
								// setup texture filtering
								glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
								glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);					

								// load png
								pngInfo info;
								if (!pngLoad(strFileName.c_str(), PNG_BUILDMIPMAPS, PNG_SOLID , &info))
								{	return 1;
								}

							/*	char szPrint[256];
								sprintf(szPrint,"TEX OVERWRITE MDL: %s - %s\n", strName.c_str(), szTexName);
								ConsolePrint(szPrint);*/
							}
						}
					}
				}
				pModel = IEngineStudio.GetModelByIndex( i );
			}
		}
		m_fTexturesSet = true;
	}
	return 1;
}
