/*
 * ExNihilo 3D Engine
 * 
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * Please read AUTHORS file !!!
 * 
 * $Id: ExManagerTexture.cpp,v 1.39 2002/12/13 11:45:01 data Exp $
 *
 */
 
#include "ExManagerTexture.h"

bool ExManagerTexture::m_flag = false; 
ExManagerTexture* ExManagerTexture::m_instance = NULL; 

ExManagerTexture* ExManagerTexture::CreateSingleton(void){
Guard(ExManagerTexture* ExManagerTexture::CreateSingleton(void))
	if(!m_flag)
	{
		m_flag = true; // We are creating the error log now, so set flag to true
		m_instance = new ExManagerTexture; // Create the error log
	}else
	{
		std::cout<<"Error singleton already created"<<std::endl;
	}
	return m_instance; 
UnGuard
}

ExManagerTexture::ExManagerTexture(void)
{
Guard(ExManagerTexture::ExManagerTexture(void))
	m_Multitexturing_level=-1;	
	m_Anisotropy_level=-1;
	m_Anisotropy_max_level=-1;
	m_Multitexturing_max_level=-1;
	glMultiTexCoord2fARB = NULL;
	glActiveTextureARB = NULL;
	glClientActiveTextureARB = NULL;

UnGuard
}


ExManagerTexture::~ExManagerTexture(void)
{
Guard(ExManagerTexture::~ExManagerTexture(void))
UnGuard
}

void  ExManagerTexture::Init(void)
{
Guard(void  ExManagerTexture::Init(void))
	ExManagerObject<ExCTexture>::Init();
	*Consol<<"****************************************"<<std::endl;
	*Consol<<"*ExManagerTexture Init                 *"<<std::endl;
	*Consol<<"****************************************"<<std::endl;
	char *blah = (char *) glGetString(GL_EXTENSIONS);
	//--------------------------------
	//ANISOTROPIC EXTENSION
	//--------------------------------
	if (strstr( (const char *)blah, "GL_EXT_texture_filter_anisotropic" )) 
	{ 
		glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT,&m_Anisotropy_max_level);
		*Consol<<"ExManagerTexture::GL_EXT_texture_filter_anisotropic enable. Maximum level:"<<m_Anisotropy_max_level<<std::endl;
		m_Anisotropy=true;
		m_Anisotropy_level=m_Anisotropy_max_level;
	}else
	{
		m_Anisotropy=false;
	}

	//--------------------------------
	//MIMAP SGIS EXTENSION
	//--------------------------------
	if (strstr( (const char *)blah, "GL_SGIS_generate_mipmap" )) 
	{ 
		*Consol<<"ExManagerTexture::GL_SGIS_generate_mipmap enable."<<std::endl;
		m_SGIS_Mimap=true;
	}else
	{
		*Consol<<"ExManagerTexture::GL_SGIS_generate_mipmap not supported."<<std::endl;
		m_SGIS_Mimap=false;
	}

	//--------------------------------
	//TEXTURING COMPRESSION EXTENSION
	//--------------------------------
	if(strstr( (const char *)blah, "GL_ARB_texture_compression" ))
	{ 
		*Consol<<"ExManagerTexture::GL_ARB_texture_compression found and enable. "<<std::endl;
		m_ARB_Texture_Compression=true;
	}else
	{
		*Consol<<"ExManagerTexture::GL_ARB_texture_compression extension missing. "<<std::endl; 
		m_ARB_Texture_Compression=false;
	}

	//--------------------------------
	//MULTITEXTURING EXTENSION
	//--------------------------------
	if (strstr( (const char *)blah, "GL_ARB_multitexture" )) 
	{
		glActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC)wglGetProcAddress("glActiveTextureARB");
		glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC)wglGetProcAddress("glMultiTexCoord2fARB");
		glClientActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)wglGetProcAddress("glClientActiveTextureARB");
		glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB,&m_Multitexturing_max_level);
		*Consol<<"ExManagerTexture::GL_ARB_multitexture found and enable. Maximum textures:"<<m_Multitexturing_max_level<<std::endl;
		m_ARB_Multitexture=true;
		m_Multitexturing_level=m_Multitexturing_max_level;
	}else
	{
		*Consol<<"ExManagerTexture::GL_ARB_multitexture extension missing"<<std::endl; 
		m_ARB_Multitexture=false;
		throw ExCExpMultitexturing();
	}

	//--------------------------------
	//TEXTURE ENV DOT 3
	//--------------------------------
	if (strstr( (const char *)blah, "GL_ARB_texture_env_dot3" )) 
	{ 
		*Consol<<"ExManagerTexture::GL_ARB_texture_env_dot3 enable."<<std::endl;
		m_ARB_texture_env_dot3=true;
	}else
	{
		*Consol<<"ExManagerTexture::GL_ARB_texture_env_dot3 not supported."<<std::endl;
		m_ARB_texture_env_dot3=false;
	}

	//--------------------------------
	//TEXTURE ENV COMBINE
	//--------------------------------
	if (strstr( (const char *)blah, "GL_ARB_texture_env_combine" )) 
	{ 
		*Consol<<"ExManagerTexture::GL_ARB_texture_env_combine enable."<<std::endl;
		m_ARB_texture_env_dot3=true;
	}else
	{
		*Consol<<"ExManagerTexture::GL_ARB_texture_env_combine not supported."<<std::endl;
		m_ARB_texture_env_dot3=false;
	}

	//--------------------------------
	//TEXTURE CUBE MAP
	//--------------------------------
	if (strstr( (const char *)blah, "GL_ARB_texture_cube_map" )) 
	{ 
		*Consol<<"ExManagerTexture::GL_ARB_texture_cube_map enable."<<std::endl;
		m_ARB_texture_cube_map=true;
	}else
	{
		*Consol<<"ExManagerTexture::GL_ARB_texture_cube_map not supported."<<std::endl;
		m_ARB_texture_cube_map=false;
	}
