#include "Enemy.hpp"
#include <math/Plane.hpp>

std::vector<Object*> Play::Enemy::nests;

Object& Play::Enemy::setAction(const EnemyAction action) {
  if (action == Walk) {
    static Vector v;
    (
      v = getDirection()
    ) *= getRxz() * 2;
    setSpeed(
      v.x,
      v.z
    );
  }
  return TankEnemy::setAction(action);
}

Object& Play::Enemy::simulate(
  const EnemyAction action,
  const Object::Time dt
) {
  if (
    nest && !heroIsVisible()
  ) {
    static Vector v;
    (
      (
        v = nest->getPosition()
      ) -= getPosition()
    ).y = 0;
    static Plane p;
    switch (action) {
      case Walk:
        if (
          v.getLength() > nest->getRxz() / 3
          && 
          p.set(
            getDirection(),
            nest->getPosition()
          ).isFront(
            getPosition()
          )
        ) {
          return setAction(Turn);
        }
        break;
      case Turn:
        if (
          v.normalize().getDistance(
            getDirection()
          ) < 0.1
        ) {
          return setAction(Walk);
        }
    }
  }
  return TankEnemy::simulate(
    action,
    dt
  );
}

Object& Play::Enemy::onCollision(Object* object) {
  if (object == nullptr) {
    setAction(Termination);
  }
  return TankEnemy::onCollision(object);
}

const Matrix* Play::Enemy::getActivationMatrix() {
  for (
    unsigned int i = 0;
    i < nests.size();
    i++
  ) {
    nest = nests[
      std::rand() % nests.size()
    ];
    static Vector v;
    v = nest->getPosition();
    v.y += nest->getRy() + getRy();
    std::vector<Object*> collisions;
    if (
      getCollisions(
        collisions,
        v
      ) == 0 || (
        collisions.size() == 1 && collisions[0] == nest
      )
    ) {
      static Matrix ret;
      ret.setIdentity();
      ret._vector.position = v;
      ret._vector.direction = v.neg();
      return &ret;
    }
  }
  return nullptr;
}

Play::CyanEnemy::CyanEnemy() : Enemy(Color::Cyan) {
}

Play::WhiteEnemy::WhiteEnemy() : Enemy(Color::White) {
}
