//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
/** @author   Casey Bowman
 *  @version  1.1
 *  @date     Tue Mar 10 13:52:41 EDT 2015 
 *  @see      (License) MIT style license
 */

import javafx.application.Application; 
import javafx.scene.Group; 
import javafx.scene.Scene; 
import javafx.scene.paint.Color; 
import javafx.scene.shape.Rectangle; 
import javafx.stage.Stage; 
import javafx.scene.layout.Pane;
import javafx.scene.input.MouseEvent;
import javafx.event.EventHandler;
import java.util.Arrays;
import java.util.Random;

//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
/** A simple javafx application to display a rectangle in a window.
 *  @const screenWidth   the width of the window
 *  @const screenHeight  the height of the window
 *  @const rectWidth     the width of the rectangle
 *  @const rectHeight    the height of the rectangle
 *  @const rectX         the x-coordinate of the top left corner of the rectangle
 *  @const rectY         the y-coordinate of the top left corner of the rectangle
 *  @const step          the max step size for the movement of the rectangle
 *  @const bord          makes sure the rectangle stays away from the edges
 *  @const rand          a random number generator
 *  @const root          the group to which the scene belongs
 *  @const scene         the scene for this window
 *  @const pane          a pane to hold the rectangle 
 */
public class FXRectangleMove extends Application
{
    private int screenWidth  = 600;
    private int screenHeight = 600;
  
    private int rectWidth  = 100;
    private int rectHeight = 100;

    private int rectX = 100;
    private int rectY = 100;

    private int step = 300;
    private int bord = 10;

    private Random rand = new Random ();

    Group root  = new Group ();
    Scene scene = new Scene (root, screenWidth, screenHeight, Color.web ("#33CC99"));     // the scene needs a group, width, height, and color
    Pane pane   = new Pane ();

    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    /** Main method.  Calls internal method launch (String[])
     *  of Application class.
     */
    public static void main (String[] args)
    {
        launch (args);
    } // main

    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    /** start method.  Called by launch.  Directs the creation of 
     *  components and windows for the fx application.
     *  @param stage  the stage for this application
     */
    @Override
    public void start (Stage stage)
    {        
        Rectangle r = makeRect (rectX, rectY, rectWidth, rectHeight);  
        setListener (r);
        setRect (r);      
        addRect (r);   
        addPane ();
        showWindow (stage);
    }

    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    /** this method creates a Rectangle of the appropriate size.
     *  @param x  the x-coordinate for the top left corner of the rectangle
     *  @param y  the y-coordinate for the top left corner of the rectangle
     *  @param w  the width of the rectangle
     *  @param h  the height of the rectangle
     */
    public Rectangle makeRect (int x, int y, int w, int h) { return new Rectangle (x, y, w, h); }
     
    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    /** This method will create a mouse click listener for the rectangle.
     *  setOnMouseClicked creates an EventHandler object.
     *
     *  @param r  the rectangle
     */
    public void setListener (Rectangle r)
    {
        r.setOnMouseClicked (new EventHandler  ()
        {
            //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::
            /** The handle method for this EventHandler object must be
             *  overridden.  In this case, the method calls a method to
             *  move the rectangle, and another method to color it.
             *
             *  @param t  the mouse event that was triggered
             */
            @Override
            public void handle (MouseEvent t)
            {
                moveRect  ();
                colorRect ();
            }

            //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
            /** moveRect handles the movement of the rectangle by grabbing
             *  two random integers from rand.  It then computes a new 
             *  x-coordinate and a new y-coordinate.  If these would put 
             *  the rectangle off the screen, then they are changed.
             */
            public void moveRect ()
            {
                int xdiff = rand.nextInt (step) - step / 2;
                int ydiff = rand.nextInt (step) - step / 2;
                int currX = (int) r.getX ();
                int currY = (int) r.getY ();
                int newX  = currX + xdiff;
                int newY  = currY + ydiff;
                if (newX < bord || newX > screenWidth  - rectWidth  - bord) newX = currX - xdiff;
                if (newY < bord || newY > screenHeight - rectHeight - bord) newY = currY - ydiff;
                r.setX (newX);
                r.setY (newY);
            }
 
            //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
            /** colorRect grabs three random doubles from rand that are by
             *  default between 0 and 1, which are then used to create a new 
             *  color.
             */
            public void colorRect ()
            {
                double[] rgb = new double[3];
                for (int i = 0; i < rgb.length; i++) rgb[i] = rand.nextDouble ();
                r.setFill (new Color (rgb[0], rgb[1], rgb[2], 1.0));
            }
        });
    }
   
    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    /** this method sets some stylistic parameters of the rectangle.  I've 
     *  chosen to set the arc width and height which rounds the corners, 
     *  I've set the stroke color and width which styles the border, 
     *  and I've set the fill which colors the interior of the rectangle.
     *  @param r  the rectangle to style
     */
    public void setRect (Rectangle r) 
    {
        r.setArcWidth  (10);
        r.setArcHeight (10);
        r.setStroke (Color.BLACK);
        r.setStrokeWidth (3);
        r.setFill (Color.web ("#EE3344"));
    } // setRect

    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    /** this method adds a rectangle to the pane.
     *  @param r  the rectangle to add.
     */
    public void addRect (Rectangle r) { pane.getChildren (). add (r); }

    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    /** this method adds the pane to the group.
     */
    public void addPane () { root.getChildren (). add (pane); }

    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    /** this method displays the window.
     *  @param stage  the stage to display.
     */
    public void showWindow (Stage stage)
    {
        stage.setScene (scene);
        stage.show ();
    } // showWindow

} // FXRectangle