import objectdraw.*;
import java.awt.*;

/*
 * 
 * A simple active object that controls a ball that bounces around the
 * canvas and interacts with a boundary and a pong paddle, plus a
 * nudge method that allows someone to make a minor change to its
 * trajectory.
 *
 * Jim Teresco, Siena College, CSIS 120, Fall 2011
 *
 * $Id: PongBall.java 1560 2011-03-07 18:29:47Z terescoj $
 */

public class PongBall extends ActiveObject {

    // size and speed of falling balls
    private static final int BALLSIZE = 30;
    private static final double MIN_SPEED = 3;
    private static final double MAX_SPEED = 10;
    private static final int DELAY_TIME = 33;
    private static final double NUDGE_MAX = 2;

    // the ball controlled by this instance
    private FilledOval ball;

    // the paddle with which we will interact
    private FilledRect paddle;

    // how far to fall before stopping and disappearing?
    private double yMax;
    // how far up to go before bouncing off the ceiling?
    private double yMin;
    // and what about the walls?
    private double xMin, xMax;

    // speeds are now instance variables since 
    private double xSpeed, ySpeed;

    // label for speeds
    private Text speeds;
    
    // Draw a ball and start it falling.
    public PongBall(FilledRect paddle, FramedRect boundary,
    DrawingCanvas aCanvas) {

        // compute/remember our boundaries (of the upper left corner of a ball)
        yMax = boundary.getY()+boundary.getHeight();
        yMin = boundary.getY();
        xMin = boundary.getX();
        xMax = boundary.getX() + boundary.getWidth() - BALLSIZE;

        // random generator for the x-coordinate
        RandomDoubleGenerator posGen = new RandomDoubleGenerator(xMin, xMax);

        // draw the ball at its initial position, which is at the 
        // top of the playing area, at a randomly-selected position
        ball = new FilledOval(posGen.nextValue(), yMin+1,
            BALLSIZE, BALLSIZE, aCanvas);

        // remember the paddle
        this.paddle = paddle;
        
        // A label for the speeds
        speeds = new Text("", 10, 10, aCanvas);

        // activate!
        start();
    }

    // our "nudge" method -- make a minor change in the trajectory
    // and temporarily make the ball red
    public void nudge() {
        RandomDoubleGenerator nudgeAmount = new RandomDoubleGenerator(-NUDGE_MAX, NUDGE_MAX);
        
        // randomly perturb both the x and y speeds
        xSpeed = xSpeed + nudgeAmount.nextValue();
        ySpeed = ySpeed + nudgeAmount.nextValue();

        speeds.setText("xSpeed = " + xSpeed + ", ySpeed = " + ySpeed);
        
        ball.setColor(Color.red);
    }

    // move the ball repeatedly until it falls off screen, bouncing
    // off the paddle and walls along the way
    public void run() {

        // start by moving downward and some amount to the left or right
        RandomDoubleGenerator speedGen = new RandomDoubleGenerator(MIN_SPEED, MAX_SPEED);

        xSpeed = speedGen.nextValue();
        double initYSpeed = speedGen.nextValue();
        ySpeed = initYSpeed;
        
        // keep moving as long as we haven't fallen off the bottom of
        // the screen
        while (ball.getY() <= yMax) {
            // if we are above the top line, start moving down
            if (ball.getY() < yMin) {
                ySpeed = initYSpeed;
            }

            // if we are in contact with the paddle, start moving up
            if (ball.overlaps(paddle)) {
                ySpeed = -initYSpeed;
            }

            // bounce off side walls
            if (ball.getX() < xMin || ball.getX() > xMax) {
                xSpeed = -xSpeed;
            }

            // move a little in the appropriate direction
            speeds.setText("xSpeed = " + xSpeed + ", ySpeed = " + ySpeed);
            ball.move(xSpeed, ySpeed);
            speeds.moveTo(ball.getX() + BALLSIZE, ball.getY() + BALLSIZE);
            ball.setColor(Color.black);
            pause(DELAY_TIME);
        }

        ball.removeFromCanvas();
        speeds.removeFromCanvas();
    }
}
