#include "GSOptions.h"
#include "GetEmGood.h"
#include "PacTypes.h"

#include <String/StringUtil.h>



IMPLEMENT_CLONEABLE( CGSOptions, "GSOptions" )



void CGSOptions::Init()
{
  m_WaitForKey        = false;
  m_MenuWaitingForKey = 0;

  m_Menu.Add( 0, "", Pac::ControlKey::PLAYER_1_LEFT );
  m_Menu.Add( 1, "", Pac::ControlKey::PLAYER_1_RIGHT );
  m_Menu.Add( 2, "", Pac::ControlKey::PLAYER_1_UP );
  m_Menu.Add( 3, "", Pac::ControlKey::PLAYER_1_DOWN );
  m_Menu.Add( 4, "", Pac::ControlKey::PLAYER_1_ACTION );
  m_Menu.Add( 5, "", Pac::ControlKey::PLAYER_2_LEFT );
  m_Menu.Add( 6, "", Pac::ControlKey::PLAYER_2_RIGHT );
  m_Menu.Add( 7, "", Pac::ControlKey::PLAYER_2_UP );
  m_Menu.Add( 8, "", Pac::ControlKey::PLAYER_2_DOWN );
  m_Menu.Add( 9, "", Pac::ControlKey::PLAYER_2_ACTION );

  m_Menu.Add( 10 );
  m_Menu.Add( 11 );

  m_Menu.SetItemLeftRightActive( 10, true );
  m_Menu.SetItemLeftRightActive( 11, true );

  if ( m_paramInit.HasParam( "InGame" ) )
  {
    m_Menu.Add( 12 );
    m_Menu.Add( 13 );
  }
  else
  {
    m_Menu.Add( 14 );
  }

  UpdateMenuItemForKey( 0 );
  UpdateMenuItemForKey( 1 );
  UpdateMenuItemForKey( 2 );
  UpdateMenuItemForKey( 3 );
  UpdateMenuItemForKey( 4 );
  UpdateMenuItemForKey( 5 );
  UpdateMenuItemForKey( 6 );
  UpdateMenuItemForKey( 7 );
  UpdateMenuItemForKey( 8 );
  UpdateMenuItemForKey( 9 );

  m_Menu.SetMenuHandler( fastdelegate::MakeDelegate( this, &CGSOptions::OnMenuHandler ) );
  m_Menu.SetValues( GR::tPoint( 400, 300 ), GR::tPoint( 700, 0 ) );
}



void CGSOptions::Exit()
{
}



void CGSOptions::UpdateMenuItemForKey( int ItemID )
{
  GR::Database::Table*    pTable = theApp.m_TextDB.GetTable( "GUI" );
  std::string             keyName = GR::Strings::ToUpper( theApp.InputClass()->GetKeyName( theApp.BoundKey( m_Menu.GetItemParamByID( ItemID ) ) ) );

  m_Menu.SetItemText( ItemID, pTable->Entry( ItemID ) + ": " + keyName );
}



void CGSOptions::OnMenuHandler( FallingMenu::MenuEntryAction Action, const FallingMenu::tMenuEntry& Entry )
{
  switch ( Action )
  {
    case FallingMenu::MEA_LEFT_PRESSED:
      switch ( Entry.TextID )
      {
        case 10:
          {
            int     fxVolume = theApp.GetVarI( "FX.Volume" );
            fxVolume = math::maxValue( fxVolume - 10, 0 );

            theApp.SetVarI( "FX.Volume", fxVolume );

            m_Menu.UpdateItemText( Entry.TextID );
          }
          break;
        case 11:
          {
            int     musicVolume = theApp.GetVarI( "Music.Volume" );
            musicVolume = math::maxValue( musicVolume - 10, 0 );

            theApp.SetVarI( "Music.Volume", musicVolume );

            m_Menu.UpdateItemText( Entry.TextID );
          }
          break;
      }
      break;
    case FallingMenu::MEA_RIGHT_PRESSED:
      switch ( Entry.TextID )
      {
        case 10:
          {
            int     fxVolume = theApp.GetVarI( "FX.Volume" );
            fxVolume = math::minValue( fxVolume + 10, 100 );

            theApp.SetVarI( "FX.Volume", fxVolume );

            m_Menu.UpdateItemText( Entry.TextID );
          }
          break;
        case 11:
          {
            int     musicVolume = theApp.GetVarI( "Music.Volume" );
            musicVolume = math::minValue( musicVolume + 10, 100 );

            theApp.SetVarI( "Music.Volume", musicVolume );

            m_Menu.UpdateItemText( Entry.TextID );
          }
          break;
      }
      break;
  }
}



