import java.awt.*;
import java.applet.*;
import java.awt.event.*;

class Dot
{
	int left, top;
	Color color = Color.RED;
	
	Dot(int l, int t, Color c)
	{
		left   = l;
		top    = t;
		color  = c;
	}
	
	public void setWidth(int w) {}        
	public int widthOf()  
	{ 
		return 0; 
	}       
	
	public void setHeight(int h) {}             
	public int heightOf() 
	{ 
		return 0;
	}        
	
	public void setLeft(int l)     
	{ 
		left = l; 
	}
	public int leftOf()  
	{ 
		return left; 
	}
	
	public void setTop(int t)      
	{ 
		top = t; 
	}
	public int topOf()   
	{ 
		return top; 
	}
	
	public void setColor(Color c) 
	{ 
		color = c; 
	}
	public Color colorOf() 
	{ 
		return color; 
	}
	
	public void draw (Graphics g) {}
	
	public boolean find (int x, int y) 
	{ 
		return false; 
	}
}

class RectDot extends Dot
{
	int width, height;
	
	RectDot (int l, int t, int w, int h, Color c)
	{
		super(l,t,c);
		width = w;
		height = h;
	}
	
	public void setWidth(int w)   
	{ 
		width = w; 
	}
	public int  widthOf()  
	{ 
		return width; 
	}
	
	public void setHeight(int h) 
	{ 
		height = h; 
	}
	public int  heightOf() 
	{ 
		return height;
	}
	
	public boolean find(int x, int y)
	{
		if (super.leftOf() < x && x < super.leftOf()+width && super.topOf()  < y && y < super.topOf()+height)
		return true;
		return false;
	}
	
	public void draw(Graphics g)
	{
		g.setColor(colorOf());
		g.fillRect(leftOf(), topOf(), width, height);
		g.setColor(Color.black);
	}
}

class CircDot extends Dot
{
	int diam;
	
	CircDot (int l, int t, int d, Color c)
	{
		super(l,t,c);
		diam = d;
	}
	
	public void setWidth(int w)  
	{ 
		diam = w; 
	}
	public int   widthOf()     
	{ 
		return diam; 
	}
	
	public void setHeight(int h) 
	{ 
		diam = h; 
	}
	public int   heightOf()    
	{ 
		return diam;
	}
	
	public void setDiam(int d)   
	{ 
		diam = d; 
	}
	public int diameterOf() 
	{ 
		return diam; 
	}
	
	public boolean find (int x, int y)
	{
		if (super.leftOf() < x && x < super.leftOf()+diam && super.topOf()  < y && y < super.topOf()+diam)
		return true;
		return false;
	}
	
	public void draw(Graphics g)
	{
		g.setColor(colorOf());
		g.fillOval(leftOf(), topOf(), diam, diam);
		g.setColor(new Color(0,0,0));
	}
}

public class Bounce extends Applet implements ActionListener, AdjustmentListener
{
	//runtime variables
	boolean running = false;
	boolean currentlyCircle = true;
	boolean showtails = false;
	
	//buttons
	Button runbutton = new Button("Run");
	Button tailbutton = new Button("Tail");
	Button shapebutton = new Button("Square");
	Button clearbutton = new Button("Clear");
	Button quitbutton = new Button("Quit");
	
	//text
	Label speedlabel = new Label("Speed");
	Label sizelabel = new Label("Size");
	
	//panels
	Panel drawingpanel = new Panel();
	
	//scrollbars
	private final int barHeight = 20;
	private final int SLIDER_WIDTH = 10;
	private final int MAXSPEED = 110;
	private final int MINSPEED = 0;
	private final int MAX_SIZE = 110;
	private final int MIN_SIZE = 10;
	/* These are the default values, and do not need to be implemented.
	 * If I wanted to use something other then default, these constants
	 * would be used.
	private final int UNIT_INC = 1;
	private final int BLOC_INC = 10;
	*/
	Scrollbar speedbar = new Scrollbar(Scrollbar.HORIZONTAL, MAXSPEED/2, SLIDER_WIDTH, MINSPEED, MAXSPEED);
	Scrollbar sizebar = new Scrollbar(Scrollbar.HORIZONTAL, MAX_SIZE/2, SLIDER_WIDTH, MIN_SIZE, MAX_SIZE);
	
