#include "GetEmGood.h"

#include "GSMenu.h"

#include <Controls/Xtreme/GUIComponentDisplayer.h>



GetEmGood           theApp;



GetEmGood::GetEmGood() :
  CXFrameApp(),
  m_MusicFadeOut( false ),
  m_MusicFadeIn( false ),
  m_TempVolume( 0.0f ),
  m_BestScore( 0 ),
  m_BestScore2P( 0 ),
  m_LastScore( 0 ),
  m_LastScore2P( 0 )
{
  ConfigureApp( "GetEmGood.assetproject", "GR Games\\GetEmGood" );

  srand( (unsigned int)time( NULL ) );
}



GetEmGood::~GetEmGood()
{
}




void GetEmGood::Configure( Xtreme::EnvironmentConfig& Config )
{
  Config.StartUpWidth   = 800;
  Config.StartUpHeight  = 600;
  Config.IconResourceID = IDI_ICON_3DAPP;
  Config.FixedSize      = true;
  Config.Caption        = "Get 'em Good!";
}



void GetEmGood::PlaySong( const std::string& Song )
{
  if ( m_ActiveSong != Song )
  {
    if ( m_ActiveSong.empty() )
    {
      // first song
      MusicClass()->SetVolume( 0 );

      m_MusicFadeIn = true;
      m_ActiveSong = Song;
      MusicClass()->LoadMusic( CMisc::AppPath( "sounds/%s.ogg", Song.c_str() ).c_str() );
      MusicClass()->Play();
    }
    else
    {
      m_NextSong = Song;
      m_MusicFadeOut = true;
      m_MusicFadeIn = false;
    }
  }
}



