/*
 * FXGL - JavaFX Game Library. The MIT License (MIT).
 * Copyright (c) AlmasB (almaslvl@gmail.com).
 * See LICENSE for details.
 */

package sandbox.benchmark;

import com.almasb.fxgl.app.GameApplication;
import com.almasb.fxgl.app.GameSettings;
import com.almasb.fxgl.core.math.FXGLMath;
import com.almasb.fxgl.dsl.components.RandomMoveComponent;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.entity.EntityFactory;
import com.almasb.fxgl.entity.SpawnData;
import com.almasb.fxgl.entity.Spawns;
import com.almasb.fxgl.physics.CollisionDetectionStrategy;
import javafx.geometry.Rectangle2D;
import javafx.scene.text.Font;
import javafx.scene.text.Text;

import java.util.Map;

import static com.almasb.fxgl.dsl.FXGL.*;

/**
 * A benchmark demo that uses lightweight FXGL physics.
 *
 * @author Almas Baimagambetov (AlmasB) (almaslvl@gmail.com)
 */
public class PhysicsBenchmarkSample extends GameApplication {

    private static final int NUM_OBJECTS = 300;

    private int frames;
    private int numCollisions = 0;

    private Text text;

    private enum Type {
        BALL, NOTHING, TYPE_A, TYPE_B, TYPE_C, TYPE_D, TYPE_E, TYPE_F
    }

    @Override
    protected void initSettings(GameSettings settings) {
        settings.setWidth(1280);
        settings.setHeight(720);
        settings.setProfilingEnabled(true);
        settings.setCollisionDetectionStrategy(CollisionDetectionStrategy.BRUTE_FORCE);
        settings.setRandomSeed(225);
    }

    @Override
    protected void initGameVars(Map<String, Object> vars) {
        vars.put("collisions", 0);
    }

    @Override
    protected void initGame() {
        frames = 0;

        getGameWorld().addEntityFactory(new BenchmarkFactory());

        for (int i = 0; i < NUM_OBJECTS; i++) {
            spawn("ball", FXGLMath.randomPoint(new Rectangle2D(0, 0, getAppWidth() - 64, getAppHeight() - 64)));
        }

        text = new Text("");
        text.setFont(Font.font(32));

        addUINode(text, 100, getAppHeight() - 40);
    }

    @Override
    protected void initPhysics() {
        onCollision(Type.BALL, Type.BALL, (b1, b2) -> {
            numCollisions++;
        });

        // some extra handlers
        for (int i = 0; i < Type.values().length; i++) {
            for (int j = i + 1; j < Type.values().length; j++) {
                onCollision(Type.values()[i], Type.values()[j], (b1, b2) -> {
                    numCollisions++;
                });
            }
        }
    }

    @Override
    protected void onUpdate(double tpf) {
        text.setText("Collisions: " + numCollisions);
        numCollisions = 0;

        frames++;

        // at 60fps this should finish in 100 sec
        if (frames == 6000) {
            getGameController().exit();
        }
    }

    public static class BenchmarkFactory implements EntityFactory {

        @Spawns("ball")
        public Entity newEntity(SpawnData data) {
            return entityBuilder(data)
                    .type(Type.BALL)
                    //.type(FXGLMath.randomBoolean() ? Type.BALL : Type.NOTHING)
                    .viewWithBBox("brick.png")
                    .collidable()
                    //.rotate(random(5, 105))
                    //.with(new RandomMoveComponent(new Rectangle2D(0, 0, getAppWidth() - 64, getAppHeight() - 64), random(10, 200)).withoutRotation())
                    .build();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

@@ -246,110 +246,8 @@
 gs;%0A
-import com.almasb.fxgl.core.math.FXGLMath;%0Aimport com.almasb.fxgl.dsl.components.RandomMoveComponent;%0A
 impo
@@ -404,16 +404,62 @@
 Spawns;%0A
+import com.almasb.fxgl.physics.BoundingShape;%0A
 import c
@@ -520,35 +520,38 @@
 ort 
-javafx.geometry.Rectangle2D
+com.almasb.fxgl.physics.HitBox
 ;%0Aim
@@ -632,16 +632,41 @@
 til.Map;
+%0Aimport java.util.Random;
 %0A%0Aimport
@@ -762,16 +762,55 @@
 hysics.%0A
+ * no rotation = 843%0A * rotation = 970%0A
  *%0A * @a
@@ -977,24 +977,59 @@
 CTS = 300;%0A%0A
+    private static Random random;%0A%0A
     private 
@@ -1474,45 +1474,8 @@
 E);%0A
-        settings.setRandomSeed(225);%0A
     
@@ -1635,24 +1635,59 @@
 nitGame() %7B%0A
+        random = new Random(225L);%0A
         fram
@@ -1825,106 +1825,283 @@
     
-spawn(%22ball%22, FXGLMath.randomPoint(new Rectangle2D(0, 0, getAppWidth() - 64, getAppHeight() - 64))
+var x = random.nextDouble() * (1280 - 64.0);%0A            var y = random.nextDouble() * (720 - 64.0);%0A            spawn(%22ball%22, x, y);%0A        %7D%0A%0A        // with rotation%0A        getGameWorld().getEntities().forEach(e -%3E %7B%0A            e.setRotation(random.nextDouble() * 180.0
 );%0A 
@@ -2100,32 +2100,34 @@
 80.0);%0A        %7D
+);
 %0A%0A        text =
@@ -3326,16 +3326,8 @@
 view
-WithBBox
 (%22br
@@ -3361,65 +3361,84 @@
    .
-collidable()%0A                    //.rotate(random(5, 105)
+bbox(new HitBox(BoundingShape.box(64, 64)))%0A                    .collidable(
 )%0A  

allow easy change of benchmark params