/*********************************************************************
*	CBaseContainer
*	SOURCE FILE
*	Autor:	Michal Jirouš
*	Datum: 1.7.2008
*	Soubor: basecontainer.cpp
*	Popis: Zakladni predpis kontejneru, obsahuje zakladni principy a funkce
**********************************************************************/

#include "gfg.h"

CBaseContainer::~CBaseContainer()
{
	clear();
}

//Smazani vsech komponent
void CBaseContainer::clear()
{
	for( iterContElem_t iter = m_Components.begin(); iter != m_Components.end(); iter++ )
		delete (*iter);
	m_Components.clear();
}

//Reakce na ymenu pozice
void CBaseContainer::onScissorBoxTranslate( float offsetX, float offsetY )
{
	for( iterContElem_t iter = m_Components.begin(); iter != m_Components.end(); iter++ )
		(*iter)->m_pComponent->setPositionOffset( offsetX, offsetY );
}

bool CBaseContainer::inputController( int type, float x, float y, int param1, int param2 )
{
	if( m_Components.empty() )
		return false;

	if( (type == GFG_LOST_FOCUS )   )
	{
		m_Components.back()->m_pComponent->inputController( type, 0, 0, param1, 0 );
		return false;
	}
	else if( type == GFG_GOT_FOCUS)
	{
		gotFocus( param1 );
		return false;
	}

	if( !m_bVisible || !m_bEnabled || m_bTemporaryDisabled )
		return false;

	//pokud tuto zpravu komponenty neobslouzi, tak dojde ke zmene fokusu
	if( type == GFG_SPECIAL_KEY_DOWN || (type == GFG_KEYBOARD_DOWN && param1 == GFG_KEY_TAB) )
	{
		if( !m_Components.back()->m_pComponent->inputController( type, x, y, param1, param2 ) )
			return changeFocusBySpecKey( param1 );
		else
			return true;
	}
	else if( type == GFG_MOUSE_OVER )
	{
		for( riterContElem_t iter = m_Components.rbegin(); iter != m_Components.rend(); iter++ )
		{
			if(	(*iter)->m_pComponent->inputController( type, x, y, param1, param2 ) )
				param1 = 0;
		}
		return (param1 == 0);
	}
	else if( type == GFG_MOUSE_BUTTON && param2 == GFG_DOWN )
	{
		for( riterContElem_t iter = m_Components.rbegin(); iter != m_Components.rend(); iter++ )
		{
			if(	(*iter)->m_pComponent->inputController( type, x, y, param1, param2 ) )
			{
				//zmena fokusu na komponentu, na kterou se kliklo
				changeFocusedItem( *iter, 0 );
				return true;
			}
		}
		return false;
	}
	else if( type & GFG_KEYBOARD )
	{
		return m_Components.back()->m_pComponent->inputController( type, x, y, param1, param2 );
	}
	
	for( iterContElem_t iter = m_Components.begin(); iter != m_Components.end(); iter++ )
		(*iter)->m_pComponent->inputController( type, x, y, param1, param2 );
	return false;
}

//Vykreslovani
void CBaseContainer::draw( ScissorBox &scissorBox )
{
	if( !m_bVisible )
		return;

	ScissorBox itersected = m_ScissorBox.intersection( scissorBox );
	for( iterContElem_t iter = m_Components.begin(); iter != m_Components.end(); iter++ )
		(*iter)->m_pComponent->draw( itersected );
	
	//vykresleni ramecku s textem
	if( m_bDraw )
	{
		glBegin( GL_LINE_STRIP );
			setColor( GFG_COLOR_TEXTBOX_START_LINE_MOUSEOVER );
			glVertex2f( m_fGlobalXpos + m_fWidth * 0.1f, m_fGlobalYpos + m_fHeight - m_fPaddingTop / 2.0f );
			glVertex2f( m_fGlobalXpos + m_fPaddingLeft / 2.0f, m_fGlobalYpos + m_fHeight - m_fPaddingTop / 2.0f );
			setColor( GFG_COLOR_SKIN_END_LINE );
			glVertex2f( m_fGlobalXpos + m_fPaddingLeft / 2.0f, m_fGlobalYpos + m_fPaddingBottom / 2.0f );
			glVertex2f( m_fGlobalXpos + m_fWidth - m_fPaddingRight / 2.0f, m_fGlobalYpos + m_fPaddingBottom / 2.0f );
			setColor( GFG_COLOR_TEXTBOX_START_LINE_MOUSEOVER );
			glVertex2f( m_fGlobalXpos + m_fWidth - m_fPaddingRight / 2.0f, m_fGlobalYpos + m_fHeight - m_fPaddingTop / 2.0f  );
			if( m_dsCaption.empty() )
				glVertex2f( m_fGlobalXpos + m_fWidth * 0.1f, m_fGlobalYpos + m_fHeight - m_fPaddingTop / 2.0f  );			
			else
				glVertex2f( m_fGlobalXpos + m_fWidth * 0.1f + m_dsCaption.m_pLineList->front().width + 10.0f, m_fGlobalYpos + m_fHeight - m_fPaddingTop / 2.0f  );
		glEnd();
		
		if( !m_dsCaption.empty() )
			m_dsCaption.draw( m_fGlobalXpos + m_fWidth * 0.1f + 5.0f, m_fGlobalYpos + m_fHeight - m_fPaddingTop / 2.0f );
	}
	
}

