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

  Module: TiOptionsWindow

  Author: Carlo Ordonez

  Description:

    Adjust various game settings

  Copyright 2005 Sony Online Entertainment.  All rights reserved.

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

#include "TiOptionsWindow.h"
#include "TiUIControl.h"
#include "TiFocusMessage.h"
#include "InputConsole.h"
#include "TiUI.h"

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

TiOptionsWindow::TiOptionsWindow( TiWindow* pParent )
: TiWindow( pParent )
{
  mpCtrl = SyNew TiUIControl();

  mOptions.Init( kOptMax );

  mOptions( kOptBrightness )    = Option( "Brightness", Option::kTypeSlider );
  mOptions( kOptAmbVol )        = Option( "Music/Amb", Option::kTypeSlider );
  mOptions( kOptFxVol )         = Option( "Sound FX", Option::kTypeSlider );
  mOptions( kOptControls )      = Option( "Controls...", Option::kTypeCommand );
  mOptions( kOptSwivel )        = Option( "Combat Camera Swivel" );
  mOptions( kOptReverseCamera ) = Option( "Reverse Camera Inputs" );
  mOptions( kOptVibration )     = Option( "Vibration" );
  mOptions( kOptStereo )        = Option( "Stereo" );
  mOptions( kOptBlood )         = Option( "Blood" );
  mOptions( kOptSubtitles )     = Option( "Subtitles" );
  mOptions( kOptDamageText )    = Option( "Damage Text" );
  mOptions( kOptChatText )      = Option( "Chat Text" );
  mOptions( kOptPlayerMarkers ) = Option( "Player Markers" );
  mOptions( kOptHeadset )       = Option( "Headset Settings...", Option::kTypeCommand );

  mSelection = 0;
  mDisplayControls = false;
}

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

//***********************************************************************
// SetOptions
//***********************************************************************

void TiOptionsWindow::SetOptions( TitanOptionsI* pOptions )
{
  mpOptions = pOptions;

  mOptions(kOptBrightness).mSliderVal     = pOptions->GetBrightness();
  mOptions(kOptAmbVol).mSliderVal         = pOptions->GetAmbientVolume();
  mOptions(kOptFxVol).mSliderVal          = pOptions->GetSoundFxVolume();
  mOptions(kOptSwivel).mToggleVal         = pOptions->GetCameraSwivel();
  mOptions(kOptReverseCamera).mToggleVal  = pOptions->GetReverseCameraInputs();
  mOptions(kOptVibration).mToggleVal      = pOptions->GetVibration();
  mOptions(kOptStereo).mToggleVal         = pOptions->GetStereo();
  mOptions(kOptBlood).mToggleVal          = pOptions->GetBlood();
  mOptions(kOptSubtitles).mToggleVal      = pOptions->GetSubtitles();
  mOptions(kOptDamageText).mToggleVal     = pOptions->GetDamageText();
  mOptions(kOptChatText).mToggleVal       = pOptions->GetChatText();
  mOptions(kOptPlayerMarkers).mToggleVal  = pOptions->GetPlayerMarkers();
}

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

