/*
 * 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 !!!
 * 
 *
 */

#include "ExCWindowObject.h"
//--------------------------------
// Constructor // Destructor
//--------------------------------
ExCWindowObject::ExCWindowObject(void)
{
Guard(ExCWindowObject::ExCWindowObject(void))
	Init();
	
UnGuard
}

ExCWindowObject::ExCWindowObject(ExCVec2D Size)
{
Guard(ExCWindowObject::ExCWindowObject(ExCVec2D Size))
	Init();
	SetWindowSize(Size);
	SetOldWindowSize(Size);
UnGuard
}

ExCWindowObject::ExCWindowObject(ExCVec2D Size,ExCVec2D Position)
{
Guard(ExCWindowObject::ExCWindowObject(ExCVec2D Size,ExCVec2D Position))
	Init();
	SetPosition(Position);
	SetOldPosition(Position);
	SetWindowSize(Size);
	SetOldWindowSize(Size);
UnGuard
}

ExCWindowObject::ExCWindowObject(ExCVec2D Size,ExCVec2D Position,std::string Title)
{
Guard(ExCWindowObject::ExCWindowObject(ExCVec2D Size,ExCVec2D Position,std::string Title))
	Init();
	SetWindowTitle(Title);
	SetPosition(Position);
	SetOldPosition(Position);
	SetWindowSize(Size);
	SetOldWindowSize(Size);
UnGuard
}
ExCWindowObject::~ExCWindowObject(void)
{
}


void ExCWindowObject::Init(void)
{
Guard(void ExCWindowObject::Init(void))
	SetName("ExCWindowObject");
	SetType(typeid(this).name());
	m_ShowWindow=true;
	m_Blending=false;
	m_RequestFocus=false;
	m_CurrentObjectFocus=NULL;
	m_LastObjectFocus=NULL;
	//Manager Pointer
	ManagerTexture=NULL;
	ManagerWindow=NULL;
	//Parent
	m_Parent=NULL;
	//Title
	m_ShowWindowTitle=false;
	m_WindowTitle="ExCWindowObject";
	m_WindowOldTitle="ExCWindowObject";
	m_WindowTitleColor.SetValue(0.1f,0.1f,0.1f);
	//Size and position
	m_WindowSize.SetValue(240,320);
	m_OldSize.SetValue(240,320);
	m_TitleBarSize=20;
	m_OldPosition.SetValue(0.0f,0.0f);
	m_OldMousePosition.SetValue(0,0);
	m_Position.SetValue(0,0);
	//Color and blending
	m_Blending=false;
	m_BackroundBlending=0.5f;
	m_BackroundColor.SetValue(1.0f,1.0f,1.0f);
	//Border 
	m_BorderColor.SetValue(0.6f,0.6f,0.6f);
	m_BorderSize=1.0f;
	m_ShowBorder=true;
	//Texturing
	m_BackroundIsTexturing1=false;
	m_BackroundTexture1="NONE";
	m_BackroundIsTexturing2=false;
	m_BackroundTexture2="NONE";
	m_TextureIsMouving=false;
	m_TextureMouvingVec.SetValue(0.0f,0.0f);
	//Window state
	m_CanMouve=false;
	m_Mouving=false;
	m_Reduced=false;
	m_Maximized=false;
	m_ShowWindow=true;
	m_Active=false;			//if windows is the active windows

	m_RequestFocus=false;
	m_LastObjectFocus=NULL;
	m_CurrentObjectFocus=NULL;
	m_ObjectRequestFocus=NULL;
	//std::cout<<"ExCWindowObject"<<std::endl;
UnGuard
}
//--------------------------------
// Methode
//--------------------------------

