#include <Misc/CloneFactory.h>

#include <IO/FileStream.h>

#include "GSGame.h"
#include "GetEmGood.h"
#include "Level.h"
#include "Player.h"



IMPLEMENT_CLONEABLE( CGSGame, "GSGame" )



void CGSGame::Init()
{
  theApp.EnableCursor( false );
  m_LevelNo = 1;
  
  m_PlayState.GameMode = (Pac::GameMode::Value)m_paramInit.GetParamI32( "GameMode" );

  m_PlayState.Level.m_GameEventHandler = fastdelegate::MakeDelegate( this, &CGSGame::OnGameEvent );
  //m_Level.Load( GR::IO::FileStream( CMisc::AppPath( "data/level%d.dat", m_LevelNo ).c_str() ) );

  m_PlayState.PrepareLevel();

  for ( int i = 0; i < m_PlayState.NumPlayers(); ++i )
  {
    m_PlayState.SpawnPlayer( i );
  }
  theApp.PlaySong( Misc::Format( "Get_em_DX_game%1%" ) << ( rand() % 6 ) + 1 );
}



void CGSGame::Exit()
{
  theApp.EnableCursor();
}



void CGSGame::OnGameEvent( const Pac::tGameEvent& Event )
{
}



void CGSGame::OnResume()
{
  theApp.EnableCursor( false );
}



void CGSGame::UpdatePerDisplayFrame( const GR::f32 ElapsedTime )
{
  if ( IsPaused() )
  {
    return;
  }
  if ( theApp.InputClass()->ReleasedKeyPressed( Xtreme::KEY_ESCAPE ) )
  {
    GR::Strings::ParameterList    params;

    params.SetParam( "InGame", 1 );
    PushState( "GSOptions", params );

    theApp.EnableCursor();
    return;
  }

  if ( m_PlayState.IsGameOver() )
  {
    theApp.SoundClass()->Play( theApp.Sound( "Level.Done" ) );

    GR::Strings::ParameterList    params;

    params.SetParamIP( "Score", m_PlayState.Score );


    if ( m_PlayState.GameMode == Pac::GameMode::SINGLE_PLAYER )
    {
      theApp.m_LastScore = m_PlayState.Score;
      if ( theApp.GetVarI( "Score.1" ) < m_PlayState.Score )
      {
        theApp.SetVarI( "Score.1", m_PlayState.Score );
        theApp.m_BestScore = m_PlayState.Score;
      }
    }
    else
    {
      theApp.m_LastScore2P = m_PlayState.Score;
      if ( theApp.GetVarI( "Score.2" ) < m_PlayState.Score )
      {
        theApp.SetVarI( "Score.2", m_PlayState.Score );
        theApp.m_BestScore2P = m_PlayState.Score;
      }
    }

    ChangeState( "GSGameOver", params );
    return;
  }

  if ( m_PlayState.LevelEndDelay == 0 )
  {
    if ( m_PlayState.IsLevelCompleted() )
    {
      m_PlayState.PrepareLevel();

      for ( int i = 0; i < m_PlayState.NumPlayers(); ++i )
      {
        // players with no live left are resurrected on a new level (which was completed by the other player)
        m_PlayState.SpawnPlayer( i );
      }
      theApp.PlaySong( Misc::Format( "Get_em_DX_game%1%" ) << ( rand() % 6 ) + 1 );
      return;
    }
    m_PlayState.Level.Update( ElapsedTime );
  }
}



void CGSGame::Display( XRenderer& Renderer )
{
  m_PlayState.Level.Display( Renderer, 0, 19 );

  Renderer.SetShader( XRenderer::ST_FLAT );
  std::string     text = Misc::Format( "LIVES %1%" ) << m_PlayState.Lives;

  theApp.RenderText( Renderer, 0, 584, Misc::Format( "SCORE %01:8%" ) << m_PlayState.Score );
  theApp.RenderText( Renderer, 800 - text.length() * 16, 584, text );

  theApp.RenderTextCentered( Renderer, 0, m_PlayState.Hint );

  theApp.RenderText( Renderer, 0, 0, Misc::Format( "LEVEL %1%" ) << m_PlayState.LevelNumber );

  if ( m_PlayState.Bonus > 999 )
  {
    theApp.RenderText( Renderer, Renderer.Width() - 9 * 16, 0, "BONUS 999" );
  }
  else
  {
    theApp.RenderText( Renderer, Renderer.Width() - 9 * 16, 0, Misc::Format( "BONUS %01:3% " ) << m_PlayState.Bonus );
  }

  for ( int i = 0; i < 8; ++i )
  {
    if ( m_PlayState.ExtraState[i] > 0 )
    {
      XTextureSection   section = theApp.m_Sections[i + Pac::FT_FIRST_EXTRA];

      section.m_Height = m_PlayState.ExtraState[i] * 2;

      Renderer.RenderTextureSection2d( 300 + i * 20, 584, section );
    }
  }
}



void CGSGame::Update()
{
  if ( IsPaused() )
  {
    return;
  }
  if ( m_PlayState.LevelEndDelay == 0 )
  {
    m_PlayState.UpdateFixed();
  }
  else
  {
    if ( m_PlayState.Bonus > 100 )
    {
      m_PlayState.Bonus -= 100;
      for ( int i = 0; i < m_PlayState.NumPlayers(); ++i )
      {
        m_PlayState.Score += 500;
      }
    }
    else if ( m_PlayState.Bonus > 10 )
    {
      m_PlayState.Bonus -= 10;
      for ( int i = 0; i < m_PlayState.NumPlayers(); ++i )
      {
        m_PlayState.Score += 50;
      }
    }
    else if ( m_PlayState.Bonus > 0 )
    {
      --m_PlayState.Bonus;
      for ( int i = 0; i < m_PlayState.NumPlayers(); ++i )
      {
        m_PlayState.Score += 5;
      }
    }
    else
    {
      --m_PlayState.LevelEndDelay;
    }
  }
}



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