#pragma once

#include "physics/particle.hpp"
#include "lib/fixed_length_list.hpp"

namespace physics {

  struct particle_force_generator
  {
    virtual void update_force(particle * particle, float duration) = 0;
  };

  struct particle_force_entry
  {
    physics::particle * particle;
    particle_force_generator * force_generator;

    bool operator==(const particle_force_entry&) const = default;
  };

  struct particle_force_registry
  {
    fixed_length_list<particle_force_entry, 64> registrations;

    void add(particle * particle, particle_force_generator * force_generator);
    void update_forces(float duration);
  };

  struct particle_gravity : particle_force_generator
  {
    vec3 gravity;

    particle_gravity(const vec3& gravity)
      : gravity(gravity)
    {}

    void update_force(particle * particle, float duration) override;
  };

  struct particle_drag : particle_force_generator
  {
    float k1;
    float k2;

    void update_force(particle * particle, float duration) override;
  };

  struct particle_spring : particle_force_generator
  {
    physics::particle * other;
    float spring_constant;
    float rest_length;

    void update_force(particle * particle, float duration) override;
  };

  struct particle_anchored_spring : particle_force_generator
  {
    vec3 * anchor;
    float spring_constant;
    float rest_length;
kk
    void update_force(particle * particle, float duration) override;
  };

  struct particle_bungee : particle_force_generator
  {
    physics::particle * other;
    float spring_constant;
    float rest_length;

    void update_force(particle * particle, float duration) override;
  };
}
