/********************************************************************

  Module: TiPauseMenu

  Author: Carlo Ordonez

  Description:

    Menu that pops up when Start is pressed

  Copyright 2005 Sony Online Entertainment.  All rights reserved.

*********************************************************************/

#include "TiPauseMenu.h"
#include "TiUIControl.h"
#include "TiFocusMessage.h"
#include "TiCommandMessage.h"
#include "TiLoadSaveGameWindow.h"
#include "TiOptionsWindow.h"
#include "InputConsole.h"
#include "SyStr.h"
#include "TiUI.h"
#include "TitanUI.h"
#include "TitanI.h"
#include "SyPathname.h"
#include "SyDirectory.h"
#include "t4utf.h"


//***********************************************************************
// Constructor/Destructor
//***********************************************************************

TiPauseMenu::TiPauseMenu( TiWindow* pParent )
: TiWindow( pParent )
{
  mpCtrl = SyNew TiUIControl();
  mpOptionsWindow = SyNew TiOptionsWindow( this );
  mpCurrentMenu = NULL;
  mPlayerId = 0;
  mInitialized = false;
}

TiPauseMenu::~TiPauseMenu()
{
  delete mpCtrl;
}

//***********************************************************************
// Init
//***********************************************************************

int32 TiPauseMenu::Init( int32 Player, TitanOptionsI* pOptions )
{
  mPlayerId = Player;
  mpOptionsWindow->SetOptions( pOptions );

  if( !mInitialized )
  {
    char szBuffer[100];

    mDesignMenu.Init( &mTestMenu, "Design" );
    mDesignMenu.AddItem( TI_CMD_INVISIBLE, "Invisible", TiMenuItem::kCheck, NULL );
    mDesignMenu.AddItem( TI_CMD_GOD_MODE, "God", TiMenuItem::kCheck, NULL );
    mDesignMenu.AddItem( TI_CMD_LOG, "Log", TiMenuItem::kCheck, NULL );
    mDesignMenu.AddItem( TI_CMD_DEBUG_LABEL, "Debug Label", TiMenuItem::kCheck, NULL );
    mDesignMenu.AddItem( 0, "Go to Level", TiMenuItem::kNormal, &mLevelMenu );
    mDesignMenu.AddItem( 0, "", TiMenuItem::kSeperator, NULL );
    mDesignMenu.AddItem( TI_CMD_RESTART, "Restart", TiMenuItem::kNormal, NULL );

    mLevelMenu.Init( &mDesignMenu, "Go to Level" );

    SyDirectory::FindFile finder;

    int find = finder.Open( "game_assets/design/level" );
    if( find >= 0 )
    {
      while( finder.GetFile() )
      {
        SyPathname pathname( finder.GetFullPath() );
        if( SyStr::Stricmp( pathname.Extension().AsChar(), "lvl" ) == 0 ) // lvl files only
        {
          // add to menu
          mLevelMenu.AddItem( TI_CMD_GOTO_LEVEL, pathname.BaseExtension().AsChar(), TiMenuItem::kNormal, NULL );
        }
      }
    }
    finder.Close();

    mRenderMenu.Init( &mTestMenu, "Render" );
    mRenderMenu.AddItem( TI_CMD_BLOOM, "Bloom", TiMenuItem::kCheck, NULL );
    ///mRenderMenu.AddItem( TI_CMD_WATERONSPU, "Water on spu", TiMenuItem::kCheck, NULL );
    mRenderMenu.AddItem( TI_CMD_MULTI_PASS, "Multi Pass", TiMenuItem::kCheck, NULL );
    mRenderMenu.AddItem( TI_CMD_DISPLAY_STATS, "Display Stats", TiMenuItem::kCheck, NULL );
    mRenderMenu.AddItem( TI_CMD_TOGGLE_SHADOW, "Draw Shadows", TiMenuItem::kCheck, NULL );
    mRenderMenu.AddItem( TI_CMD_TOGGLE_PORTALS, "Draw Portals", TiMenuItem::kCheck, NULL );
    mRenderMenu.AddItem( TI_CMD_TOGGLE_FLORA, "Flora", TiMenuItem::kCheck, NULL );
    mRenderMenu.AddItem( TI_CMD_TOGGLE_PARTICLES, "Particles", TiMenuItem::kCheck, NULL );
    mRenderMenu.AddItem( 0, "Draw Mode", TiMenuItem::kNormal, &mDrawModeMenu );

    mDrawModeMenu.Init( &mRenderMenu, "Draw Mode" );
    mDrawModeMenu.AddItem( TI_CMD_NORMAL, "Normal", TiMenuItem::kRadio, NULL );
    mDrawModeMenu.AddItem( TI_CMD_WIRE_FRAME, "Wire Frame", TiMenuItem::kRadio, NULL );
    mDrawModeMenu.AddItem( TI_CMD_SOLID_FILL, "Solid Fill", TiMenuItem::kRadio, NULL );

    mProgrammingMenu.Init( &mTestMenu, "Programming" );
    mProgrammingMenu.AddItem( TI_CMD_BUILD_INFO, "Build Info", TiMenuItem::kNormal, NULL );
    mProgrammingMenu.AddItem( TI_CMD_VINCE, "Vince", TiMenuItem::kNormal, NULL );

    mSoundMenu.Init( &mTestMenu, "Sound" );
    mSoundMenu.AddItem( TI_CMD_MONO, "Mono", TiMenuItem::kRadio, NULL );
    mSoundMenu.AddItem( TI_CMD_STEREO, "Stereo", TiMenuItem::kRadio, NULL );
    mSoundMenu.AddItem( TI_CMD_5_1_SURROUND, "5.1 Surround", TiMenuItem::kRadio, NULL );
    mSoundMenu.AddItem( TI_CMD_7_1_SURROUND, "7.1 Surround", TiMenuItem::kRadio, NULL );

    mTestMenu.Init( &mMenu, "TEST" );
    mTestMenu.AddItem( 0, "Design", TiMenuItem::kNormal, &mDesignMenu );
    mTestMenu.AddItem( 0, "Render", TiMenuItem::kNormal, &mRenderMenu );
    mTestMenu.AddItem( 0, "Programming", TiMenuItem::kNormal, &mProgrammingMenu );
    mTestMenu.AddItem( 0, "Sound", TiMenuItem::kNormal, &mSoundMenu );

    TitanI *pTitan = TitanUI::Instance()->GetTitanI();
    pTitan->T4Expand(szBuffer, sizeof(szBuffer), SyHashResourceID("UiGamePaused"));
    mMenu.Init( NULL, szBuffer );

    pTitan->T4Expand(szBuffer, sizeof(szBuffer), SyHashResourceID("UiPauseMenuTest"));
    mMenu.AddItem( 0, szBuffer, TiMenuItem::kNormal, &mTestMenu );
    pTitan->T4Expand(szBuffer, sizeof(szBuffer), SyHashResourceID("UiPauseMenuReturnToGame"));
    mMenu.AddItem( TI_CMD_RETURN_TO_GAME, szBuffer, TiMenuItem::kNormal, NULL );
    pTitan->T4Expand(szBuffer, sizeof(szBuffer), SyHashResourceID("UiPauseMenuUseGateScroll"));
    mMenu.AddItem( TI_CMD_USE_GATE_SCROLL, szBuffer, TiMenuItem::kNormal, NULL );
    pTitan->T4Expand(szBuffer, sizeof(szBuffer), SyHashResourceID("UiPauseMenuLoadGame"));
    mMenu.AddItem( TI_CMD_LOAD_GAME, szBuffer, TiMenuItem::kNormal, NULL );
	pTitan->T4Expand(szBuffer, sizeof(szBuffer), SyHashResourceID("ACTION_SAVEGAME"));
	mMenu.AddItem( TI_CMD_SAVE_GAME, szBuffer, TiMenuItem::kNormal, NULL );
    pTitan->T4Expand(szBuffer, sizeof(szBuffer), SyHashResourceID("UiPauseMenuOptions"));
    mMenu.AddItem( TI_CMD_OPTIONS, szBuffer, TiMenuItem::kNormal, NULL );
    pTitan->T4Expand(szBuffer, sizeof(szBuffer), SyHashResourceID("UiPauseMenuExitGame"));
    mMenu.AddItem( TI_CMD_EXIT_GAME, szBuffer, TiMenuItem::kNormal, NULL );
  #ifdef WIN32
    pTitan->T4Expand(szBuffer, sizeof(szBuffer), SyHashResourceID("UiPauseMenuExitTitan"));
    mMenu.AddItem( TI_CMD_EXIT_TITAN, szBuffer, TiMenuItem::kNormal, NULL );
  #endif

    mMenus.Add( &mMenu );
    mMenus.Add( &mTestMenu );
    mMenus.Add( &mDesignMenu );
    mMenus.Add( &mRenderMenu );
    mMenus.Add( &mProgrammingMenu );
    mMenus.Add( &mSoundMenu );
    mMenus.Add( &mDrawModeMenu );
    mMenus.Add( &mLevelMenu );

	mpLoadSaveGameWindow = SyNew TiLoadSaveGameWindow( this );
	mpLoadSaveGameWindow->Show( false );
  }
  else
  {
    mMenu.mSelection = 0;
    mTestMenu.mSelection = 0;
    mDesignMenu.mSelection = 0;
    mRenderMenu.mSelection = 0;
    mProgrammingMenu.mSelection = 0;
    mSoundMenu.mSelection = 0;
    mDrawModeMenu.mSelection = 0;
    mLevelMenu.mSelection = 0;
  }

  mpCurrentMenu = &mMenu;

  mInitialized = true;
  return( 0 );
}

