#include "ActionCharge.h"
#include "GroundMap.h"
#include "ActionFollow.h"
#include "ActionWait.h"

#include "MemoryManager/debugNew.h"

using namespace ground;

ActionCharge::ActionCharge(Unit* u,unitEnumeration::UnitState state,EnnemyUnit* ennemy) : ActionHit(u,state, ennemy){
}

ActionCharge::~ActionCharge(void){
}

void ActionCharge::execute(){

	/**
	 * on restaure l'etat de l'unité
	 */
	unit->setState(this->unitState);
	unit->allowDust(true);
	// si l'unité est morte, on arrete de la charger
	if(!ennemy->isAlive()){
		dispose();
		return;
	}
	if (unit->isMounted()){
		// distance sans altitude entre les 2 unités
		float distance = (unit->getPosition() - ennemy->getPosition()).getLength();
		unit->setOrientation(unit->getPosition().getAngle(ennemy->getPosition()));

		if(distance > unit->getWeapon()->maxRange) {
			// l'unité n'est pas à porté, on doit se rapprocher de l'ennemy
			timeBeforeHit = unit->getWeapon()->weaponSpeed;
			unit->pushAction(this);
			unit->pushAction(new ActionFollow(unit,this->unitState, ennemy->getUnit(), unit->getWeapon()->maxRange-(unit->getRadius()+ennemy->getRadius()), false));
			return;
		} else if(timeBeforeHit>0) {
			// on ne tappe pas tout de suite, il faut attendre encore..
			timeBeforeHit--;
			unit->pushAction(this);
			// on deplace l'unité
			move();

		} else {
			// on donne le coup
			processHit();

			// a-t-on tué l'ennemy? si non, on continu de l'attaquer
			if(!ennemy->isAlive()){
				ennemy->setState(EnnemyUnit::DEAD);
				dispose();
			} else {
				unit->attack(*ennemy);
				dispose();
			}
			// on deplace l'unité
			move();

		} // fin de else
	}else{
		dispose();
		unit->pushAction(new ActionHit(this->unit,this->unitState,this->ennemy));
	}


}

void ActionCharge::move(){
	// on deplace l'unité
	float distance = (unit->getPosition() - ennemy->getPosition()).getLength();
	//float speed = unit->getSpeed();
	float speed;
	// on prend le min des vitesse des 2 unités pour eviter qu'elle ne se colle trop.
	if (unit->getSpeed() < ennemy->getUnit()->getSpeed()){
		speed = unit->getSpeed();
	}else{
		speed = ennemy->getUnit()->getSpeed();
	}
	
	unit->setOrientation(unit->getPosition().getAngle(ennemy->getPosition()));

	if(distance > unit->getRadius() ) {
		// on ne pourra pas atteindre le point mais on s'en rapproche
		Point2D deplacement = (ennemy->getPosition() - unit->getPosition())*speed;
		Point2D arrive = unit->getPosition() + deplacement;
		// on verifie qu'on peut bien passer sur la case
		GroundMap& groundMap = GroundMap::getInstance();
		Case * c = groundMap.getCase((int)(arrive.getX()+0.5f),(int)(arrive.getY()+0.5f));
		if (c->isPassable() && c->getGroundType() != ground::FOREST && c->getGroundType() != ground::OREE){
			unit->setPosition(arrive);
		}else{
			unit->pushAction(new ActionWait(unit,this->unitState,25));
		}
	}

	// on est en attaque, on prépare le coup
	if(unit->getCurrentAnimation()!=RenderSystem::RenderableEntity::FIGHT){
		unit->setAnimation(RenderSystem::RenderableEntity::FIGHT, unit->isMounted());
	}
	// ici getMount ne peut pas retourner NULL car on est monté...
	if (unit->getMount()->getCurrentAnimation() != RenderSystem::RenderableEntity::WALK){
		unit->getMount()->setAnimation(RenderSystem::RenderableEntity::WALK);
	}

}

