#pragma once
#include "../Location.h"

/**
 * @brief A static location is a location whose boundaries (not content) does not evolve over time.
 */
class StaticLocation : public Location
{
public:
  StaticLocation()
    : m_id(s_id++)
  {
  }

  size_t getID() const
  {
    return m_id;
  }

  /**
   * @brief Computes the "oldest" tile in the location, i.e. the tile which was never visited or visited long ago.
   * @param location The location of which to scan the tiles.
   * return The oldest tile in the location.
   */
  virtual std::pair<BWAPI::TilePosition, int> getOldestVisibleTile() const = 0;

  virtual BWAPI::TilePosition getRandomTile() const = 0;

protected:
  template <class TileIterator>
  static std::pair<BWAPI::TilePosition, int> getOldestVisibleTile(TileIterator begin, TileIterator end)
  {
    const InfluenceMapRef<Visibility>::map_ptr map = Spar->getPerceptualState()->getVisibility();

    int min = boost::numeric::bounds<int>::highest();
    BWAPI::TilePosition minTile = BWAPI::TilePositions::None;
    for (; begin != end; ++begin)
    {
      BWAPI::TilePosition tile = *begin;
      const Visibility& visibility = map->getData(tile);
      if (visibility.lastVisible < min)
      {
        min = visibility.lastVisible;
        minTile = tile;
      }
    }
    return std::make_pair(minTile, min);
  }

  template <class TileIterator>
  static std::pair<BWAPI::TilePosition, int> getNewestVisibleTile(TileIterator begin, TileIterator end)
  {
    const InfluenceMapRef<Visibility>::map_ptr map = Spar->getPerceptualState()->getVisibility();

    int max = boost::numeric::bounds<int>::lowest();
    BWAPI::TilePosition maxTile = BWAPI::TilePositions::None;
    for (; begin != end; ++begin)
    {
      BWAPI::TilePosition tile = *begin;
      const Visibility& visibility = map->getData(tile);
      if (visibility.lastVisible > max)
      {
        max = visibility.lastVisible;
        maxTile = tile;
      }
    }
    return std::make_pair(maxTile, max);
  }

  /*
   * @brief This static location's ID.
   */
  const size_t m_id;

  static size_t s_id;

private :
  //const member prevent assignment operator
  StaticLocation& operator= (const StaticLocation&);

};