void CGSOptions::Display( XRenderer& Renderer )
{
  if ( m_paramInit.HasParam( "InGame" ) )
  {
    Renderer.SetShader( XRenderer::ST_ALPHA_BLEND );
    Renderer.SetTexture( 0, NULL );
    Renderer.RenderQuad2d( 0, 0, 800, 600, 0x80000000 );
  }
  m_Menu.Display( Renderer );
}



void CGSOptions::UpdatePerDisplayFrame( const float ElapsedTime )
{
  if ( m_WaitForKey )
  {
    GR::u32     pressedKey = theApp.InputClass()->PressedVKey();
    if ( ( pressedKey != 0 )
    &&   ( theApp.InputClass()->ReleasedVKeyPressed( pressedKey ) ) )
    {
      theApp.SetKeyBinding( m_MenuWaitingForKey, pressedKey );
      theApp.m_BoundKeys[m_MenuWaitingForKey / 5][m_MenuWaitingForKey % 5] = pressedKey;
      UpdateMenuItemForKey( m_MenuWaitingForKey );
      m_WaitForKey = false;
    }
    return;
  }

  m_Menu.Update( ElapsedTime );
  if ( m_Menu.Done() )
  {
    m_Menu.SetUndone();
    switch ( m_Menu.SelectedItem() )
    {
      case 0:
      case 1:
      case 2:
      case 3:
      case 4:
      case 5:
      case 6:
      case 7:
      case 8:
      case 9:
        {
          GR::Database::Table*    pTable = theApp.m_TextDB.GetTable( "GUI" );

          m_Menu.SetItemText( m_Menu.SelectedItem(), pTable->Entry( m_Menu.SelectedItem() ) + ": " + pTable->Entry( 15 ) );

          m_WaitForKey = true;
          m_MenuWaitingForKey = m_Menu.SelectedItem();
        }
        break;
        /*
      case 6:
        theApp.ToggleFullscreen();
        break;*/
      case 10:
        // FX Volume
        {
          int     fxVolume = theApp.GetVarI( "FX.Volume" );
          fxVolume = ( fxVolume + 10 );
          fxVolume -= fxVolume % 10;
          if ( fxVolume > 100 )
          {
            fxVolume = 0;
          }

          theApp.SetVarI( "FX.Volume", fxVolume );

          m_Menu.UpdateItemText( 10 );
        }
        break;
      case 11:
        // Music Volume
        {
          int     musicVolume = theApp.GetVarI( "Music.Volume" );
          musicVolume = ( musicVolume + 10 );
          musicVolume -= musicVolume % 10;
          if ( musicVolume > 100 )
          {
            musicVolume = 0;
          }

          theApp.SetVarI( "Music.Volume", musicVolume );

          m_Menu.UpdateItemText( 11 );
        }
        break;
      case 12:
        // resume
        PopState();
        break;
      case 14:
        // back to main menu
        ChangeState( "GSMenu" );
        break;
      case 13:
        // quit game
        PopState();
        ChangeState( "GSMenu" );
        break;
    }
  }
  if ( theApp.InputClass()->ReleasedKeyPressed( Xtreme::KEY_ESCAPE ) )
  {
    if ( m_paramInit.HasParam( "InGame" ) )
    {
      PopState();
    }
    else
    {
      ChangeState( "GSMenu" );
    }
  }
}



void CGSOptions::Update()
{

  // TODO - Update

}



bool CGSOptions::ProcessEvent( const GUI::OutputEvent& Event )
{
  switch ( Event.Type )
  {
    case OET_BUTTON_PUSHED:
      break;
  }
  return false;
}
