import java.util.concurrent.ThreadLocalRandom;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Ellipse;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

/**
 * Displays an egg. Its shape and angle of rotation can be manipulated by key presses.
 * Clicking the mouse on either the egg or the background randomizes its color.
 *
 * @author Drue Coles
 */
public class EasterEgg extends Application {

    @Override
    public void start(Stage primaryStage) {
        StackPane root = new StackPane();
        Scene scene = new Scene(root, Color.DARKGREEN);

        // A colored rectangle is used to provide a background color. 
        final int rWidth = 500;
        final int rHeight = 400;
        final Rectangle background = new Rectangle(rWidth, rHeight);
        background.setFill(Color.DARKGREEN);

        // The egg is rendered as an Ellipse object. 
        final int eWidth = 170;
        final int eHeight = 100;
        final Ellipse egg = new Ellipse(eWidth, eHeight);
        egg.setFill(Color.HOTPINK);
        root.getChildren().addAll(background, egg);
       
        // The egg's shape and angle of rotation can be manipulated by key presses.
        class KeyHandler implements EventHandler<KeyEvent> {
            
            // The arrow keys stretch and shrink the egg. F11 and F12 rotate it. The space
            // bar turns it into a circle.
            @Override
            public void handle(KeyEvent event) {
                
                double radiusX = egg.getRadiusX();
                double radiusY = egg.getRadiusY();
                double angle = egg.getRotate();
                
                int minRadius = 10;
                int deltaRadius = 2; // change in radius from each event
                int deltaAngle = 10; // change in angle from each event
                
                KeyCode code = event.getCode();
                switch (code) {
                    
                    case LEFT: // shrink x-dimension
                        egg.setRadiusX(Math.max(minRadius, radiusX - deltaRadius));
                        break;
                        
                    case RIGHT: // stretch x-dimension
                        egg.setRadiusX(radiusX + deltaRadius);
                        break;
                        
                    case DOWN: // shrink y-dimension
                        egg.setRadiusY(Math.max(minRadius, radiusY - deltaRadius)); 
                        break;
                   
                    case UP: // stretch y-dimension
                        egg.setRadiusY(radiusY + deltaRadius);
                        break;  
                  
                    case F11:
                        egg.setRotate(angle - deltaAngle);
                        break;
                    case F12:
                        egg.setRotate(angle + deltaAngle);
                        break;
                        
                    case SPACE: // transform to a circle
                        double n = Math.min(radiusX, radiusY); 
                        egg.setRadiusX(n);
                        egg.setRadiusY(n);
                }
            }
        }
        scene.setOnKeyPressed(new KeyHandler());
        
        // Clicking the mouse on the egg or the background randomizes its color.
        class MouseHandler implements EventHandler<MouseEvent> {
            @Override
            public void handle(MouseEvent event) {

                if (event.getSource() == background) {
                    background.setFill(randomColor());
                } else {
                    egg.setFill(randomColor());
                }
                
                // A simpler approach relying on inheritance:
                //
                // Shape shape = (Shape) event.getSource();
                // shape.setFill(randomColor());                  
            }
        }
        MouseHandler mouseHandler = new MouseHandler();
        background.setOnMouseClicked(mouseHandler);
        egg.setOnMouseClicked(mouseHandler);
 
        primaryStage.setResizable(false);
        primaryStage.setTitle("Easter Egg");
        primaryStage.setScene(scene);
        primaryStage.show();
        primaryStage.setAlwaysOnTop(true);
    }

    /**
     * Returns a color with a randomly generated RGB value.
     */
    private static Color randomColor() {
        ThreadLocalRandom rand = ThreadLocalRandom.current();
        int r = rand.nextInt(256);
        int g = rand.nextInt(256);
        int b = rand.nextInt(256);
        return Color.rgb(r, g, b);
    }

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