#include "stdafx.h"
#include "Region.h"
#include "Chokepoint.h"
#include "Map.h"
#include "Tile.h"
#include "../../../PerceptualState.h"

void Region::addChokepoint(Chokepoint* chokepoint)
{
  if(!(
    // Remove chokepoint blocked by generators in Benzene
    (chokepoint->getChokepoint()->getSides().first == BWAPI::Position(4000, 1088) && chokepoint->getChokepoint()->getSides().second == BWAPI::Position(4088, 1088))
    || (chokepoint->getChokepoint()->getSides().first == BWAPI::Position(0, 1064) && chokepoint->getChokepoint()->getSides().second == BWAPI::Position(88, 1064))
    // Remove chokepoint blocked by minerals in Destination
    || (chokepoint->getChokepoint()->getSides().first == BWAPI::Position(1708, 204) && chokepoint->getChokepoint()->getSides().second == BWAPI::Position(1752, 248))
    || (chokepoint->getChokepoint()->getSides().first == BWAPI::Position(1288, 3832) && chokepoint->getChokepoint()->getSides().second == BWAPI::Position(1331, 3870))
    // Remove chokepoint blocked by doors in Fortress
    || (chokepoint->getChokepoint()->getSides().first == BWAPI::Position(744, 3304) && chokepoint->getChokepoint()->getSides().second == BWAPI::Position(784, 3320))
    || (chokepoint->getChokepoint()->getSides().first == BWAPI::Position(808, 848) && chokepoint->getChokepoint()->getSides().second == BWAPI::Position(848, 840))
    || (chokepoint->getChokepoint()->getSides().first == BWAPI::Position(3112, 904) && chokepoint->getChokepoint()->getSides().second == BWAPI::Position(3152, 920))
    || (chokepoint->getChokepoint()->getSides().first == BWAPI::Position(3424, 3374) && chokepoint->getChokepoint()->getSides().second == BWAPI::Position(3472, 3368))
    ))
  {
    std::pair<Region*, Region*> regions = chokepoint->getRegions();
    Region* otherRegion = regions.first == this ? regions.second : regions.first;
    assert(otherRegion != this);
    m_chokepoints.insert(std::make_pair(chokepoint, otherRegion));
    m_adjacentRegions.insert(std::make_pair(otherRegion, chokepoint));
  }
}

bool Region::isInLocation(BWAPI::Position position) const
{
  return m_parent->getRegion(BWAPI::TilePosition(position)) == this;
}

bool Region::isInLocation(BWAPI::TilePosition tile) const
{
  return m_parent->getRegion(tile) == this;
}

// m_subLocations are exclusively Tiles

class ConvertToTilePosition : public std::unary_function<const AutoPopulatedLocation*, BWAPI::TilePosition>
{
public:
  BWAPI::TilePosition operator()(const AutoPopulatedLocation* subLocation) const
  {
    assert(dynamic_cast<const Tile*>(subLocation) != NULL);
    return *dynamic_cast<const Tile*>(subLocation);
  }
};

std::pair<BWAPI::TilePosition, int> Region::getOldestVisibleTile() const
{
  return StaticLocation::getOldestVisibleTile(
    boost::make_transform_iterator(m_subLocations.begin(), ConvertToTilePosition()),
    boost::make_transform_iterator(m_subLocations.end(), ConvertToTilePosition()));
}

std::pair<BWAPI::TilePosition, int> Region::getNewestVisibleTile() const
{
  return StaticLocation::getNewestVisibleTile(
    boost::make_transform_iterator(m_subLocations.begin(), ConvertToTilePosition()),
    boost::make_transform_iterator(m_subLocations.end(), ConvertToTilePosition()));
}

BWAPI::TilePosition Region::getRandomTile() const
{
  const AutoPopulatedLocation* subLocation = m_subLocations[rand() % m_subLocations.size()];
  
  assert(dynamic_cast<const Tile*>(subLocation) != NULL);
  return *dynamic_cast<const Tile*>(subLocation);
}