	//drawn objs
	Dot dot;
	private Graphics page;
	Point currentlocation;
	Point previouslocation;

	//initialize the applet and draw everything
	public void init()
	{
		double colWeight[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};//15 cols
		double rowWeight[] = {1,1,1,1,1,1,1,1,1,1}; //10 rows
		int colWidth[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};//15 cols
		int rowHeight[] = {1,1,1,1,1,1,1,1,1,1}; //10 rows
		GridBagConstraints c = new GridBagConstraints();
		GridBagLayout gbl = new GridBagLayout();
		gbl.rowHeights = rowHeight;
		gbl.rowWeights = rowWeight;
		gbl.columnWeights = colWeight;
		gbl.columnWidths = colWidth;
		c.anchor = GridBagConstraints.CENTER;
		
		//setBounds(0,0,480,640);
		setLayout(new BorderLayout());
		Panel p = new Panel();
		p.setLayout(gbl);
		
		//speed scrollbar
		c.weightx = 1;
		c.weighty = 1;
		c.gridwidth = 3;
		c.gridheight = 1;
		c.gridx = 1;
		c.gridy = 7;
		c.fill= GridBagConstraints.HORIZONTAL;
		gbl.setConstraints(this.speedbar,c);
		
		//run button
		c.weightx = 1;
		c.weighty = 1;
		c.gridwidth = 2;
		c.gridheight = 1;
		c.gridx = 5;
		c.gridy = 7;
		c.fill= GridBagConstraints.HORIZONTAL;
		gbl.setConstraints(this.runbutton,c);
		
		//tail button
		c.weightx = 1;
		c.weighty = 1;
		c.gridwidth = 2;
		c.gridheight = 1;
		c.gridx = 8;
		c.gridy = 7;
		c.fill= GridBagConstraints.HORIZONTAL;
		gbl.setConstraints(this.tailbutton,c);
		
		//size scrollbar
		c.weightx = 1;
		c.weighty = 1;
		c.gridwidth = 3;
		c.gridheight = 1;
		c.gridx = 11;
		c.gridy = 7;
		c.fill= GridBagConstraints.HORIZONTAL;
		gbl.setConstraints(this.sizebar,c);
		
		//speed text label
		c.weightx = 1;
		c.weighty = 1;
		c.gridwidth = 3;
		c.gridheight = 1;
		c.gridx = 1;
		c.gridy = 8;
		c.fill= GridBagConstraints.HORIZONTAL;
		gbl.setConstraints(this.speedlabel,c);
		
		//shape button
		c.weightx = 1;
		c.weighty = 1;
		c.gridwidth = 2;
		c.gridheight = 1;
		c.gridx = 5;
		c.gridy = 8;
		c.fill= GridBagConstraints.HORIZONTAL;
		gbl.setConstraints(this.shapebutton,c);
		
		//clear button
		c.weightx = 1;
		c.weighty = 1;
		c.gridwidth = 2;
		c.gridheight = 1;
		c.gridx = 8;
		c.gridy = 8;
		c.fill= GridBagConstraints.HORIZONTAL;
		gbl.setConstraints(this.clearbutton,c);
		
		//size text label
		c.weightx = 1;
		c.weighty = 1;
		c.gridwidth = 3;
		c.gridheight = 1;
		c.gridx = 11;
		c.gridy = 8;
		c.fill= GridBagConstraints.HORIZONTAL;
		gbl.setConstraints(this.sizelabel,c);
		
		//quit button
		c.weightx = 1;
		c.weighty = 1;
		c.gridwidth = 3;
		c.gridheight = 1;
		c.gridx = 6;
		c.gridy = 9;
		c.fill= GridBagConstraints.HORIZONTAL;
		gbl.setConstraints(this.quitbutton,c);
		
		//add to the screen
		p.add(this.speedbar);
		p.add(this.runbutton);
		p.add(this.tailbutton);
		p.add(this.sizebar);
		p.add(this.speedlabel);
		p.add(this.shapebutton);
		p.add(this.clearbutton);
		p.add(this.sizelabel);
		p.add(this.quitbutton);
		
		//add listners
		this.speedbar.addAdjustmentListener(this);
		this.runbutton.addActionListener(this);
		this.tailbutton.addActionListener(this);
		this.sizebar.addAdjustmentListener(this);
		this.shapebutton.addActionListener(this);
		this.clearbutton.addActionListener(this);
		this.quitbutton.addActionListener(this);

		//drawing paramaters
		page = getGraphics();
		//boundaries
		int bound_x = Integer.parseInt(getParameter("WIDTH"));
		int bound_y = Integer.parseInt(getParameter("HEIGHT"));
		//directions
		int dx = 5;
		int dy = 5;	

		//add the panels
		add("South", p);
		add("Center", drawingpanel);
	}

