#include "Wild.h"
#include ".\Level.h"
#include ".\GetEmGood.h"
#include "PlayState.h"
#include "Player.h"



Wild::Wild() :
  m_NumTilesToMove( 0 )
{
  m_Type = Pac::UT_WILD;
  SetAnimation( "Wild.Move" );

  m_HP = 3;
  m_MoveSpeed = 10;
  m_NewMoveDelay = 10;

  m_DisplayOffset.set( -( 48 - 16 ) / 2, -( 21 - 16 ) / 2 - 18 );
}



void Wild::UpdateFixed( PlayState& State )
{
  TiledMover::UpdateFixed( State );
}



void Wild::SetRandomPossibleDir( PlayState& State )
{
  std::set<Pac::eDir>   possibleDirections;

  if ( State.Level.CanMove( this, m_Position, Pac::DIR_N ) )
  {
    possibleDirections.insert( Pac::DIR_N );
  }
  if ( State.Level.CanMove( this, m_Position, Pac::DIR_S ) )
  {
    possibleDirections.insert( Pac::DIR_S );
  }
  if ( State.Level.CanMove( this, m_Position, Pac::DIR_W ) )
  {
    possibleDirections.insert( Pac::DIR_W );
  }
  if ( State.Level.CanMove( this, m_Position, Pac::DIR_E ) )
  {
    possibleDirections.insert( Pac::DIR_E );
  }

  if ( possibleDirections.empty() )
  {
    return;
  }
  std::set<Pac::eDir>::iterator    itP( possibleDirections.begin() );
  std::advance( itP, rand() % possibleDirections.size() );

  m_MoveDir = *itP;
  m_NumTilesToMove = 1 + rand() % 8;
}



void Wild::OnArrivedAtTile( PlayState& State )
{
  TiledMover::OnArrivedAtTile( State );
  m_TilePos = m_Position / 16;

  Pac::eDir     playerInDir = Pac::DIR_NONE;

  int     playerThere = -1;

  m_MoveDir = Pac::DIR_NONE;

  for ( int i = 0; i < State.NumPlayers(); ++i )
  {
    Player*   pPlayer = State.Level.FindPlayer( i );
    if ( pPlayer != NULL )
    {
      if ( ( math::absolute( pPlayer->m_TilePos.x - m_TilePos.x ) <= 1 )
      &&   ( math::absolute( pPlayer->m_TilePos.y - m_TilePos.y ) <= 1 ) )
      {
        // random
        if ( rand() % 2 )
        {
          if ( pPlayer->m_TilePos.y < m_TilePos.y )
          {
            playerInDir = Pac::DIR_N;
            break;
          }
          else if ( pPlayer->m_TilePos.y > m_TilePos.y )
          {
            playerInDir = Pac::DIR_S;
            break;
          }
        }
        else
        {
          if ( pPlayer->m_TilePos.x < m_TilePos.x )
          {
            playerInDir = Pac::DIR_W;
            break;
          }
          else if ( pPlayer->m_TilePos.x > m_TilePos.x )
          {
            playerInDir = Pac::DIR_E;
            break;
          }
        }
      }
      else if ( math::absolute( pPlayer->m_TilePos.x - m_TilePos.x ) <= 1 )
      {
        if ( pPlayer->m_TilePos.y < m_TilePos.y )
        {
          playerInDir = Pac::DIR_N;
          break;
        }
        else if ( pPlayer->m_TilePos.y > m_TilePos.y )
        {
          playerInDir = Pac::DIR_S;
          break;
        }
      }
      else if ( math::absolute( pPlayer->m_TilePos.y - m_TilePos.y ) <= 1 )
      {
        if ( pPlayer->m_TilePos.x < m_TilePos.x )
        {
          playerInDir = Pac::DIR_W;
          break;
        }
        else if ( pPlayer->m_TilePos.x > m_TilePos.x )
        {
          playerInDir = Pac::DIR_E;
          break;
        }
      }
    }
  }

  if ( playerInDir != Pac::DIR_NONE )
  {
    // don't get stuck on corners
    if ( State.Level.CanMove( this, m_Position, playerInDir ) )
    {
      m_NumTilesToMove = 1 + rand() % 8;
      m_MoveDir = playerInDir;
    }
    else
    {
      SetRandomPossibleDir( State );
    }
  }
  else if ( m_NumTilesToMove )
  {
    --m_NumTilesToMove;
    if ( State.Level.CanMove( this, m_Position, m_MoveDir ) )
    {
      return;
    }
    m_NumTilesToMove = 0;
    m_MoveDir = Pac::DIR_NONE;
  }
  else
  {
    if ( m_NumTilesToMove )
    {
      --m_NumTilesToMove;
    }
    else
    {
      if ( m_NewMoveDelay == 0 )
      {
        --m_NewMoveDelay;
        if ( m_NewMoveDelay == 0 )
        {
          // move random
          SetRandomPossibleDir( State );
        }
      }
      else
      {
        m_NewMoveDelay = 100 + rand() % 50;
      }
    }
  }
}



int Wild::DetermineMovementPoints( Pac::eDir Dir )
{
  return 1;
}



void Wild::ProcessEvent( PlayState& State, const eUnitEvent& Event )
{
  TiledMover::ProcessEvent( State, Event );
  switch ( Event )
  {
    case ET_BLOCKED_UP:
      break;
    case ET_FALL_START:
      break;
    case ET_FALL_END:
      break;
    case ET_ENTER_PLATFORM:
      break;
    case ET_LEAVE_PLATFORM:
      break;
    case ET_DIE:
      break;
  }
}



void Wild::OnLoad( PlayState& State )
{
  m_StartPosition = m_Position;
}