//***********************************************************************
// DrawSelf
//***********************************************************************

void TiPauseMenu::DrawSelf()
{
  SyAssert( mpCurrentMenu != NULL );
  TiMenu& menu = *mpCurrentMenu;
  std::vector< TiMenuItem >& menuItems = menu.mMenuItems;

  int32 w, h;
  TiUI::Instance()->GetDisplaySize( &w, &h );
  const int32 rowsMax = (h / TiUI::Instance()->GetFontHeight()) - 5;

  const int32 margin = 20;
  const char8* pButtons = "|xSelect  |cBack";

  // calculate frame dimensions
  int32 width = SY_MAX( Wnd_Width, mpCtrl->GetTextWidth(pButtons)+(margin<<1) );
  for( uint32 i = 0; i < menuItems.size(); i++ )
  {
    TiMenuItem& item = menuItems[i];
    width = SY_MAX( width, mpCtrl->GetTextWidth(item.mText)+(margin<<1) );
  }
  int32 rows = SY_MIN( (int32)menuItems.size() + 5, rowsMax );

  // draw frame
  mpCtrl->Init( width, rows );
  mpCtrl->Draw();

  // title
  int32 tbWidth = mpCtrl->GetClientSize().X - (margin<<1);
  mpCtrl->DrawTextBox( menu.mTitle, margin, 0, tbWidth, 1, TiUIControl::kNormal, TI_TF_HALIGN_CENTER|TI_TF_SHADOW );

  // compute scroll
  int32 numLines = rows-5;
  int32 numItems = (int32)menuItems.size();
  if( menu.mSelection-menu.mScroll >= numLines )
  {
    menu.mScroll = menu.mSelection - (numLines - 1);
  }
  else if( menu.mSelection < menu.mScroll )
  {
    menu.mScroll = menu.mSelection;
  }
  else if( menu.mScroll > numItems-numLines )
  {
    menu.mScroll = SY_MAX( 0, menu.mScroll-1 );
  }

  // draw menu items
  int32 row = 2;
  for( int32 i = menu.mScroll; i < numItems && row-2 < numLines; i++, row++ )
  {
    TiMenuItem& item = menuItems[i];
    TiUIControl::TextColor color = (i == menu.mSelection) ? TiUIControl::kSelected : TiUIControl::kNormal;
    mpCtrl->DrawTextBox( item.mText, margin, row, tbWidth, 1, color, TI_TF_HALIGN_CENTER|TI_TF_SHADOW|TI_TF_ELLIPSIS );

    // draw check marks
    SyVect2I loc = mpCtrl->GetRowCenter( row );
    loc.X = mpCtrl->GetClientUL().X + margin;
    loc.Y -= 5;
    if( item.mType == TiMenuItem::kCheck )
    {
      const char8* pBox = "menu_dialog_checkbox.tga";
      const char8* pCheck = "menu_dialog_checkbox_check.tga";

      TiUI::Instance()->Blit( pBox, 0, loc, SYALPHABLENDMODE_AVG, mpCtrl->GetOpacity() );
      if( item.GetCheck() )
      {
        loc.X += 2;
        loc.Y -= 5;
        TiUI::Instance()->Blit( pCheck, 0, loc, SYALPHABLENDMODE_AVG, mpCtrl->GetOpacity() );
      }
    }
    else if( item.mType == TiMenuItem::kRadio )
    {
      const char8* pBox = "menu_dialog_radio.tga";
      const char8* pRadio = "menu_dialog_radio_check.tga";

      TiUI::Instance()->Blit( pBox, 0, loc, SYALPHABLENDMODE_AVG, mpCtrl->GetOpacity() );
      if( item.GetCheck() )
      {
        loc += 3;
        TiUI::Instance()->Blit( pRadio, 0, loc, SYALPHABLENDMODE_AVG, mpCtrl->GetOpacity() );
      }
    }
  }

  // scrollbar, if needed
  if( numItems > numLines )
  {
    float32 thumb = (float32)menu.mScroll/(float32)(numItems-numLines);
    mpCtrl->DrawVScroll( tbWidth+margin, 2, tbWidth, numLines, thumb );
  }

  // draw buttons
  mpCtrl->DrawTextBox( pButtons, margin, rows-2, mpCtrl->GetClientSize().X-(margin<<1), 1, TiUIControl::kNormal, TI_TF_HALIGN_CENTER|TI_TF_SHADOW );
}