	public void run()
	{

		//while (running)
		//{
			if (!showtails)
			{
				dot.setColor(drawingpanel.getBackground());
			}
			update();//check if speed, size, or shape changed
			draw();//draw next dot based on move(), or initial condition
			pause();
			move();//calculate and prepare the coordinates for the next iteration to be drawn
		//}
	}

	public void update()
	{
		previouslocation = currentlocation;
		currentlocation = new Point(dot.leftOf(), dot.topOf());
	}
	
	public void draw()
	{
		
	}
	
	public void paint(Graphics page)
	{
		if(currentlyCircle)
		{
			System.err.println("here");
			page.drawOval(dot.leftOf(), dot.topOf(), dot.widthOf(), dot.heightOf());
			page.fillOval(dot.leftOf(), dot.topOf(), dot.widthOf(), dot.heightOf());
		}
		else
		{
			page.drawRect(dot.leftOf(), dot.topOf(), dot.widthOf(), dot.heightOf());
			page.fillRect(dot.leftOf(), dot.topOf(), dot.widthOf(), dot.heightOf());
		}
	}
	
	public void pause()
	{
		//for (long i = 100000000; i <= i; i++){}
	}
	
	public void move()
	{
	
	}
   
   	public void actionPerformed(ActionEvent e)
	{
		Object source = e.getSource();
		
		if (source == this.runbutton)
		{
			if (!running) //prevents drawing a new dot when there is already one on the screen
			{
				running = true;
				dot = new CircDot(100, 100, sizebar.getValue(), Color.RED);
				currentlyCircle = true;
			}
			run();
		}
		else if (source == this.shapebutton)
		{
			if(running)//no need to evaluate if the run button hasn't been pressed (ie no dot to switch)
			{
				if (currentlyCircle) //if circle, draw it as a rectangle
				{
					dot = new RectDot(dot.leftOf(), dot.topOf(), dot.widthOf(), dot.heightOf(), dot.colorOf());
					this.shapebutton.setLabel("Square");
					currentlyCircle = false;
				}
				else //if rectangle, draw it as a circle
				{
					dot = new CircDot(dot.leftOf(), dot.topOf(), 2*dot.widthOf(), dot.colorOf());
					this.shapebutton.setLabel("Circle");
					currentlyCircle = true;
				}
			}
		}
		else if (source == this.clearbutton)
		{
			/* Erase the dot by setting its color to the background. 
			 * Running is also set to false. This means the run button
			 * can be pressed again and another dot will be drawn.
			 */
			running = false;
			dot.setColor(getBackground());
		}
		else if (source == this.tailbutton)
		{
			//toggle showing tails. This is used in run
			showtails = true;
		}
		else if (source == quitbutton)
		{
			//remove listeners
			stop();
		}
		
		update(drawingpanel.getGraphics());
	}
	
	public void adjustmentValueChanged(AdjustmentEvent e)
	{
		Object source = e.getSource();
		
		//set the new size. If the size is too big its adjusted in draw
		if (source == sizebar)
		{
			dot.setWidth(sizebar.getValue());
			dot.setHeight(sizebar.getValue());
		}
		if (source == speedbar)
		{
			
		}
	}
	
	public void stop()
	{
		this.speedbar.removeAdjustmentListener(this);
		this.runbutton.removeActionListener(this);
		this.tailbutton.removeActionListener(this);
		this.sizebar.removeAdjustmentListener(this);
		this.shapebutton.removeActionListener(this);
		this.clearbutton.removeActionListener(this);
		this.quitbutton.removeActionListener(this);
	}
}