#include "Car.hpp"
#include <logic/Logic.hpp>

Car::Wheel::Wheel() : CylinderMesh(
  8,
  1,
  true,
  true
) {
  rotateZ(Math::PIdiv2).centralize().setColor(
    Color(Color::White) /= 7
  );
  for (
    Vertices::iterator i = vertices.begin();
    i < vertices.end();
    i++
  ) {
    Vertex* v = *i;
    if (
      std::abs(v->z) < 0.25 && std::abs(v->y) < 0.25
    ) {
      v->x *= 0.8;
      *v = Color(Color::White) /= 2;
    }
  }
}

Car::Wheels::Wheels(
  const double r,
  const double dx,
  const double w
) : r(r) {
  Mesh* m = scale(
    r * w,
    r,
    r
  ).translate(
    dx / 2,
    0
  ).clone();
  *this += m->rotateY(Math::PI);
  delete m;
}

const Car::Wheels& Car::Wheels::render(
  const double z,
  const double rad
) const {
  static Matrix t;
  static Matrix r;
  Graphics::get()->push().apply(
    t.setTranslate(
      0,
      0,
      z
    ) *= r.setXRotation(rad)
  );
  Wheel::render();
  Graphics::get()->pop();
  return *this;
}

const double Car::getRy() const {
  if (rY == 0) {
    rY = getWheelR() - getWheelsY();
  }
  return rY;
}

const Car& Car::renderBody() const {
  MeshObject::renderMesh();
  return *this;
}

const MeshObject& Car::renderMesh() const {
  static Matrix m;
  Graphics::get()->push().apply(
    m.setTranslate(
      0,
      getRy() * (
        1 + sin(
          Logic::get()->getTimer() * Math::PImul2
        )
      ) / 0x20
    )
  );
  const Car& ret = renderBody();
  Graphics::get()->pop().push().apply(
    m.setTranslate(
      0,
      getWheelsY()
    )
  );
  renderWheels();
  Graphics::get()->pop();
  return ret;
}