//***********************************************************************
// ProcessKeyDown
//***********************************************************************

bool TiPauseMenu::ProcessKeyDown( int32 KeyCode )
{
  switch( KeyCode )
  {
  case SyInputEvent::KEYCODE_UP:
    Prev();
    return( true );

  case SyInputEvent::KEYCODE_DOWN:
    Next();
    return( true );

  case SyInputEvent::KEYCODE_ENTER:
    Select();
    return( true );

  case SyInputEvent::KEYCODE_ESCAPE:
    Back();
    return( true );

  default:
    return( TiWindow::ProcessKeyDown( KeyCode ) );
  }
}

//***********************************************************************
// ProcessButtonDown
//***********************************************************************

bool TiPauseMenu::ProcessButtonDown( int32 DeviceId, int32 ButtonId )
{
  if( DeviceId != mPlayerId ) { return( true ); }

  switch( TiWindow::GetButton( ButtonId ) )
  {
  case TiButtonMap::kUp:
    Prev();
    return( true );

  case TiButtonMap::kDown:
    Next();
    return( true );

  case TiButtonMap::kX:
    Select();
    return( true );

  case TiButtonMap::kCircle:
  case TiButtonMap::kStart:
    Back();
    return( true );

  default:
    return( false );
    //return( TiWindow::ProcessButtonDown( DeviceId, ButtonId ) );
  }
}

