#include "physics/body.hpp"
#include "physics/contact.hpp"

namespace physics {

  struct collision_primitive
  {
    rigid_body * body;
    mat4x4 offset;
    mat4x4 transform;

    inline void update_transform()
    {
      transform = body->transform_matrix * offset;
    }
  };

  struct collision_sphere : collision_primitive
  {
    float radius;
  };

  struct collision_plane : collision_primitive
  {
    vec3 normal;
    float distance;
  };

  struct collision_box : collision_primitive
  {
    vec3 half_size;
  };

  struct collision_data
  {
    contact * const contacts;
    int ix;
    int length; // const

    // what...
    float restitution; // const
    float friction; // const

    collision_data(contact * contacts,
                   int length,
                   float restitution,
                   float friction)
      : contacts(contacts), ix(0), length(length), restitution(restitution), friction(friction)
    {}

    inline contact * add_contact()
    {
      contact * contact = &contacts[ix];
      ix += 1;
      return contact;
    }
  };

  struct collision_detector
  {
    static int sphere_and_sphere(const collision_sphere& a,
                                 const collision_sphere& b,
                                 collision_data& data);

    static int sphere_and_halfspace(const collision_sphere& sphere,
                                    const collision_plane& plane,
                                    collision_data& data);

    static int sphere_and_plane(const collision_sphere& sphere,
                                const collision_plane& plane,
                                collision_data& data);

    static int box_and_halfspace(const collision_box& box,
                                 const collision_plane& plane,
                                 collision_data& data);
  };

}