UnGuard
}



void  ExManagerTexture::Reset(void)
{
Guard(void  ExManagerTexture::Reset(void))
	ExManagerObject<ExCTexture>::Reset();
UnGuard
}

bool  ExManagerTexture::Init(std::string FileName)
{
Guard(bool  ExManagerTexture::Init(std::string FileName))
	//openf file and load object

	return true;
UnGuard
}

bool ExManagerTexture::CheckExist(std::string  name)
{
Guard(ExManagerTexture::CheckExist(std::string  name))
	if(name.find(".")<name.length())//if extension remove them
	{
		name.erase(name.find("."),name.length()-name.find("."));
	}
	if(ManagerId->GetObjectId(name,typeid(ExCTexture).name())==-1)return true;
	return false;
UnGuard
}


bool ExManagerTexture::Load(std::string FileName)
{
Guard(ExManagerTexture::Load(std::string FileName))
	if(FileName.find(".")<FileName.length())//if extension remove them
	{
		FileName.erase(FileName.find("."),FileName.length()-FileName.find("."));
	}
	if(!CheckExist(FileName)){return true;}
	
	try
	{
		return	Add(ExCTexture(FileName));
	}catch(ExCExpFileNotFound)
	{
		*Consol<<"Exception file not found texture not added"<<std::endl;
		return false;
	}
	catch(ExCExpNullPointer)
	{
		*Consol<<"Exception null pointer texture not added"<<std::endl;
		return false;
	}
	
UnGuard
}

bool ExManagerTexture::LoadCubeMap(std::string FileName)
{
Guard(ExManagerTexture::LoadCubeMap(std::string FileName))
	if(FileName.find(".")<FileName.length())//if extension remove them
	{
		FileName.erase(FileName.find("."),FileName.length()-FileName.find("."));
	}
	if(!CheckExist(FileName)){return true;}
	
	try
	{
		return	Add(ExCTexture(FileName));
	}catch(ExCExpFileNotFound)
	{
		*Consol<<"Exception file not found texture not added"<<std::endl;
		return false;
	}
	catch(ExCExpNullPointer)
	{
		*Consol<<"Exception null pointer texture not added"<<std::endl;
		return false;
	}
	
UnGuard
}

bool ExManagerTexture::Add(std::string FileName)
{
Guard(ExManagerTexture::Add(std::string FileName))
	return Load(FileName);
UnGuard
}

bool ExManagerTexture::Add(ExCTexture object)
{
Guard(ExManagerTexture::Add(ExCTexture object))
	if(!CheckExist(object.GetName())){return true;}
	object.SetAnisotropyLevel(m_Anisotropy,m_Anisotropy_max_level);
	object.SetSGISMipMap(m_SGIS_Mimap);
	object.SetTextureCompression(m_ARB_Texture_Compression);
	return ExManagerObject<ExCTexture>::Add(object);
UnGuard
}

