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

import java.util.BitSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;

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.BoxRender;
import nz.ac.massey.javaecs.examples.Components.Collider;
import nz.ac.massey.javaecs.examples.Components.Gravity;
import nz.ac.massey.javaecs.examples.Components.LogUpdate;
import nz.ac.massey.javaecs.examples.Components.Render;
import nz.ac.massey.javaecs.examples.Components.RidgidBody;
import nz.ac.massey.javaecs.examples.Components.TimedExistence;
import nz.ac.massey.javaecs.examples.Components.Vec2D;

public class ExistenceSystem extends ECSSystem{
    Engine gameEngine;
    Random rand;

    public ExistenceSystem(Engine gameEngine){
        this.gameEngine = gameEngine;
        // Set registrations
        registrationSet = new BitSet();
        registrationSet.set(gameEngine.getComponentIndex(TimedExistence.class));
        registrationSet.set(gameEngine.getComponentIndex(BoxRender.class));
    }

    @Override
    public void init() {
        rand = new Random();
        
    }

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

    public void update(double dt){
        Queue<Entity> deletions = new LinkedList<>();
        for (Entity entity : entities) {
            BoxRender shape = (BoxRender)gameEngine.getComponentData(entity, BoxRender.class);
            TimedExistence timedExistence = (TimedExistence)gameEngine.getComponentData(entity, TimedExistence.class);
            // Get the rate the fade should occur at our current frame rate.
            double fadeRate = timedExistence.lifeTime / dt; // I.e. might say 200 frames left
            // Fade the opacity
            shape.a -= shape.a / fadeRate;
            // Clauses to keep things safe
            if (shape.a < 0) shape.a = 0.;
            else if (shape.a > 1) shape.a = 1.;
            // Reduce the time the shape may continue living for
            timedExistence.lifeTime -= dt;

            if (timedExistence.lifeTime <= 0){
                deletions.add(entity);
            }
        }
        while (deletions.size() > 0){
            gameEngine.destroyEntity(deletions.remove());
        }
        // Finally, randomly add an entity as required
        if (rand.nextInt(16384) < 8){
            Entity newEnt = gameEngine.createEntity();
            gameEngine.addComponent(newEnt, Vec2D.class, new Vec2D(10 + rand.nextDouble()* 80, 10+ rand.nextDouble()* 80,0));
            gameEngine.addComponent(newEnt, RidgidBody.class, new RidgidBody(-2.5 + rand.nextDouble()* 5., 0., 0., 0., 0.f, 0., rand.nextDouble() * 20.));
            double size = 3 + rand.nextDouble() * 7;
            gameEngine.addComponent(newEnt, Collider.class, new Collider(size, size));
            gameEngine.addComponent(newEnt, Gravity.class, new Gravity(0, -9.80665, 45., 45.)); // Terminal velocity is 45 m/s
            gameEngine.addComponent(newEnt, Render.class, new Render(BoxRender.class));
            gameEngine.addComponent(newEnt, BoxRender.class, new BoxRender(size, size, 30 + rand.nextInt(225), 30 + rand.nextInt(225), 30 + rand.nextInt(225)));
            gameEngine.addComponent(newEnt, TimedExistence.class, new TimedExistence(5 + rand.nextDouble() * 90));
        }
    }
    
}
