#include "stdafx.h"
#include "BaseLocation.h"
#include "Region.h"
#include "../../../PerceptualState.h"
#include "../../../../Utils/BresenhamCircle.h"

const int BASE_LOCATION_TILE_RADIUS = 4;

struct AddTile : std::binary_function<int,int,void>
{
  AddTile(const BWTA::BaseLocation* baseLocation)
    : m_center(baseLocation->getTilePosition())
  {}

  void operator()(int x, int y)
  {
    m_tiles.push_back(m_center + BWAPI::TilePosition(x,y));
  }

  const std::vector<BWAPI::TilePosition>& getResult() const
  {
    return m_tiles;
  }

private:
  const BWAPI::TilePosition m_center;
  std::vector<BWAPI::TilePosition> m_tiles;

  AddTile& operator=(const AddTile &);
};

BaseLocation::BaseLocation(const BWTA::BaseLocation* baseLocation, Region* parent)
  : m_parent(parent)
  , m_baseLocation(baseLocation)
  , m_tiles(BresenhamCircle(AddTile(baseLocation), BASE_LOCATION_TILE_RADIUS, true).getResult())
{
}

bool BaseLocation::hasEnemyArmyUnits() const
{
  std::set<BWAPI::Unit*> enemyUnits = Spar->getPerceptualState()->getEnemyUnits(CircularLocation(getCurrentCenter(), BASE_LOCATION_TILE_RADIUS * TILE_SIZE));
  for (std::set<BWAPI::Unit*>::const_iterator it = enemyUnits.begin(); it != enemyUnits.end(); ++it)
  {
    BWAPI::Unit* unit = *it;
    if (!unit->getType().isWorker() && (unit->getType().groundWeapon() != BWAPI::WeaponTypes::None || unit->getType() == BWAPI::UnitTypes::Protoss_High_Templar))
      return true;
  }
  return false;
}

bool BaseLocation::isInLocation(BWAPI::Position position) const
{
  return CircularLocation(m_baseLocation->getPosition(), BASE_LOCATION_TILE_RADIUS * TILE_SIZE).isInLocation(position);
}

bool BaseLocation::isInLocation(BWAPI::TilePosition tile) const
{
  return CircularLocation(m_baseLocation->getPosition(), BASE_LOCATION_TILE_RADIUS * TILE_SIZE).isInLocation(tile);
}

std::pair<BWAPI::TilePosition, int> BaseLocation::getOldestVisibleTile() const
{
  return StaticLocation::getOldestVisibleTile(m_tiles.begin(), m_tiles.end());
}

BWAPI::TilePosition BaseLocation::getRandomTile() const
{
  return m_tiles[rand() % m_tiles.size()];
}

int BaseLocation::getLastVisible() const
{
  // Return the last visible frame of the resource depot position
  return Spar->getPerceptualState()->getVisibility()->getData(m_baseLocation->getTilePosition()).lastVisible;
}