void TiOptionsWindow::DrawSelf()
{
  if( mDisplayControls )
  {
    int32 w, h;
    TiUI::Instance()->GetDisplaySize( &w, &h );

    mpCtrl->Init( 100, 1, TiUIControl::kNone );
    mpCtrl->Draw();

    // diagram
    const char8* pScreen = "frontend_gamecontrols.tga";
    SyVect2I offset, size;
    TiUI::Instance()->GetBitmapInfo( pScreen, offset, size );

    // stretch as needed
    SyVect2I screenLoc, screenSize;
    if( size.X > w && size.Y > h )
    {
      screenLoc( 0, 0 );
      screenSize( w, h );
    }
    else if( size.X > w )
    {
      screenSize.X = w;
      screenSize.Y = w * size.Y / size.X;

      screenLoc.X = 0;
      screenLoc.Y = (h>>1) - (screenSize.Y>>1);
    }
    else if( size.Y > h )
    {
      screenSize.X = h * size.X / size.Y;
      screenSize.Y = h;

      screenLoc.X = (w>>1) - (screenSize.X>>1);
      screenLoc.Y = 0;
    }
    else
    {
      screenSize = size;
      screenLoc.X = (w>>1) - (screenSize.X>>1);
      screenLoc.Y = (h>>1) - (screenSize.Y>>1);
    }
    TiUI::Instance()->StretchBlit( pScreen, 0, screenLoc, screenSize, offset, size, SYALPHABLENDMODE_AVG, mpCtrl->GetOpacity() );

    // button(s)
    /*
    const char8* pText = "|cBack";
    int32 tbWidth = mpCtrl->GetTextWidth(pText);
    mpCtrl->Init( SyVect2I(w>>1,h-125), tbWidth+40, 1, TiUIControl::kNone );
    mpCtrl->Draw();
    mpCtrl->DrawTextBox( pText, 20, 0, tbWidth, 1, TiUIControl::kNormal, TI_TF_SHADOW|TI_TF_HALIGN_CENTER );
    //*/
  }
  else
  {
    int32 rows = 19;
    int32 margin = 20;
    int32 width = 200;
    int32 sliderX = 0;

    mSelection = SY_CLAMP( mSelection, 0, kOptMax-1 );

    // calculate frame width
    int32 i, row;
    for( i = 0; i < kOptMax; i++ )
    {
      const Option& opt = mOptions(i);
      int32 tbWidth = mpCtrl->GetTextWidth(opt.mName)+(margin<<1);
      if( opt.mType == Option::kTypeSlider )
      {
        sliderX = SY_MAX( tbWidth, sliderX );
        width = SY_MAX( sliderX + tbWidth, width );
      }
      else
      {
        width = SY_MAX( tbWidth, width );
      }
    }

    // buttons by current selection
    const char8* pButtons = "";
    switch( mOptions(mSelection).mType )
    {
    case Option::kTypeSlider:
      pButtons = "|v|VAdjust  |cExit";
  	  break;
    case Option::kTypeCommand:
      pButtons = "|xSelect  |cExit";
      break;
    case Option::kTypeToggle:
      pButtons = "|xChange  |cExit";
      break;
    }
    width = SY_MAX( mpCtrl->GetTextWidth( pButtons )+(margin<<1), width );

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

    TiUIControl::TextColor normal = TiUIControl::kNormal;
    TiUIControl::TextColor selected = TiUIControl::kSelected;

    // title
    mpCtrl->DrawTextBox( "Options", margin, 0, width-(margin<<1), 1, normal, TI_TF_SHADOW|TI_TF_HALIGN_CENTER );

    // menu items
    for( i = 0, row = 2; i < kOptMax; i++, row++ )
    {
      bool sel = mSelection == i;
      const Option& opt = mOptions(i);
      if( opt.mType == Option::kTypeSlider )
      {
        int32 col0 = margin; 
        int32 col1 = sliderX;
        int32 col2 = width-margin;
        mpCtrl->DrawTextBox( opt.mName, col0, row, col1-col0, 1, sel ? selected : normal, TI_TF_SHADOW|TI_TF_HALIGN_RIGHT );
        mpCtrl->DrawProgressBar( col1, row, col2-col1, opt.mSliderVal );
      }
      else
      {
        mpCtrl->DrawTextBox( opt.mName, margin, row, width-(margin<<1), 1, sel ? selected : normal, TI_TF_SHADOW|TI_TF_HALIGN_CENTER );
      }

      if( opt.mType == Option::kTypeToggle )
      {
        // check box
        SyVect2I loc = mpCtrl->GetRowCenter( row );
        loc.X = mpCtrl->GetClientUL().X + margin;
        loc.Y -= 5;

        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( opt.mToggleVal )
        {
          loc.X += 2;
          loc.Y -= 5;
          TiUI::Instance()->Blit( pCheck, 0, loc, SYALPHABLENDMODE_AVG, mpCtrl->GetOpacity() );
        }
      }
    }

    // buttons
    mpCtrl->DrawTextBox( pButtons, margin, rows-2, width-(margin<<1), 1, normal, TI_TF_HALIGN_CENTER|TI_TF_SHADOW );
  }
}

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

