// physics_world.hpp - Mundo físico 2D
// © 2025 Orni Attack
//
// Gestiona un conjunto de RigidBody, integra sus movimientos y detecta
// colisiones por frame. Diseño minimalista para arcade: broadphase trivial
// O(n²) suficiente para <50 cuerpos (15 enemigos + balas + paredes).
//
// Los RigidBody viven en las entidades (las entidades poseen sus bodies);
// PhysicsWorld solo guarda punteros no-owning. La entidad es responsable
// de añadir/quitar su body del mundo en init/destroy.

#pragma once

#include <SDL3/SDL.h>

#include <vector>

namespace Physics {

struct RigidBody;

class PhysicsWorld {
    public:
        PhysicsWorld() = default;

        // Añade un cuerpo al mundo (no toma ownership).
        void addBody(RigidBody* body);

        // Elimina un cuerpo. No-op si no está registrado.
        void removeBody(RigidBody* body);

        // Vacía la lista (no destruye los cuerpos).
        void clear() { bodies_.clear(); }

        // Define los límites del mundo (paredes implícitas). Pasa un rect
        // PLAYAREA para que los cuerpos reboten contra los bordes según su
        // restitution. Vacío = sin paredes.
        void setBounds(const SDL_FRect& bounds) {
            bounds_ = bounds;
            has_bounds_ = true;
        }
        void clearBounds() { has_bounds_ = false; }

        // Avanza la simulación dt segundos:
        //   1. Integra cada cuerpo (semi-implicit Euler + damping)
        //   2. Resuelve colisiones contra los bounds (si configurados)
        //   3. Resuelve colisiones cuerpo-cuerpo (impulsos elásticos)
        void update(float dt);

        // Consultas
        [[nodiscard]] auto getBodyCount() const -> std::size_t { return bodies_.size(); }
        [[nodiscard]] auto getBodies() const -> const std::vector<RigidBody*>& { return bodies_; }

    private:
        std::vector<RigidBody*> bodies_;
        SDL_FRect bounds_{0.0F, 0.0F, 0.0F, 0.0F};
        bool has_bounds_{false};

        void integrate(float dt);
        void resolveBoundsCollisions();
        void resolveBodyCollisions();
};

}  // namespace Physics