void ExCWindowObject::Draw(void)
{
Guard(void ExCWindowObject::Draw(void))
	ExNihilo::EnterOrthoMode();
	glPushAttrib(GL_ALL_ATTRIB_BITS);
		glDisable(GL_LIGHTING);
		if(m_ShowWindow)
		{
			//-----------------------------------------------
			//Draw window content
			//-----------------------------------------------
			float TabTextures[8],TabVertices[8];

			TabTextures[0]=0;TabTextures[1]=1;
			TabTextures[2]=0;TabTextures[3]=0;
			TabTextures[4]=1;TabTextures[5]=0;
			TabTextures[6]=1;TabTextures[7]=1;
			if(m_Blending)
			{
				glDisable(GL_LIGHTING);
				glEnable(GL_BLEND);
				glEnable(GL_ALPHA);
				glBlendFunc(GL_ONE,GL_ONE);
				glEnable(GL_ALPHA_TEST);
				glAlphaFunc(GL_GREATER,0);
				glDisable(GL_DEPTH_TEST);
				glColor4f(m_BackroundColor.GetX(),m_BackroundColor.GetY(),m_BackroundColor.GetZ(),m_BackroundBlending);
			}else glColor3f(m_BackroundColor.GetX(),m_BackroundColor.GetY(),m_BackroundColor.GetZ());

			TabVertices[0]=m_Position.GetX();TabVertices[1]=m_Position.GetY();
			TabVertices[2]=m_Position.GetX();TabVertices[3]=m_Position.GetY()+m_WindowSize.GetY();
			TabVertices[4]=m_Position.GetX()+m_WindowSize.GetX();TabVertices[5]=m_Position.GetY()+m_WindowSize.GetY();
			TabVertices[6]=m_Position.GetX()+m_WindowSize.GetX();TabVertices[7]=m_Position.GetY();

			if(m_TextureIsMouving)
			{
				glMatrixMode(GL_TEXTURE);
					glTranslatef(m_TextureMouvingVec.GetX()*glutGet(GLUT_ELAPSED_TIME),m_TextureMouvingVec.GetY()*glutGet(GLUT_ELAPSED_TIME),0.0f);
				glMatrixMode(GL_MODELVIEW);	
			}

			if(m_BackroundIsTexturing1)
			{
				ManagerTexture->SetTexture(1,m_BackroundTexture1);
				glTexCoordPointer(2,GL_FLOAT,0,TabTextures);
			}
			if(m_BackroundIsTexturing2)
			{
				ManagerTexture->SetTexture(0,m_BackroundTexture2);
				glTexCoordPointer(2,GL_FLOAT,0,TabTextures);
			}
			//glColor3f(1.0f,1.0f,1.0f);
			glColor3f(m_BackroundColor.GetX(),m_BackroundColor.GetY(),m_BackroundColor.GetZ());
			glEnableClientState(GL_VERTEX_ARRAY);
			glVertexPointer(2,GL_FLOAT,0,TabVertices);
			glDrawArrays( GL_QUADS, 0, 4 );
			
			if(m_BackroundIsTexturing1)ManagerTexture->ResetMultitexture();
			
			if(m_TextureIsMouving)
			{
				glMatrixMode(GL_TEXTURE);
				glLoadIdentity();
				glMatrixMode(GL_MODELVIEW);
			}
			if(m_Blending)
			{
				glDisable(GL_BLEND);
				glDisable(GL_ALPHA);
				glEnable(GL_DEPTH_TEST);
			}
			//-----------------------------
			//DrawBorder
			//-----------------------------
			if(m_ShowBorder)
			{
				glColor3f(m_BorderColor.GetX(),m_BorderColor.GetY(),m_BorderColor.GetZ());
				glBegin(GL_LINE_STRIP);
					glVertex2f(m_Position.GetX()-1,m_Position.GetY()+1);
					glVertex2f(m_Position.GetX()+m_WindowSize.GetX()+1,m_Position.GetY()+1);
					glVertex2f(m_Position.GetX()+m_WindowSize.GetX()+1,m_Position.GetY()+m_WindowSize.GetY());
					glVertex2f(m_Position.GetX()-1,m_Position.GetY()+m_WindowSize.GetY());
					glVertex2f(m_Position.GetX()-1,m_Position.GetY()+1);
				glEnd();
			}
			if(m_ShowWindowTitle)
			{
				glColor3f(m_WindowTitleColor.GetX(),m_WindowTitleColor.GetY(),m_WindowTitleColor.GetZ());
				ExNihilo::WriteToScreen(m_Position.GetX()+5,m_Position.GetY()+5+m_WindowSize.GetY()/2,m_WindowTitle);
			}
			//------------------------------
			//Draw all Child
			//------------------------------
			for(unsigned int i=0;i<m_VecWindowObject.size();i++)
			{
				//m_VecWindowObject.at(i).SetParrent(this);	
				m_VecWindowObject.at(i)->Draw();	
			}
		}
	glPopAttrib();
	ExNihilo::LeaveOrthoMode();
UnGuard
}

void ExCWindowObject::AddObjectControl(ExCWindowObject *object)
{
Guard(void ExCWindowObject::AddObjectControl(ExCWindowObject *object))
	object->SetParrent(this);
	object->SetManagerTexture(ManagerTexture);
	object->SetManagerWindow(ManagerWindow);
	object->SetPosition(m_Position+object->GetPosition());
	m_VecWindowObject.push_back(object);
UnGuard
}

