#include <math.h>
// better hope you were paying attention in physics class for this one
#include "physics.h"
#include "world.h"
#include "config.h"

// Main physics update loop for all entities
void UpdateEntities(float dt, int screenWidth)
{
    // Iterate through all possible entities
    for (int i = 0; i < MAX_ENTITIES; i++)
    {
        Entity *e = &entities[i];

        // Skip inactive entities
        if (!e->active)
            continue;

        // Check if entity is currently touching the ground
        // YOU'RE GROUNDED!!! lol
        bool onGround = IsGrounded(e);

        // Apply gravity force if enabled for this entity
        if (e->affectedByGravity)
        {
            ApplyForce(
                e,
                (Vector2){0, e->mass * g}
            );
        }

        // Compute acceleration from accumulated forces (F = ma)
        e->acceleration.x =
        e->force.x / e->mass;

        e->acceleration.y =
        e->force.y / e->mass;

        // Integrate velocity from acceleration
        e->velocity.x +=
        e->acceleration.x * dt;

        e->velocity.y +=
        e->acceleration.y * dt;

        // Apply air drag to slow movement over time
        e->velocity.x *= AIR_DRAG;
        e->velocity.y *= AIR_DRAG;

        // Apply ground friction when on the ground
        if (onGround)
        {
            if (e->velocity.x > 0)
            {
                e->velocity.x -=
                GROUND_FRICTION * dt;

                if (e->velocity.x < 0)
                    e->velocity.x = 0;
            }
            else if (e->velocity.x < 0)
            {
                e->velocity.x +=
                GROUND_FRICTION * dt;

                if (e->velocity.x > 0)
                    e->velocity.x = 0;
            }
        }

        // Clamp player horizontal speed
        if (e->isPlayer)
        {
            if (e->velocity.x > MAX_PLAYER_SPEED)
                e->velocity.x = MAX_PLAYER_SPEED;

            if (e->velocity.x < -MAX_PLAYER_SPEED)
                e->velocity.x = -MAX_PLAYER_SPEED;
        }

        // Integrate position from velocity
        e->position.x +=
        e->velocity.x * dt;

        e->position.y +=
        e->velocity.y * dt;

        // Reset forces after integration step
        e->force = (Vector2){0, 0};

        // Ground collision
        if (e->position.y +
            e->size * 0.5f >=
            ground_y)
        {
            e->position.y =
            ground_y -
            e->size * 0.5f;

            e->velocity.y *=
            -BOUNCE;

            // Stop tiny bounces... or at least, attempt to.
            if (fabsf(e->velocity.y) < 15.0f)
            {
                e->velocity.y = 0;
            }
        }

        // Left wall collision
        if (e->position.x -
            e->size * 0.5f < 0)
        {
            e->position.x =
            e->size * 0.5f;

            e->velocity.x *= -0.6f;
        }

        // Right wall collision
        if (e->position.x +
            e->size * 0.5f >
            screenWidth)
        {
            e->position.x =
            screenWidth -
            e->size * 0.5f;

            e->velocity.x *= -0.6f;
        }
    }
}
