#include "ActionFollow.h"
#include "ActionMove.h"
#include "ActionWait.h"
#include "GroundMap.h"
#include "RenderableEntity.h"

using namespace RenderSystem;

ActionFollow::ActionFollow(Unit *u,unitEnumeration::UnitState state, Entity *e, bool loop) : UnitAction(u,state)
{
	unit= u;
	entity = e;
	distance = 0.0f;
	this->loop = loop;
}

ActionFollow::ActionFollow(Unit *u,unitEnumeration::UnitState state, Entity *e, float dist, bool loop) : UnitAction(u,state)
{
	unit= u;
	entity = e;
	distance = dist;
	this->loop = loop;
}

ActionFollow::~ActionFollow(void)
{
}

void ActionFollow::execute(void)
{
	/**
	 * on restaure l'etat de l'unité
	 */
	unit->setState(this->unitState);
	unit->allowDust(false);
	// si l'entité est morte, on arrete de la suivre
	if (!entity->isAlive()){
		dispose();
		return;
	}
	// distance sans altitude entre les 2 unités
	float dist = (unit->getPosition() - entity->getPosition()).getLength();

	//TODO: régler le pb du radius utilisé dans ActionMove: on ne peut pas se rapprocher plus que radius de l'entité
	if(dist > distance + unit->getRadius()+entity->getRadius()) {
		// il faut se rapprocher de l'unité
		// on verifie que l'ennemie est sur une case passable pour nous
		ground::GroundMap::getInstance().setCurrentUnit(unit);
		ground::Case * c = ground::GroundMap::getInstance().getCase(entity->getPosition().getX()+0.5f,entity->getPosition().getY()+0.5f);
		if (c == NULL || !c->isPassable()){
			// la case n'est pas passable, on attend
			unit->wait(25);
		}else{
			// la case est passable, on peut calculer un chemin
			ground::GroundMap::getInstance().computePath(unit->getPosition(),entity->getPosition());
			ground::GroundMap::getInstance().setCurrentUnit(NULL);
			if (ground::GroundMap::getInstance().haveFoundPath()){
				// on a trouvé un chemin
				path = ground::GroundMap::getInstance().getLastPath();
			}else{
				// on a pas trouvé de chemin mais on a quand même un chemin qui nous approche de notre but
				path = ground::GroundMap::getInstance().getLastPath();
			}

			if(path.size() >= 2) {
				unit->pushAction(this);
				unit->pushAction(new ActionMove(unit,this->unitState, path[1]));
			}else{
				dispose();
			}
		}
	} else {
		//on entretien l'action seulement si désiré
		if(this->loop) {
			unit->pushAction(this);
			// on attend 1 second avant de re verifier si on doit partir
			unit->pushAction(new ActionWait(this->unit,this->unitState,25));
		}else{
			// sinon, on la detruit
			dispose();
		}
	}
}