void CBaseContainer::run()
{
	for( iterContElem_t iter = m_Components.begin(); iter != m_Components.end(); iter++ )
		(*iter)->m_pComponent->run();
}

void CBaseContainer::setAlphaMultiplier( float multiplier )
{
	m_fAlphaMultiplier = multiplier;
	for( iterContElem_t iter = m_Components.begin(); iter != m_Components.end(); iter++ )
		(*iter)->m_pComponent->setAlphaMultiplier( multiplier );
}

//Prehozeni fokusu na komponentu danou parametrem element, type specifikuje,
//kterou klavesou doslo ke zmene
void CBaseContainer::changeFocusedItem( ContainerElement *element, int type )
{
	if( m_Components.empty() || element == NULL )
		return;
		
	m_Components.back()->m_pComponent->inputController( GFG_LOST_FOCUS, 0, 0, 0, 0 );

	element->m_pComponent->inputController( GFG_GOT_FOCUS, 0,  0,type, 0 );
	m_Components.remove( element );
	m_Components.push_back( element );

}

void CBaseContainer::setTemporaryDisabled( bool disabled )
{
	m_bTemporaryDisabled = disabled;	
	if( !m_bEnabled )
		return;

	for( iterContElem_t iter = m_Components.begin(); iter != m_Components.end(); iter++ )
		(*iter)->m_pComponent->setTemporaryDisabled( disabled );
	
}

void CBaseContainer::setEnabled( bool enabled )
{
	if( m_bTemporaryDisabled )
	{
		m_bEnabled = enabled;
		return;
	}

	m_bEnabled = enabled;
	for( iterContElem_t iter = m_Components.begin(); iter != m_Components.end(); iter++ )
		(*iter)->m_pComponent->setTemporaryDisabled( !enabled );
}

//Pokud komponenta 'me' splni podminky, tak ziska fokus
void CBaseContainer::giveMeFocus( CBaseComponent *me )
{
	if( me->isFocusable() && me->getEnabled() && !me->getTemporaryDisabled() && me->getVisible() )
	{
		for( iterContElem_t iter = m_Components.begin(); iter != m_Components.end(); iter++ )
		{
			if(	(*iter)->m_pComponent == me )
			{
				changeFocusedItem( *iter, 0 );
				return;
			}
		}
	}
}

//pri zjisteni fokusovatelnosti musi projit cely seznam komponent a ptat se jich
bool CBaseContainer::isFocusable()
{
	for( iterContElem_t iter = m_Components.begin(); iter != m_Components.end(); iter++ )
		if( (*iter)->m_pComponent->isFocusable() )
			return true;
	return false;
}

//Hledá první komponentu, která může získat fokus, podle parametru direction
ContainerElement *CBaseContainer::findFirstNextFocusable( ContainerElement *start, ContainerElement *next, int direction )
{
	if( !start || !next)
		return NULL;
	ContainerElement *tmp = next;

	//kdyz dojde  prvku start, tak vypocet konci
	//pokud nalezne vyhovujici prvek, tak take
	while( tmp && tmp != start && ( tmp->m_pComponent->getTemporaryDisabled() || !tmp->m_pComponent->getEnabled() || !tmp->m_pComponent->getVisible() || !tmp->m_pComponent->isFocusable() ))
	{
		switch( direction )
		{
			/*case GFG_KEY_RIGHT:
				tmp = tmp->m_pNext;
				continue;*/
			case GFG_KEY_DOWN:
				tmp = tmp->m_pDown;
				continue;
			/*case GFG_KEY_LEFT:
				tmp = tmp->m_pPrevious;
				continue;*/
			case GFG_KEY_UP:
				tmp = tmp->m_pUp;
				continue;
			default:
				return NULL;
		}
		
	}
	return tmp;
}

