import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;

import javax.swing.JPanel;

/**
 * Panel that runs an animation.
 * In particular, it contains an orbiting square.
 *
 * @author An anonymous student, David Mutchler and many others before them.
 *         Created November 2004, updated August 2005 and September 2008.
 */
public class AnimatedPanel extends JPanel implements Runnable {
	
	// Default background color of the panel.
	private static final Color DEFAULT_COLOR = Color.BLUE;
	
	// Default color of the panel's orbiting square.
	private static final Color DEFAULT_SQUARE_COLOR = Color.GREEN;
	
	// Default size of the square, as a fraction of the panel's width.
	private static final double DEFAULT_SQUARE_SIZE = 0.14;
	
	// Default radius of the square's orbit, as a fraction of the panel's width.
	private static final double DEFAULT_SQUARE_RADIUS = 0.33;
	
	// How often to change the position of the panel's orbiting square,
	// in milliseconds.
	private static final int PAUSE_TIME = 20;

	// How much to change the position of the orbiting square at each time step,
	// in radians.
	private static final double ANGLE_DELTA = 0.005;

	private double angle; // Current position of the orbiting square, in radians.
	private boolean squareIsMoving;
	private int squareSize;    // In pixels
	private int orbitRadius;   // In pixels
	private Color squareColor;
	private Point panelCenter; // in pixels
	
	/**
	 * Construct a square panel with width and height the given size
	 * and with other item sizes based on that given size.
	 *
	 * @param size Desired size (width and height) of this panel.
	 */
	public AnimatedPanel(int size) {
		// Set the panel size
		int width = size;
		int height = size;
		this.setPreferredSize(new Dimension(width, height));
		
		// Center of the panel
		this.panelCenter = new Point(width / 2, height / 2);
		
		// Size of each side of the orbiting square
		this.squareSize = (int) (width * AnimatedPanel.DEFAULT_SQUARE_SIZE);
		
		// Distance square should orbit from the center of the panel
		this.orbitRadius = (int) (size * AnimatedPanel.DEFAULT_SQUARE_RADIUS);
		
		// Orbiting square starts out at the 0 radians point and is initially stationary
		this.angle = 0.0;
		this.squareIsMoving = false;
		
		// Background color of the panel and color of the square
		this.setBackground(AnimatedPanel.DEFAULT_COLOR);
		this.squareColor = AnimatedPanel.DEFAULT_SQUARE_COLOR;
	}
	
	/**
	 * Repeatedly update the position of the square.
	 */
	public void run() {
		System.out.println("Animation thread started.");
		
		this.squareIsMoving = true;
		while (this.squareIsMoving) {
			try {
				// Sleep so the square orbits at a resonable speed.
				Thread.sleep(AnimatedPanel.PAUSE_TIME); 
			} catch (InterruptedException exception) {
				// Just continue the loop if you cannot sleep.
			}
		
		  // Update the square's position and redraw the panel.
		  this.angle += 2 * Math.PI * AnimatedPanel.ANGLE_DELTA;
		  this.repaint();
    	}
		
		System.out.println("Animation thread stopped.");
    }
    
    /**
     * Draw the square at its current position.
     *
     * @param graphics Graphics object to draw upon
     */
    @Override
	public void paintComponent(Graphics graphics) {
    	super.paintComponent(graphics);
    	
    	// Convert from polar to rectangular coordinates
    	int x = (int) (this.panelCenter.getX() + this.orbitRadius * Math.cos(this.angle) - this.squareSize / 2);
    	int y = (int) (this.panelCenter.getY() - this.orbitRadius * Math.sin(this.angle) - this.squareSize / 2);
    	
    	// Draw the square
    	graphics.setColor(this.squareColor);
    	graphics.fillRect(x, y, this.squareSize, this.squareSize);
    }

	/**
	 * Stop the orbiting square.
	 */
	public void stop() {
		this.squareIsMoving = false;
	}
}