#include "PlayState.h"

#include <debug/debugclient.h>



PlayState::PlayState()
{
  GameMode              = Pac::GameMode::SINGLE_PLAYER;
  Player[0].PlayerIndex = 0;
  Player[1].PlayerIndex = 1;
  Level.m_pState        = this;
  Bonus                 = 0;
  BonusTickDelay        = 0;
  LevelNumber           = 0;
  NumEnemiesSpawned     = 0;
  PunishEnemiesSpawned  = 0;
  LevelIsCompleted      = false;
  LevelEndDelay         = 0;
  CaterpillarSpawned    = false;
  Score                 = 0;
  Lives                 = 3;
  TicksSinceLastDot     = 0;

  for ( int i = 0; i < 8; ++i )
  {
    ExtraState[i] = 0;
  }
}



int PlayState::NumPlayers()
{
  if ( GameMode == Pac::GameMode::SINGLE_PLAYER )
  {
    return 1;
  }
  return 2;
}



bool PlayState::IsLevelCompleted()
{
  return LevelIsCompleted;
}



bool PlayState::IsGameOver()
{
  for ( int i = 0; i < NumPlayers(); ++i )
  {
    if ( Level.FindPlayer( i ) != NULL )
    {
      return false;
    }
    if ( ( Lives > 0 )
    ||   ( Player[i].Spawning )
    ||   ( Player[i].DeathDelay > 0 ) )
    {
      return false;
    }
  }
  return true;
}



void PlayState::PrepareLevel()
{
  Hint = "COLLECT ALL DOTS";
  ++LevelNumber;
  Level.Clear();
  Level.Generate();
  NumEnemiesSpawned = 0;
  PunishEnemiesSpawned = 0;
  TicksSinceLastDot = 0;
  SpawnList.clear();
  LevelIsCompleted = false;
  CaterpillarSpawned = false;
  for ( int i = 0; i < 5; ++i )
  {
    SpawnList.push_back( Pac::UT_GREEN_MASK );
  }
  for ( int i = 0; i < 10; ++i )
  {
    SpawnList.push_back( Pac::UT_RED_MASK );
    SpawnList.push_back( Pac::UT_WILD );
  }
  Bonus = 999 - LevelNumber * 50;
  if ( Bonus < 100 )
  {
    Bonus = 100;
  }
}



void PlayState::UpdateFixed()
{
  if ( Level.m_NumDots > 0 )
  {
    ++TicksSinceLastDot;
    if ( TicksSinceLastDot >= 400 )
    {
      TicksSinceLastDot = 0;
      // spawn punish enemy!
      if ( PunishEnemiesSpawned < 10 )
      {
        ++PunishEnemiesSpawned;

        GR::tPoint    pos = Level.FindPotentialPos();

        Level.LateSpawnUnitAtTile( pos.x, pos.y, Pac::UT_WILD );
      }
    }
  }
  if ( Bonus > 0 )
  {
    ++BonusTickDelay;
    if ( BonusTickDelay >= 10 )
    {
      BonusTickDelay = 0;
      --Bonus;
    }
  }
  if ( !CaterpillarSpawned )
  {
    if ( ( LevelNumber % 5 ) == 1 )
    {
      if ( rand() % 100 >= 98 )
      {
        GR::tPoint    pos = Level.FindPotentialPos();

        Level.LateSpawnUnitAtTile( pos.x, pos.y, Pac::UT_CATERPILLAR );
        CaterpillarSpawned = true;
      }
    }
  }

  for ( int i = 0; i < NumPlayers(); ++i )
  {
    if ( Player[i].DeathDelay > 0 )
    {
      --Player[i].DeathDelay;
    }
    else if ( ( Level.FindPlayer( i ) == NULL )
    &&        ( !Player[i].Spawning ) )
    {
      if ( Lives > 0 )
      {
        --Lives;
        SpawnPlayer( i );
      }
    }
  }
}



void PlayState::SpawnPlayer( int PlayerIndex )
{
  std::set<GR::tPoint>    potentialStartPos;

  for ( int i = 0; i < Level.m_Field.Width(); ++i )
  {
    for ( int j = 0; j < Level.m_Field.Height(); ++j )
    {
      if ( ( Level.m_Field.Field( i, j ) == Pac::FT_DOT )
      ||   ( Level.m_Field.Field( i, j ) == Pac::FT_EMPTY ) )
      {
        potentialStartPos.insert( GR::tPoint( i, j ) );
      }
    }
  }
  if ( potentialStartPos.empty() )
  {
    dh::Log( "No potential start pos!" );
    return;
  }
  int     randPos = rand() % potentialStartPos.size();

  std::set<GR::tPoint>::iterator    it( potentialStartPos.begin() );
  std::advance( it, randPos );
  GR::tPoint    potentialPos = *it;

  Level.LateSpawnUnitAtTile( potentialPos.x, potentialPos.y, Pac::UT_PLAYER, PlayerIndex );
  Player[PlayerIndex].Spawning = true;
}



