package nz.ac.massey.javaecs.examples.Systems;

import java.util.BitSet;

import nz.ac.massey.javaecs.ECSSystem;
import nz.ac.massey.javaecs.Engine;
import nz.ac.massey.javaecs.Entity;
import nz.ac.massey.javaecs.examples.Components.Vec2D;
import nz.ac.massey.javaecs.examples.Components.RidgidBody;
import nz.ac.massey.javaecs.examples.Components.Collider;
import nz.ac.massey.javaecs.examples.Components.Gravity;

public class PhysicsSystem extends ECSSystem {
    Engine gameEngine;

    public PhysicsSystem(Engine gameEngine){
        this.gameEngine = gameEngine;
        // Set registrations
        registrationSet = new BitSet();
        registrationSet.set(gameEngine.getComponentIndex(Vec2D.class));
        registrationSet.set(gameEngine.getComponentIndex(RidgidBody.class));
        registrationSet.set(gameEngine.getComponentIndex(Gravity.class));
        registrationSet.set(gameEngine.getComponentIndex(Collider.class));
    }

    @Override
    public void init() {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void update() {
        // TODO Auto-generated method stub
        
    }

    public void update(double dt){
        for (Entity entity : entities) {
            Vec2D pos = (Vec2D)gameEngine.getComponentData(entity, Vec2D.class);
            RidgidBody ridgidBody = (RidgidBody)gameEngine.getComponentData(entity, RidgidBody.class);
            Gravity gravity = (Gravity)gameEngine.getComponentData(entity, Gravity.class);
            Collider collider = (Collider)gameEngine.getComponentData(entity, Collider.class);
            // Firstly, add the result of the accelerative forces to the ridgidbody
            ridgidBody.xVel += ridgidBody.xAcc * dt;
            ridgidBody.yVel += ridgidBody.yAcc * dt;
            // Set acceleration to zero (it has been processed/integrated and is now applied to the velocity);
            // use a constant-force component to apply acceleration each frame
            ridgidBody.xAcc = 0.;
            ridgidBody.yAcc = 0.;
            
            if (!collider.collided){
                // Special case of gravity
                if (gravity.terminalX < 0 || Math.abs(ridgidBody.xVel) < gravity.terminalX){
                    ridgidBody.xAcc += gravity.x;
                }
                if (gravity.terminalY < 0 || Math.abs(ridgidBody.yVel) < gravity.terminalY){
                    ridgidBody.yAcc += gravity.y;
                }
            }
            
            
            // Finally, move the vec2d by the new velocity
            pos.x += ridgidBody.xVel * dt;
            pos.y += ridgidBody.yVel * dt;
        }
    }    
}
