#pragma once
#include "CompositeLocation.h"
#include <set>

class Map;
class Chokepoint;
class BaseLocation;
class Tile;

/**
 * @brief Output from BWTA algorithm that decomposes the map into connected components.
 *        Regions are connected to other regions via chokepoints.
 */
class Region : public CompositeLocation
{
public:
  Region(BWTA::Region* region, Map* parent)
    : m_parent(parent)
    , m_region(region)
  {
  }

  ~Region()
  {
  }

  Map* getParent() const
  {
    return m_parent;
  }

  virtual BWAPI::Position getCurrentCenter() const
  {
    return m_region->getCenter();
  }

  virtual bool isInLocation(BWAPI::Position position) const;
  virtual bool isInLocation(BWAPI::TilePosition tile) const;

  virtual std::pair<BWAPI::TilePosition, int> getOldestVisibleTile() const;
  virtual std::pair<BWAPI::TilePosition, int> getNewestVisibleTile() const;

  virtual BWAPI::TilePosition getRandomTile() const;

  const std::set<std::pair<Chokepoint*, Region*>>& getChokepoints() const
  {
    return m_chokepoints;
  }

  const std::set<std::pair<Region*, Chokepoint*>>& getAdjacentRegions() const
  {
    return m_adjacentRegions;
  }

  const std::set<BaseLocation*>& getBaseLocations() const
  {
    return m_baseLocations;
  }

  //const BWTA::Region* getBWTARegion() const
  //{
  //  return m_region;
  //}

protected:
  friend class Map;

  void addChokepoint(Chokepoint* chokepoint);

  void addBaseLocation(BaseLocation* baseLocation)
  {
    m_baseLocations.insert(baseLocation);
  }

  virtual void _output(std::ostream& out) const
  {
    out << "Region " << m_region->getCenter();
  }

  Map* const m_parent;
  BWTA::Region* const m_region;
  std::set<std::pair<Chokepoint*, Region*>> m_chokepoints;
  std::set<std::pair<Region*, Chokepoint*>> m_adjacentRegions;
  std::set<BaseLocation*> m_baseLocations;
};