bool TiOptionsWindow::ProcessKeyDown( int32 KeyCode )
{
  switch( KeyCode )
  {
  case SyInputEvent::KEYCODE_ESCAPE:
    Close();
  	return( true );

  case SyInputEvent::KEYCODE_UP:
    mSelection--;
    return( true );

  case SyInputEvent::KEYCODE_DOWN:
    mSelection++;
    return( true );

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

  case SyInputEvent::KEYCODE_LEFT:
    Left();
    return( true );

  case SyInputEvent::KEYCODE_RIGHT:
    Right();
    return( true );

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

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

bool TiOptionsWindow::ProcessButtonDown( int32 DeviceId, int32 ButtonId )
{
  switch( TiWindow::GetButton( ButtonId ) )
  {
  case TiButtonMap::kCircle:
    Close();
    return( true );

  case TiButtonMap::kUp:
    TiUI::Instance()->PlaySound( TiUI::kSoundTick );
    mSelection--;
    return( true );

  case TiButtonMap::kDown:
    TiUI::Instance()->PlaySound( TiUI::kSoundTick );
    mSelection++;
    return( true );

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

  case TiButtonMap::kLeft:
    Left();
    return( true );

  case TiButtonMap::kRight:
    Right();
    return( true );

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

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

void TiOptionsWindow::ProcessMessage( TiWindowMessage* pMessage )
{
  switch( pMessage->GetMessageId() )
  {
  case TIWINDOW_SETFOCUS:
    // just gained focus
    mSelection = 0;
    mDisplayControls = false;
    mpCtrl->Close( true );
    mpCtrl->Open();
    break;

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

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

void TiOptionsWindow::Select()
{
  SyAssert( mSelection >= 0 && mSelection < mOptions.Size() );

  Option& opt = mOptions(mSelection);
  if( opt.mType == Option::kTypeToggle )
  {
    TiUI::Instance()->PlaySound( TiUI::kSoundName );
    opt.mToggleVal = !opt.mToggleVal;
  }
  else if( opt.mType == Option::kTypeCommand )
  {
    if( mSelection == kOptControls )
    {
      TiUI::Instance()->PlaySound( TiUI::kSoundName );
      mDisplayControls = true;
      mpCtrl->Close( true );
      mpCtrl->Open();
    }
  }
}

//***********************************************************************
// Left
//***********************************************************************

void TiOptionsWindow::Left()
{
  SyAssert( mSelection >= 0 && mSelection < mOptions.Size() );

  Option& opt = mOptions(mSelection);
  if( opt.mType == Option::kTypeSlider )
  {
    TiUI::Instance()->PlaySound( TiUI::kSoundTick );
    opt.mSliderVal = SY_CLAMP( opt.mSliderVal-.1f, 0.f, 1.f );
  }
}

//***********************************************************************
// Right
//***********************************************************************

void TiOptionsWindow::Right()
{
  SyAssert( mSelection >= 0 && mSelection < mOptions.Size() );

  Option& opt = mOptions(mSelection);
  if( opt.mType == Option::kTypeSlider )
  {
    TiUI::Instance()->PlaySound( TiUI::kSoundTick );
    opt.mSliderVal = SY_CLAMP( opt.mSliderVal+.1f, 0.f, 1.f );
  }
}

//***********************************************************************
// Close
//***********************************************************************

void TiOptionsWindow::Close()
{
  TiUI::Instance()->PlaySound( TiUI::kSoundBack );
  if( mDisplayControls )
  {
    mDisplayControls = false;
  }
  else
  {
    // write to data set
    // todo: perhaps ask to save to memory card
    mpOptions->SetBrightness( mOptions(kOptBrightness).mSliderVal );
    mpOptions->SetAmbientVolume( mOptions(kOptAmbVol).mSliderVal );
    mpOptions->SetSoundFxVolume( mOptions(kOptFxVol).mSliderVal );
    mpOptions->SetCameraSwivel( mOptions(kOptSwivel).mToggleVal );
    mpOptions->SetReverseCameraInputs( mOptions(kOptReverseCamera).mToggleVal );
    mpOptions->SetVibration( mOptions(kOptVibration).mToggleVal );
    mpOptions->SetStereo( mOptions(kOptStereo).mToggleVal );
    mpOptions->SetBlood( mOptions(kOptBlood).mToggleVal );
    mpOptions->SetSubtitles( mOptions(kOptSubtitles).mToggleVal );
    mpOptions->SetDamageText( mOptions(kOptDamageText).mToggleVal );
    mpOptions->SetChatText( mOptions(kOptChatText).mToggleVal );
    mpOptions->SetPlayerMarkers( mOptions(kOptPlayerMarkers).mToggleVal );

    CloseWindow();
  }
}

//***********************************************************************
// TiOptionsWindow::Option class
//***********************************************************************

TiOptionsWindow::Option::Option()
{
  mName.Init( "" );
  mType = kTypeToggle;
  mSliderVal = 0.f;
  mToggleVal = false;
}

TiOptionsWindow::Option::Option( const char8* pName, Type type, float32 SliderVal, bool ToggleVal )
{
  mName = pName;
  mType = type;
  mSliderVal = SliderVal;
  mToggleVal = ToggleVal;
}