//***********************************************************************
// ProcessMessage
//***********************************************************************

void TiPauseMenu::ProcessMessage( TiWindowMessage* pMessage )
{
  switch( pMessage->GetMessageId() )
  {
  case TIWINDOW_SETFOCUS:
    {
      TiFocusMessage* pMsg = static_cast<TiFocusMessage*>(pMessage);
      TiWindow* pOld = pMsg->GetOldWindow();

      // just gained focus
      mpCurrentMenu = &mMenu;
      mpCtrl->Init( Wnd_Width, Wnd_Rows );
      mpCtrl->Close( true );

      bool instant = pOld == mpOptionsWindow;
      mpCtrl->Open( instant );
    }
  	break;

  case TIWINDOW_KILLFOCUS:
    {
      TiFocusMessage* pMsg = static_cast<TiFocusMessage*>(pMessage);
      TiWindow* pNew = pMsg->GetNewWindow();

      // just lost focus
      if( pNew == mpOptionsWindow )
      {
        mpCtrl->Close( true );
      }
    }
    break;

  case TIWINDOW_COMMAND:
    {
      TiCommandMessage* pMsg = static_cast<TiCommandMessage*>(pMessage);
      switch( pMsg->GetCommandId() )
      {
      case TI_CMD_RETURN_TO_GAME:
        CloseWindow();
        break;

	  case TI_CMD_LOAD_GAME:
		  pMsg->SetClose( false );
		  mpLoadSaveGameWindow->Init( true );
		  mpLoadSaveGameWindow->Show( true );
		  mpLoadSaveGameWindow->SetFocus();
		  break;

	  case TI_CMD_SAVE_GAME:
		  pMsg->SetClose( false );
		  mpLoadSaveGameWindow->Init( false );
		  mpLoadSaveGameWindow->Show( true );
		  mpLoadSaveGameWindow->SetFocus();
		  break;

      case TI_CMD_OPTIONS:
        pMsg->SetClose( false );
        OpenOptionsWindow();
        break;

      default:
        // send command to game window
        TiWindow::ProcessMessage( pMessage );
      }
    }
    break;

  case TIWINDOW_CLOSE:
    if( pMessage->GetSender() == mpOptionsWindow )
    {
      CloseOptionsWindow();
    }
	else if( pMessage->GetSender() == mpLoadSaveGameWindow )
	{
		mpLoadSaveGameWindow->Show( false );
		SetFocus();
	}
    else
    {
      TiWindow::ProcessMessage( pMessage );
    }
    break;

  default:
    TiWindow::ProcessMessage( pMessage );
    break;
  }
}

