#include "stdafx.h"
#include "FleeingAirUnitBehavior.h"
#include "../Pathfinding.h"
#include "../../../../PerceptualState/PerceptualState.h"

FleeingAirUnitBehavior::FleeingAirUnitBehavior(const Process* parent, unsigned int initialPriority, BWAPI::Unit* unit, AutoPtr<Location> fleeingArea)
: UnitBehaviorT(parent, initialPriority, unit)
, UnitBehavior(parent, initialPriority, unit)
, Behavior(parent, initialPriority)
, FSM(parent)
, Process(parent)
, m_fleeingArea(fleeingArea)
, m_fleeingState(*this)
, m_states(m_fleeingState)
{}

class IsObstacle
{
  AutoPtr<Location> m_loc;
public:
  IsObstacle(AutoPtr<Location> loc) 
    : m_loc(loc) {}

  bool operator()(BWAPI::TilePosition, BWAPI::TilePosition pos2) const
  {
    //return !m_loc->isInLocation(pos2) || CorsairHarassmentBehavior::isObstacle(pos2); // Spar->getPerceptualState()->getEnemyThreat(pos2).futureAir > 0;
    
    return !m_loc->isInLocation(pos2) || BWAPI::isOnFrontier(pos2);
  }
};

class Comparer
{
  BWAPI::TilePosition m_origin;
public:
  Comparer(BWAPI::Unit * unit) : m_origin(unit->getTilePosition()) {}

  bool operator()(const BWAPI::TilePosition &left, const BWAPI::TilePosition &right)
  {
    const InfluenceMapRef<Threat>::map_ptr th = Spar->getPerceptualState()->getEnemyThreat();
    double thL = th->getData(left).futureAir, thR = th->getData(right).futureAir;
    if(thL == thR)
      return m_origin.getDistance(left) > m_origin.getDistance(right);

    return thL > thR;
  }
};

void FleeingAirUnitBehavior::Fleeing::onTimer()
{
  const InfluenceMapRef<Threat>::map_ptr th = Spar->getPerceptualState()->getEnemyThreat();
  if(!m_currentSafeSpot.isValid() || th->getData(m_currentSafeSpot).futureAir > 0)
  {
    m_currentSafeSpot = Spar->getPerceptualState()->getSafeRetreatPosition(m_context.m_unit);

    //m_currentSafeSpot = BWAPI::TilePositions::Invalid;
    //std::priority_queue<BWAPI::TilePosition, std::vector<BWAPI::TilePosition>, Comparer> tiles(Comparer(m_context.m_unit));
    //tiles.push(m_context.m_unit->getTilePosition());
    //
    //TileSet closed;
    //closed.insert(tiles.top());
    //IsObstacle eval(m_context.m_fleeingArea);

    //BWAPI::TilePosition neighbors[8];
    //while(!tiles.empty())
    //{
    //  const BWAPI::TilePosition &top = tiles.top();
    //  if(th->getData(top).futureAir == 0)
    //  {
    //    m_currentSafeSpot = top;
    //    break;
    //  }

    //  int k = getNeighbors(top, eval, neighbors);
    //  tiles.pop();
    //  for(int i = 0; i < k; ++i)
    //  {
    //    if(closed.count(neighbors[i]) == 0)
    //    {
    //      tiles.push(neighbors[i]);
    //      closed.insert(neighbors[i]);
    //    }
    //  }
    //}
  }
  if(m_currentSafeSpot.isValid())
  {
    if(m_context.m_unit->getPosition().getApproxDistance(m_currentSafeSpot) < TILE_SIZE)
      m_context.terminate(m_context.Success);
    else
      m_context.m_unit->move(m_currentSafeSpot);
  }
}
