package edu.bloomu.ch6b;

import java.util.concurrent.ThreadLocalRandom;
import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

/**
 * Draws a Sierpinski Triangle.
 *
 * @author Drue Coles
 */
public class Fractal extends Application {

    @Override
    public void start(Stage stage) {
        Pane root = new Pane();
        final int size = 500;
        Scene scene = new Scene(root, size, size, Color.BLACK);

        // three corners of an equilateral triangle
        final int gap = 10;
        Point2D p1 = new Point2D(size / 2, gap);
        Point2D p2 = new Point2D(gap, size - gap);
        Point2D p3 = new Point2D(size - gap, size - gap);

        final int dots = 100_000; // number of dots to draw
        
        // 1. Pick a corner at random (current point).
        // 2. Pick a corner at random (next point).
        // 3. Move current point halfway to next.
        // 4. Draw current point and go back to step 2.
        Point2D current = randomPoint(p1, p2, p3);        
        for (int i = 0; i < dots; i++) {
            Point2D next = randomPoint(p1, p2, p3);
            current = midpoint(current, next);
            
            // draw a dot at the current location
            double a = current.getX();
            double b = current.getY();
            Circle dot = new Circle(a, b, 1, Color.GOLD);
            root.getChildren().add(dot);
        }

        stage.setTitle("Sierpinski Triangle");
        stage.setScene(scene);
        stage.setAlwaysOnTop(true);
        stage.show();
    }

    /**
     * Returns one of three given points selected at random.
     */
    private Point2D randomPoint(Point2D a, Point2D b, Point2D c) {
        ThreadLocalRandom rand = ThreadLocalRandom.current();
        switch (rand.nextInt(3)) {
            case 0:
                return a;
            case 1:
                return b;
            default:
                return c;
        }
    }

    /**
     * Returns the midpoint of the line segment connecting two given points.
     */
    private Point2D midpoint(Point2D p, Point2D q) {
        double a = (p.getX() + q.getX()) / 2;
        double b = (p.getY() + q.getY()) / 2;
        return new Point2D(a, b);
    }

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