bool ExManagerTexture::SetTexture(int Number,std::string Name)
{
Guard(ExManagerTexture::SetTexture(int Number,std::string Name))
	//glActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC)wglGetProcAddress("glActiveTextureARB");
	if(Name.size()<1)return false;
	switch(Number)
	{
	case 0:
		glClientActiveTextureARB ( GL_TEXTURE0_ARB        ); 
		glActiveTextureARB(GL_TEXTURE0_ARB);
		break;
	case 1:
		glClientActiveTextureARB ( GL_TEXTURE1_ARB        ); 
		glActiveTextureARB(GL_TEXTURE1_ARB);
		break;
	case 2:
		glClientActiveTextureARB ( GL_TEXTURE2_ARB        ); 
		glActiveTextureARB(GL_TEXTURE2_ARB);
		break;
	case 3:
		glClientActiveTextureARB ( GL_TEXTURE3_ARB        ); 
		glActiveTextureARB(GL_TEXTURE3_ARB);
		break;
	case 4:
		glClientActiveTextureARB ( GL_TEXTURE4_ARB        ); 
		glActiveTextureARB(GL_TEXTURE4_ARB);
		break;
	case 5:
		glClientActiveTextureARB ( GL_TEXTURE5_ARB        ); 
		glActiveTextureARB(GL_TEXTURE5_ARB);
		break;
	case 6:
		glClientActiveTextureARB ( GL_TEXTURE6_ARB        ); 
		glActiveTextureARB(GL_TEXTURE6_ARB);
		break;
	case 7:
		glClientActiveTextureARB ( GL_TEXTURE7_ARB        ); 
		glActiveTextureARB(GL_TEXTURE7_ARB);

		break;
	}
	glEnable(GL_TEXTURE_2D);
	SetCurrentObject(Name);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	return true;
UnGuard
}

void ExManagerTexture::SetTextureCoord(int Number,float CoordU,float CoordV)
{
Guard(ExManagerTexture::SetTextureCoord(int Number,float CoordU,float CoordV))
	switch(Number)
	{
	case 0:
		glMultiTexCoord2fARB ( GL_TEXTURE0_ARB,CoordU,CoordV); 
		break;
	case 1:
		glMultiTexCoord2fARB ( GL_TEXTURE1_ARB,CoordU,CoordV); 
		break;
	case 2:
		glMultiTexCoord2fARB ( GL_TEXTURE2_ARB,CoordU,CoordV); 
		break;
	case 3:
		glMultiTexCoord2fARB ( GL_TEXTURE3_ARB,CoordU,CoordV); 
		break;
	}
UnGuard
}

bool ExManagerTexture::ResetMultitexture(void)
{
Guard(ExManagerTexture::ResetMultitexture(void))
	if(m_Multitexturing_max_level>6)
	{
		glActiveTextureARB(GL_TEXTURE7_ARB);
		glDisable(GL_TEXTURE_2D);
	}
	if(m_Multitexturing_max_level>5)
	{
		glActiveTextureARB(GL_TEXTURE6_ARB);
		glDisable(GL_TEXTURE_2D);
	}
	if(m_Multitexturing_max_level>4)
	{
		glActiveTextureARB(GL_TEXTURE5_ARB);
		glDisable(GL_TEXTURE_2D);
	}
	if(m_Multitexturing_max_level>3)
	{
		glActiveTextureARB(GL_TEXTURE4_ARB);
		glDisable(GL_TEXTURE_2D);
	}
	if(m_Multitexturing_max_level>2)
	{
		glActiveTextureARB(GL_TEXTURE3_ARB);
		glDisable(GL_TEXTURE_2D);
	}
	if(m_Multitexturing_max_level>1)
	{
		glActiveTextureARB(GL_TEXTURE2_ARB);
		glDisable(GL_TEXTURE_2D);
	}
	if(m_Multitexturing_max_level>0)
	{
		glActiveTextureARB(GL_TEXTURE1_ARB);
		glDisable(GL_TEXTURE_2D);
	}
	glActiveTextureARB(GL_TEXTURE0_ARB);		
    glDisable(GL_TEXTURE_2D);
	return true;
UnGuard
}