bool GetEmGood::InitInstance()
{
  if ( !CXFrameApp::InitInstance() )
  {
    return false;
  }

  if ( !RunDefaultModules() )
  {
    return false;
  }

  if ( !LoadVars( UserAppDataPath( "settings.dat" ).c_str() ) )
  {
    SetVarI( "FX.Volume", 100 );
    SetVarI( "Music.Volume", 100 );
  }

  // TODO - das ist NICHT schön hier!
  InitialiseImplementationSpecificAssets();

  m_pRenderClass->SetState( XRenderer::RS_MINFILTER, XRenderer::RSV_FILTER_LINEAR );
  m_pRenderClass->SetState( XRenderer::RS_MAGFILTER, XRenderer::RSV_FILTER_LINEAR );

  XMaterial       mat;

  ZeroMemory( &mat, sizeof( XMaterial ) );
  mat.m_dwAmbient = 0xff808080;
  m_pRenderClass->SetMaterial( mat );

  m_GUI.AddListener( &m_StateManager );

  m_Sections.push_back( Section( "Tile.Empty" ) );
  m_Sections.push_back( Section( "Tile.Dot.1.1" ) );
  m_Sections.push_back( Section( "Extra.BulletPower" ) );
  m_Sections.push_back( Section( "Extra.ExtraLife" ) );
  m_Sections.push_back( Section( "Extra.FireDelay" ) );
  m_Sections.push_back( Section( "Extra.Shield" ) );
  m_Sections.push_back( Section( "Extra.SlowDown" ) );
  m_Sections.push_back( Section( "Extra.SpeedUp" ) );
  m_Sections.push_back( Section( "Extra.SuperKill" ) );
  m_Sections.push_back( Section( "Extra.Time" ) );
  m_Sections.push_back( Section( "Tile.Key" ) );
  m_Sections.push_back( Section( "Tile.Lock" ) );
  m_Sections.push_back( Section( "Tile.Caterpillar" ) );
  m_Sections.push_back( Section( "Tile.Wall.1" ) );
  m_Sections.push_back( Section( "Tile.Wall.2" ) );
  m_Sections.push_back( Section( "Tile.Wall.3" ) );
  m_Sections.push_back( Section( "Tile.Wall.4" ) );
  m_Sections.push_back( Section( "Tile.Wall.5" ) );
  m_Sections.push_back( Section( "Tile.Wall.6" ) );
  m_Sections.push_back( Section( "Tile.Wall.7" ) );
  m_Sections.push_back( Section( "Tile.Wall.8" ) );
  m_Sections.push_back( Section( "Tile.Wall.9" ) );
  m_Sections.push_back( Section( "Tile.Wall.10" ) );
  m_Sections.push_back( Section( "Tile.Wall.11" ) );
  m_Sections.push_back( Section( "Tile.Wall.12" ) );
  m_Sections.push_back( Section( "Tile.Wall.13" ) );
  m_Sections.push_back( Section( "Tile.Wall.14" ) );
  m_Sections.push_back( Section( "Tile.Wall.15" ) );
  m_Sections.push_back( Section( "Tile.Wall.16" ) );

  m_BoundKeys[0][Pac::ControlKey::LEFT]   = BoundKey( Pac::ControlKey::PLAYER_1_LEFT );
  m_BoundKeys[0][Pac::ControlKey::RIGHT]  = BoundKey( Pac::ControlKey::PLAYER_1_RIGHT );
  m_BoundKeys[0][Pac::ControlKey::UP]     = BoundKey( Pac::ControlKey::PLAYER_1_UP );
  m_BoundKeys[0][Pac::ControlKey::DOWN]   = BoundKey( Pac::ControlKey::PLAYER_1_DOWN );
  m_BoundKeys[0][Pac::ControlKey::ACTION] = BoundKey( Pac::ControlKey::PLAYER_1_ACTION );
  m_BoundKeys[1][Pac::ControlKey::LEFT]   = BoundKey( Pac::ControlKey::PLAYER_2_LEFT );
  m_BoundKeys[1][Pac::ControlKey::RIGHT]  = BoundKey( Pac::ControlKey::PLAYER_2_RIGHT );
  m_BoundKeys[1][Pac::ControlKey::UP]     = BoundKey( Pac::ControlKey::PLAYER_2_UP );
  m_BoundKeys[1][Pac::ControlKey::DOWN]   = BoundKey( Pac::ControlKey::PLAYER_2_DOWN );
  m_BoundKeys[1][Pac::ControlKey::ACTION] = BoundKey( Pac::ControlKey::PLAYER_2_ACTION );

  if ( ( m_BoundKeys[0][Pac::ControlKey::LEFT] == Xtreme::KEY_INVALID )
  &&   ( m_BoundKeys[0][Pac::ControlKey::RIGHT] == Xtreme::KEY_INVALID )
  &&   ( m_BoundKeys[0][Pac::ControlKey::UP] == Xtreme::KEY_INVALID )
  &&   ( m_BoundKeys[0][Pac::ControlKey::DOWN] == Xtreme::KEY_INVALID )
  &&   ( m_BoundKeys[0][Pac::ControlKey::ACTION] == Xtreme::KEY_INVALID ) )
  {
    // set default keys for player 1 -> probably first startup
    SetKeyBinding( Pac::ControlKey::PLAYER_1_LEFT, InputClass()->MapKeyToVKey( Xtreme::KEY_LEFT ) );
    SetKeyBinding( Pac::ControlKey::PLAYER_1_RIGHT, InputClass()->MapKeyToVKey( Xtreme::KEY_RIGHT ) );
    SetKeyBinding( Pac::ControlKey::PLAYER_1_UP, InputClass()->MapKeyToVKey( Xtreme::KEY_UP ) );
    SetKeyBinding( Pac::ControlKey::PLAYER_1_DOWN, InputClass()->MapKeyToVKey( Xtreme::KEY_DOWN ) );
    SetKeyBinding( Pac::ControlKey::PLAYER_1_ACTION, InputClass()->MapKeyToVKey( Xtreme::KEY_LCONTROL ) );
    m_BoundKeys[0][Pac::ControlKey::LEFT]   = BoundKey( Pac::ControlKey::PLAYER_1_LEFT );
    m_BoundKeys[0][Pac::ControlKey::RIGHT]  = BoundKey( Pac::ControlKey::PLAYER_1_RIGHT );
    m_BoundKeys[0][Pac::ControlKey::UP]     = BoundKey( Pac::ControlKey::PLAYER_1_UP );
    m_BoundKeys[0][Pac::ControlKey::DOWN]   = BoundKey( Pac::ControlKey::PLAYER_1_DOWN );
    m_BoundKeys[0][Pac::ControlKey::ACTION] = BoundKey( Pac::ControlKey::PLAYER_1_ACTION );
  }

  m_BestScore   = GetVarI( "Score.1" );
  m_BestScore2P = GetVarI( "Score.2" );

  //SwitchMusic( "dx8oggplayer.dll" );

  for ( int i = 'A'; i <= 'Z'; ++i )
  {
    m_Font[(char)i] = Section( CMisc::printf( "Letter.%c", i ) );
  }
  for ( int i = '0'; i <= '9'; ++i )
  {
    m_Font[(char)i] = Section( CMisc::printf( "Letter.%c", i ) );
  }
  m_Font[' '] = Section( "Tile.Empty" );

  m_GameMode = Pac::GameMode::SINGLE_PLAYER;
  m_StateManager.PushState( new CGSMenu() );
  return true;

}



