#include "stdafx.h"
#include "BaseMenu.h"
#include "IRender.h"
#include "IInput.h"

void BaseMenu::AddEntry( MenuEntry *entry )
{
	  // Entries are sorted by their m_order param
	EntryVector::iterator iter = m_entries.begin();
	while( iter != m_entries.end() && (*iter)->GetOrder() < entry->GetOrder() )
		++iter;

	m_entries.insert( iter, entry );
}

void BaseMenu::Render( IRender *pRender )
{
	  // Yes, yes, distance between entries is hard-coded. It's bad. I'm sorry.
	for ( EntryVector::iterator iter = m_entries.begin();
		  iter != m_entries.end();
		  ++iter)
	{
		(*iter)->Render( pRender, m_x, m_y + 16 * ( iter - m_entries.begin() ) );
	}
}

void BaseMenu::ProcessInput( IInput *pInput )
{
	  // If we have a selected menu entry, it may want to process some input before we do it (like textfield entry)
	if ( m_selected >= 0 && m_selected < (int)m_entries.size() )
		m_entries[ m_selected ]->ProcessInput( pInput );

	/*
		Input handling is quite simple here.
		Up moves cursor up a position and wraps it to the bottom if we were at the top-most position
		Down move cursor down
		Escape calls Back(), which will probably close this menu (but this depends on implementation)
	*/

	pInput->BeginRead();
	while( true )
	{
		InputEvent ev = pInput->GetEvent();
		if ( ev.m_type == InputEvent::EV_INVALID )
			break;

		bool handled = false;

		if ( ev.m_type == InputEvent::EV_KEYBOARD && ev.m_keyboardEvent.m_type == KeyboardEvent::KBD_KEY_REPEAT )
		{
			if ( ev.m_keyboardEvent.m_keycode == ALLEGRO_KEY_UP )
			{
				if ( !m_entries.empty() )
				{
					if ( m_selected >= 0 && m_selected < (int)m_entries.size() )
						m_entries[ m_selected ]->SetSelected( false );

					--m_selected;
					if ( m_selected < 0 )
						m_selected = (int)m_entries.size() - 1;

					m_entries[ m_selected ]->SetSelected( true );
				}
				handled = true;
			}
			else if ( ev.m_keyboardEvent.m_keycode == ALLEGRO_KEY_DOWN )
			{
				if ( !m_entries.empty() )
				{
					if ( m_selected >= 0 || m_selected < (int)m_entries.size() )
						m_entries[ m_selected ]->SetSelected( false );

					++m_selected;
					if ( m_selected > (int)m_entries.size() - 1 )
						m_selected = 0;

					m_entries[ m_selected ]->SetSelected( true );
				}
				handled = true;
			}
			else if ( ev.m_keyboardEvent.m_keycode == ALLEGRO_KEY_ESCAPE )
			{
				Back();
				handled = true;
			}
		}

		if ( handled )
			pInput->PopEvent();
		else
			pInput->NextEvent();
	}
}

void BaseMenu::Update( float dt )
{
	for ( EntryVector::iterator iter = m_entries.begin();
		  iter != m_entries.end();
		  ++iter)
	{
		(*iter)->Update( dt );
	}
}

void BaseMenu::SetSelected( int index )
{
	if ( index < 0 || index >= (int)m_entries.size() )
		return;

	m_selected = index;

	for ( size_t i = 0; i < m_entries.size(); ++i )
	{
		m_entries[ i ]->SetSelected( false );
	}

	m_entries[ index ]->SetSelected( true );
}

void BaseMenu::SetSelected( const MenuEntry *entry )
{
	for ( size_t i = 0; i < m_entries.size(); ++i )
	{
		if ( m_entries[ i ] == entry )
		{
			SetSelected( i );
			return;
		}
	}
}