bool ExManagerTexture::SetCurrentObject(std::string Name)
{
Guard(ExManagerTexture::SetCurrentObject(std::string Name))
	if(Name.size()<=0)return false;
	if(Name.find(".")<Name.length())//if extension remove them
	{
		Name.erase(Name.find("."),Name.length()-Name.find("."));
	}
	try
	{	
		m_CurrentObjectId=ManagerId->GetObjectId(Name,typeid(ExCTexture).name());
		glBindTexture(GL_TEXTURE_2D,GetObject(m_CurrentObjectId)->m_Texture);
		if(m_SGIS_Mimap)
		{
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, true);
		}
		return true;
		//std::cout<<"ExManagerTexture ::"<<Name<<" Current object"<<std::endl;
	}catch(...)
	{
		if(!Load(Name))
		{
			std::cout<<"ExManagerTexture ::Exception can make :"<<Name<<" Current object"<<std::endl;
			return true;
		}
		return false;
	}
UnGuard
}

bool ExManagerTexture::SetCurrentObject(ExNihilo::ExId id)
{
Guard(ExManagerTexture::SetCurrentObject(ExNihilo::ExId id))
	if(GetObject(id)!=NULL)
	{
		m_CurrentObjectId=id;
		try
		{	
			glBindTexture(GL_TEXTURE_2D,GetObject(m_CurrentObjectId)->m_Texture);
			if(m_SGIS_Mimap)
			{
				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
				glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, true);
				
			}
			return true;
			//std::cout<<"ExManagerTexture ::"<<Name<<" Current object"<<std::endl;
			}catch(...)
			{
				std::cout<<"ExManagerTexture ::Exception can make :"<<m_CurrentObjectId<<" Current object"<<std::endl;
				return false;
			}
	}
	return false;
UnGuard
}

GLint ExManagerTexture::GetTextureId(std::string Name)
{
Guard(ExManagerTexture::GetTextureId(std::string Name))
	
	if(Name.find(".")<Name.length())//if extension remove them
	{
		Name.erase(Name.find("."),Name.length()-Name.find("."));
	}
	try
	{	
		m_CurrentObjectId=ManagerId->GetObjectId(Name,typeid(ExCTexture).name());
		return GetObject(m_CurrentObjectId)->m_Texture;
		//std::cout<<"ExManagerTexture ::"<<Name<<" Current object"<<std::endl;
	}catch(...)
	{
		if(!Load(Name))
		{
			std::cout<<"ExManagerTexture ::Exception can make :"<<Name<<" Current object"<<std::endl;
			return -1;
		}
		return -1;
	}
UnGuard
}

GLint ExManagerTexture::GetTextureId(ExNihilo::ExId id)
{
Guard(ExManagerTexture::GetTextureId(ExNihilo::ExId id))
	if(GetObject(id)!=NULL)
	{
		m_CurrentObjectId=id;
		try
		{	
			return GetObject(m_CurrentObjectId)->m_Texture;
			//std::cout<<"ExManagerTexture ::"<<Name<<" Current object"<<std::endl;
			}catch(...)
			{
				std::cout<<"ExManagerTexture ::Exception can make :"<<m_CurrentObjectId<<" Current object"<<std::endl;
				return -1;
			}
	}
	return -1;
UnGuard
}


ExCAction ExManagerTexture::InputAction(ExCAction Action)
{
Guard(ExCAction ExManagerTexture::InputAction(ExCAction Action))
	switch(Action.m_Action)
	{
	case LIST_TEXTURE:
		List();
		break;
	case LOAD_TEXTURE:
		break;
	case UNLOAD_TEXTURE:
		break;
	case MANAGER_TEXTURE_RELOAD: Reload();break;
	case SAVE_TEXTURE:
		ExCTexture SaveTexture;
		SaveTexture.SaveFile(Action.m_Param,ExNihilo::GetResolutionX(),ExNihilo::GetResolutionY());
		break;
	}
	if(Action.m_NextAction){return *Action.m_NextAction;}
	else{return NOTHING;}
UnGuard
}

void  ExManagerTexture::Reload(void)
{
Guard(void  ExManagerTexture::Reload(void))
	for(m_ItMap=m_Map->begin();m_ItMap!=m_Map->end();m_ItMap++)
	{
		m_ItMap->second.LoadFile(m_ItMap->second.GetFileName());
	}	
UnGuard
}