void GetEmGood::ExitInstance()
{
  SaveVars( UserAppDataPath( "settings.dat" ).c_str() );

  m_StateManager.PopAllStates();

  CXFrameApp::ExitInstance();
}



bool GetEmGood::ProcessEvent( const GR::Gamebase::tXFrameEvent& Event )
{
  switch ( Event.m_Type )
  {
    case GR::Gamebase::tXFrameEvent::ET_RENDERER_SWITCHED:
      break;
    case GR::Gamebase::tXFrameEvent::ET_DISPLAY_MODE_CHANGED:
      break;
  }
  return CXFrameApp::ProcessEvent( Event );
}



bool GetEmGood::ProcessEvent( const GUI::OutputEvent& Event )
{
  if ( m_StateManager.ProcessEvent( Event ) )
  {
    return true;
  }
  return false;
}



void GetEmGood::UpdatePerDisplayFrame( const float fElapsedTime )
{
  if ( m_MusicFadeOut )
  {
    m_TempVolume -= 50.0f * fElapsedTime;
    if ( m_TempVolume <= 0.0f )
    {
      m_MusicFadeOut = false;
      m_MusicFadeIn = true;

      m_ActiveSong = m_NextSong;
      m_NextSong = "";

      MusicClass()->SetVolume( 0 );
      MusicClass()->LoadMusic( CMisc::AppPath( "sounds/%s.ogg", m_ActiveSong.c_str() ).c_str() );
      MusicClass()->Play();
    }
    else
    {
      MusicClass()->SetVolume( (int)m_TempVolume );
    }
  }
  else if ( m_MusicFadeIn )
  {
    m_TempVolume += 50.0f * fElapsedTime;
    if ( m_TempVolume >= GetVarI( "Music.Volume" ) )
    {
      m_MusicFadeIn = false;

      MusicClass()->SetVolume( GetVarI( "Music.Volume" ) );
    }
    else
    {
      MusicClass()->SetVolume( (int)m_TempVolume );
    }
  }
  m_GUI.UpdateAllControls( fElapsedTime );
}



void GetEmGood::UpdateFixedLogic()
{
  // Game-States
  m_StateManager.UpdateCurrentState();
}



void GetEmGood::RenderTextCentered( XRenderer& Renderer, int Y, const std::string& Text, GR::u32 Color )
{
  int     width = Text.length() * 16;

  RenderText( Renderer, ( Renderer.Width() - width ) / 2, Y, Text, Color );
}



void GetEmGood::RenderText( XRenderer& Renderer, int X, int Y, const std::string& Text, GR::u32 Color )
{
  for ( size_t i = 0; i < Text.length(); ++i )
  {
    Renderer.RenderTextureSection2d( X + i * 16, Y, m_Font[Text[i]], Color );
  }
}