#include "Hero.hpp"

const double Hero::getRxz() const {
  return Graphics::get()->Near * 2;
}

const double Hero::getRy() const {
  return getRxz() * 2.5;
}

const Object& Hero::render() const {
  return *this;
}

Object& Hero::setActive(const bool active) {
  step = side = turn = 0;
  jump = false;
  return Object::setActive(active);
}

Object& Hero::simulate(const Time dt) {
  static Vector v;
  if (
    !isInAir()
  ) {
    const double s = getRy() * 7;
    static Vector speed;
    speed = getSpeed();
    speed.x = speed.z = 0;
    if (step) {
      speed += (
        (
          v = getDirection()
        ) *= s * step
      );
    }
    if (side) {
      speed += (
        (
          v = getDirection()
        ).rotateY(Math::PIdiv2) *= s * side
      );
    }
    if (jump) {
      speed.y += s * 4 / 3;
    }
    setSpeed(speed);
  }
  if (turn) {
    setDirection(
      (
        v = getDirection()
      ).rotateY(Math::PI * turn * dt)
    );
  }
  return Object::simulate(dt);
}

Input& Hero::onKey(
  const Key key,
  const bool isDown
) {
  if (isDown) {
    if (key == Forward) {
      step = 1;
    } else if (key == Backward) {
      step = - 1;
    } else if (key == Left) {
      turn = - 1;
    } else if (key == Right) {
      turn = 1;
    } else if (key == LStep) {
      side = - 1;
    } else if (key == RStep) {
      side = 1;
    } else if (key == Jump) {
      jump = true;
    }
  } else {
    if (key == Forward) {
      if (step > 0) {
        step = 0;
      }
    } else if (key == Backward) {
      if (step < 0) {
        step = 0;
      }
    } else if (key == Left) {
      if (turn < 0) {
        turn = 0;
      }
    } else if (key == Right) {
      if (turn > 0) {
        turn = 0;
      }
    } else if (key == LStep) {
      if (side < 0) {
        side = 0;
      }
    } else if (key == RStep) {
      if (side > 0) {
        side = 0;
      }
    } else if (key == Jump) {
      jump = false;
    }
  }
  return *this;
}