void ExCWindowObject::SetPosition(ExCVec2D Position)
{
Guard(void ExCWindowObject::SetPosition(ExCVec2D Position))
	m_OldPosition=m_Position;
	m_Position=Position;
UnGuard
}
/*

void ExCWindowObject::RefreshPosotion(void)
{
Guard(void ExCWindowObject::RefreshPosotion(void))
	for(unsigned int i=0;i<m_VecWindowObject.size();i++)
	{
		//m_VecWindowObject.at(i)->SetPosition();	
	}
UnGuard
}

void ExCWindowObject::RefreshSize(void)
{
Guard(void ExCWindowObject::RefreshSize(void))
	for(unsigned int i=0;i<m_VecWindowObject.size();i++)
	{
		//m_VecWindowObject.at(i)->Draw();	
	}
UnGuard
}
*/
ExCAction ExCWindowObject::InputCommand(ExCCommand Command)
{
Guard(ExCAction ExCWindowObject::InputCommand(ExCCommand Command))
	//std::cout<<"ExCWindowObject::Input Command window:"<<Command.m_Command<<std::endl;
	//find the good control to send message (one control can not be on other) the first is selected
	for(unsigned int i=0;i<m_VecWindowObject.size();i++)
	{
		//transfrom position to object position
		ExCVec2D ObjPos(Command.m_MousePosx,Command.m_MousePosy);
		//ObjPos=ObjPos-m_Position;
		//std::cout<<"Window Object name:"<<m_VecWindowObject.at(i)->GetName()<<std::endl;
		//std::cout<<"Window try to routing command :"<<Command.m_Command<<std::endl;
		//std::cout<<"Mouse position:"<<ObjPos<<std::endl;
		//std::cout<<"Object position:"<<m_VecWindowObject.at(i)->GetPosition()<<std::endl;

		/*if(m_ObjectRequestFocus!=NULL)
		{
			return InputAction(m_ObjectRequestFocus->InputCommand(Command));	
		}*/
		if(m_VecWindowObject.at(i)->PointInWindow(ExCVec2D(Command.m_MousePosx,Command.m_MousePosy)))
		{
			/*std::cout<<"Point in "<<m_VecWindowObject.at(i)->GetName()<<std::endl;
			ExCAction tmpaction;
			tmpaction=m_VecWindowObject.at(i)->InputCommand(Command);	
			std::cout<<"ExCWindowObject routing action :"<<tmpaction<<std::endl;
			return tmpaction;*/
			/*if(m_VecWindowObject.at(i)!=m_LastObjectFocus)
			{
				m_LastObjectFocus=m_CurrentObjectFocus;
				m_CurrentObjectFocus=m_VecWindowObject.at(i);
				if(m_LastObjectFocus!=NULL)
				{
					m_LastObjectFocus->InputCommand(ExCCommand(WINDOW_LOSE_FOCUS));
					m_LastObjectFocus->SetActive(false);
				}
				if(m_CurrentObjectFocus!=NULL)
				{
					m_CurrentObjectFocus->InputCommand(ExCCommand(WINDOW_GET_FOCUS));
					m_CurrentObjectFocus->SetActive(true);
				}
			}*/
			//if(m_ObjectRequestFocus)

			return InputAction(m_VecWindowObject.at(i)->InputCommand(Command));	
		}
		
	}
	//Point isnt in any control 
	switch(Command.m_Command)
	{
	case MOUSE_LEFT_BUTTON_DOWN:
		if (m_CanMouve) 
		{
			return MOUVE_OBJECT_WINDOW;
		}
		break;
	}

	return NOTHING;
UnGuard
}

ExCAction ExCWindowObject::InputAction(ExCAction Action)
{
Guard(ExCAction ExCWindowObject::InputAction(ExCAction Action))
	switch(Action.m_Action)
	{
	case REQUEST_FOCUS_OBJECT_WINDOW:
		m_ObjectRequestFocus=m_CurrentObjectFocus;
		break;
	case RELEASE_FOCUS_OBJECT_WINDOW:
		m_ObjectRequestFocus=NULL;
		break;
	default :
		return Action;
	}
	if(Action.m_NextAction){return *Action.m_NextAction;}
	else{return NOTHING;}
UnGuard
}

bool ExCWindowObject::PointInWindow(ExCVec2D point)
{
Guard(bool ExCWindowObject::PointInWindow(ExCVec2D point))
	if(point.GetX()>=m_Position.GetX()&&point.GetX()<=m_Position.GetX()+m_WindowSize.GetX())
	{
		if(point.GetY()>=m_Position.GetY()&&point.GetY()<=m_Position.GetY()+m_WindowSize.GetY())
		return true;
	}
	return false;
UnGuard
}

void ExCWindowObject::SetManagerTexture(ExManagerTexture * Texture)
{
Guard(void ExCWindowObject::SetManagerTexture(ExManagerTexture * Texture))
	ManagerTexture = Texture;
	for(unsigned int i=0;i<m_VecWindowObject.size();i++)
	{
		m_VecWindowObject.at(i)->SetManagerTexture(ManagerTexture);	
	}
UnGuard
}