// Author : Chris Tolley
// Date   : 8/30/2004
// Menu.cpp contains the class definition for a animated menu to use
// with OpenGL

#pragma warning ( disable : 4305 )
#pragma warning ( disable : 4309 )

#include <windows.h>
#include <gl/gl.h>
#include <vector>

using namespace std;

#include "HiResTimer.h"
#include "InputSystem.h"
#include "Menu.h"
#include "ScreenWriter.h"
#include "logger.h"

// Constructor
Menu::Menu() 
: m_iIndex( 0 ), m_bLeft( false ), m_bRight( false )
{}// End Menu::Constructor


// Destructor
Menu::~Menu()
{}


// Updates the menu and returns a state used to control the game
enum MenuChoice Menu::Update()
{
	// Update the input
	m_Input->Update();

	// Get the amount of seconds that have elapsed since the last update
	float elapsedSec = m_Timer->getElapsedSeconds();

	// Update all the menu options
	vector< MenuOption >::iterator it;
	for( it = m_vOptions.begin(); it != m_vOptions.end(); ++it )
	{
		it->Update( elapsedSec );
	}// End for it

	// If the enter button is down
	if( m_Input->KeyDown( DIK_RETURN ) )
	{
		// Set the current MenuOption to SCATTERING
		m_vOptions[ m_iIndex ].SetState( SCATTERING );

		// Set the enter button flag
		m_bEnter = true;
	}// End if

	// If the left arrow key is down
	if( m_Input->KeyDown( DIK_N ) )
	{
		// If the left flag is not set
		if( ! m_bLeft )
		{
			// Set the flag
			m_bLeft = true;

			// Set the current options state to SCATTERING
			m_vOptions[ m_iIndex ].SetState( SCATTERING );

			// Move to the next menu option
			if( m_iIndex != 0 )
			{
				--m_iIndex;
			}// End if
			else
			{
				m_iIndex = m_vOptions.size() - 1;
			}// End if

			// Set the new option's state to GATHERING
			m_vOptions[ m_iIndex ].SetState( GATHERING );
		}// End if
	}// End if
	else
	{
		// Otherwise if the left flag is set
		if( m_bLeft )
		{
			// Reset the flag
			m_bLeft = false;
		}// End if
	}// End if

	// If the right arrow key is down
	if( m_Input->KeyDown( DIK_M ) )
	{
		// If the right flag is not set
		if( ! m_bRight )
		{
			// Set the flag
			m_bRight = true;

			// Set the current options state to SCATTERING
			m_vOptions[ m_iIndex ].SetState( SCATTERING );

			// Move to the next menu option
			if( m_iIndex != m_vOptions.size() - 1 )
			{
				++m_iIndex;
			}// End if
			else
			{
				m_iIndex = 0;
			}// End if

			// Set the new option's state to GATHERING
			m_vOptions[ m_iIndex ].SetState( GATHERING );
		}// End if
	}// End if
	else
	{
		// Otherwise, if the right flag is set
		if( m_bRight )
		{
			// Reset the flag
			m_bRight = false;
		}// End if
	}// End else

	// If the current menu option is in a SCATTERED state
	if( m_vOptions[ m_iIndex ].GetState() == SCATTERED )
	{
		// Reset the enter flag
		m_bEnter = false;

		// Set the current menu option to GATHERING
		m_vOptions[ m_iIndex ].SetState( GATHERING );
		// Return that options choice
		return m_vChoice[ m_iIndex ];
	}// End if

	// Default return statement
	return MENU;
}// End Menu::Update


// Renders the menu options to the screen
void Menu::Render()
{
	// Clear the buffers and load the identity matrix
	glClearColor( 0, 0, 0, 0 );
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
	glLoadIdentity();

	// Save the modelview matrix stack settings and reset them
	glPushMatrix();
	glLoadIdentity();

	// Translate so we can see the menu options
	glTranslatef( -90, -30, -400 );

	// Loop through each menu option and call it's render function
	vector< MenuOption >::iterator opt;
	for( opt = m_vOptions.begin(); opt != m_vOptions.end(); ++opt )
	{
		opt->Render();
	}// End for opt

	// Restore the modelview matrix stack settings
	glPopMatrix();

	// Write some instructions onto the screen
	// A variable to hold the arguments used in a printf formatted string
	int args = 0;
	float yellow[3] = { 1, 1, 0 };
	ScreenWriter::Render( 35, 15, yellow, 
		"Use the N and M keys to scroll through the options.%n", &args );

	ScreenWriter::Render( 45, 10, yellow,
		"Press enter to select an option.%n", &args );
}// End Menu::Render


// Adds a menu option and a return value for that option
void Menu::AddOption( const char* bmpFile, enum MenuChoice choice )
{
	// Add the choice to the choice vector
	m_vChoice.push_back( choice );

	// Create and add the new option
	m_vOptions.push_back( MenuOption( bmpFile ) );

	// If that was the first menu option added
	if( m_vOptions.size() == 1 )
	{
		// Set that option's state to GATHERING
		m_vOptions[ m_iIndex ].SetState( GATHERING );
	}// End if
}// End Menu::AddOption