package nz.ac.massey.javaecs.examples;

import nz.ac.massey.javaecs.*;
import nz.ac.massey.javaecs.examples.Components.*;
import nz.ac.massey.javaecs.examples.Systems.*;

/**
 * Benchmark,
 * A port of https://github.com/abeimler/ecs_benchmark 
 */
public final class App {
    private App() {
    }

    /**
     * Says hello to the world.
     * @param args The arguments of the program.
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        int nEntities = 1_000_000;
        double startTime = System.nanoTime();
        Engine engine = new Engine(nEntities);
        double endTime = System.nanoTime();

        System.out.println("Constructor Time taken: " + (endTime - startTime) / 1e6+ " ms " + "("+ (endTime - startTime) / 1e9 + " seconds )");
        

        engine.registerComponent(ComflabulationComponent.class);
        engine.registerComponent(DirectionComponent.class);
        engine.registerComponent(PositionComponent.class);

        ComflabSystem comflabSystem = new ComflabSystem(engine);
        engine.registerSystem(ComflabSystem.class, comflabSystem);

        MovementSystem movementSystem = new MovementSystem(engine);
        engine.registerSystem(MovementSystem.class, movementSystem);

        startTime = System.nanoTime();

        for (int i = 0; i < nEntities; i++) {
            Entity entity = engine.createEntity();
            engine.addComponent(entity, PositionComponent.class, new PositionComponent());
            engine.addComponent(entity, DirectionComponent.class, new DirectionComponent());
            if (i % 2 != 0){
                engine.addComponent(entity, ComflabulationComponent.class, new ComflabulationComponent());
            }
            
        }
        endTime = System.nanoTime();

        System.out.println("Entity creation Time taken: " + (endTime - startTime) / 1e6+ " ms " + "("+ (endTime - startTime) / 1e9 + " seconds )");
        // Delay as object creation is multithreaded in at least OpenJDK 1.8 - lets use see the single core performance
        Thread.sleep(5000);
        double dt = 1.0f/60.0f;
        startTime = System.nanoTime();
        movementSystem.update(dt);
        comflabSystem.update(dt);
        endTime = System.nanoTime();

        System.out.println("Single Loop Time taken: " + (endTime - startTime) / 1e6+ " ms " + "("+ (endTime - startTime) / 1e9 + " seconds )");

        System.out.println("Hello World!");
    }
}