//***********************************************************************
// IsVisible
//***********************************************************************

bool TiPauseMenu::IsVisible() const
{
  return( mVisible || mpCtrl->IsOpen() || mpCtrl->IsOpening() || mpCtrl->IsClosing() );
}

//***********************************************************************
// Show
//***********************************************************************

void TiPauseMenu::Show( bool Visible )
{
  mVisible = Visible;
  if( Visible )
  {
    mpCtrl->Open();
  }
  else
  {
    mpCtrl->Close( true );
  }
}

//***********************************************************************
// Next
//***********************************************************************

void TiPauseMenu::Next()
{
  if( mpCurrentMenu )
  {
    mpCurrentMenu->Next();
    TiUI::Instance()->PlaySound( TiUI::kSoundTick );
  }
}

//***********************************************************************
// Prev
//***********************************************************************

void TiPauseMenu::Prev()
{
  if( mpCurrentMenu )
  {
    mpCurrentMenu->Prev();
    TiUI::Instance()->PlaySound( TiUI::kSoundTick );
  }
}

//***********************************************************************
// Select
//***********************************************************************

void TiPauseMenu::Select()
{
  if( mpCurrentMenu )
  {
    TiMenuItem& item = mpCurrentMenu->mMenuItems[ mpCurrentMenu->mSelection ];
    if( item.mpSubmenu != NULL )
    {
      // open sub menu
      mpCurrentMenu = item.mpSubmenu;
      TiUI::Instance()->PlaySound( TiUI::kSoundName );
    }
    else
    {
      TiUI::Instance()->PlaySound( TiUI::kSoundSelect );

      // send message to execute command
      TiCommandMessage msg( this, TIWINDOW_COMMAND, item.mId, !item.GetCheck() );
      if( item.mId == TI_CMD_GOTO_LEVEL )
      {
        msg.SetCommandString( SyString(item.mText) );
      }
      ProcessMessage( &msg );

      switch( item.mType )
      {
      case TiMenuItem::kNormal:
        {
          if( msg.GetClose() )
          {
            // close menu
            CloseWindow();
          }
        }
      	break;

      case TiMenuItem::kCheck:
      case TiMenuItem::kRadio:
        // toggle check state
        item.mpParent->SetCheck( item.mId, !item.GetCheck() );
        break;

      default:
        break;
      }
    }
  }
}

//***********************************************************************
// Back
//***********************************************************************

void TiPauseMenu::Back()
{
  if( mpCurrentMenu && mpCurrentMenu->mpParent != NULL )
  {
    // go up one menu
    mpCurrentMenu = mpCurrentMenu->mpParent;
    TiUI::Instance()->PlaySound( TiUI::kSoundBack );
  }
  else
  {
    // close menu
    CloseWindow();
    TiUI::Instance()->PlaySound( TiUI::kSoundCancel );
  }
}

//***********************************************************************
// OpenOptionsWindow
//***********************************************************************

void TiPauseMenu::OpenOptionsWindow()
{
  mpOptionsWindow->Show( true );
  mpOptionsWindow->SetFocus();
}

//***********************************************************************
// CloseOptionsWindow
//***********************************************************************

void TiPauseMenu::CloseOptionsWindow()
{
  mpOptionsWindow->Show( false );
  this->SetFocus();
}

//***********************************************************************
// SetCheck
//***********************************************************************

void TiPauseMenu::SetCheck( int32 MenuItemId, bool Check )
{
  for( int32 i = mMenus.Begin(); i != mMenus.End(); i = mMenus.Next(i) )
  {
    TiMenu* pMenu = mMenus(i);
    if( pMenu->Find( MenuItemId ) >= 0 )
    {
      pMenu->SetCheck( MenuItemId, Check );
      return;
    }
  }
}

//***********************************************************************
// GetCheck
//***********************************************************************

bool TiPauseMenu::GetCheck( int32 MenuItemId ) const
{
  for( int32 i = mMenus.Begin(); i != mMenus.End(); i = mMenus.Next(i) )
  {
    TiMenu* pMenu = mMenus(i);
    if( pMenu->Find( MenuItemId ) >= 0 )
    {
      return( pMenu->GetCheck( MenuItemId ) );
    }
  }

  // not found
  return( false );
}
