import codedraw.CodeDraw;

import java.awt.*;
import java.util.Random;

/**
 * Simulates the formation of a massive solar system.
 */
public class Simulation3 {

    /**
     * The main simulation method using instances of other classes.
     */
    public static void main(String[] args) {
        CodeDraw cd = new CodeDraw();
        BodyLinkedList bodies = new BodyLinkedList();
        BodyForceTreeMap forceOnBody = new BodyForceTreeMap();

        Random random = new Random(2022);

        for (int i = 0; i < Simulation.NUMBER_OF_BODIES; i++) {
            bodies.addLast(new Body(
                    Math.abs(random.nextGaussian()) * Simulation.OVERALL_SYSTEM_MASS / Simulation.NUMBER_OF_BODIES,
                    new Vector3(
                            0.2 * random.nextGaussian() * Simulation.AU,
                            0.2 * random.nextGaussian() * Simulation.AU,
                            0.2 * random.nextGaussian() * Simulation.AU
                    ),
                    new Vector3(
                            0 + random.nextGaussian() * 5e3,
                            0 + random.nextGaussian() * 5e3,
                            0 + random.nextGaussian() * 5e3
                    )
            ));
        }

        long seconds = 0;
        while (true) {
            seconds++;

            BodyLinkedList mergedBodies = new BodyLinkedList();
            for (Body b1 : bodies) {
                BodyLinkedList colliding = bodies.removeCollidingWith(b1);
                for (Body b2 : colliding) {
                    b1 = b1.merge(b2);
                }
                mergedBodies.addLast(b1);
            }
            bodies = mergedBodies;

            for (Body b1 : bodies) {
                Vector3 force = new Vector3();
                for (Body b2 : bodies) {
                    if (b1 != b2) {
                        force = force.plus(b1.gravitationalForce(b2));
                    }
                }
                forceOnBody.put(b1, force);
            }

            for (Body body : bodies) {
                body.move(forceOnBody.get(body));
            }

            if ((seconds % 3600) == 0) {
                cd.clear(Color.BLACK);
                for (Body body : bodies) {
                    body.draw(cd);
                }
                cd.show();
            }
        }
    }
}
