//
//
//	PinBallGame class, final version
//
//	From Chapter 7 of
//	Understanging Object-Oriented Programming with Java
//	Written by Tim Budd
//	Published by Addison-Wesley Longman
//
//	See ftp://ftp.cs.orst.edu/pub/budd/java/ReadMe.html 
//	for further information
//
//

import java.awt.*;
import java.awt.event.*;
import java.util.Vector;

public class PinBallGame extends Frame {

	public static void main (String [ ] args) {
		world = new PinBallGame();
		world.show();
	}

	public static final int FrameWidth = 400;
	public static final int FrameHeight = 400;
	public static PinBallGame world;
	private int score = 0;
	private Label scoreLabel;
	private Vector balls;
	private Vector targets;

	public PinBallGame () {
		setTitle ("Pin Ball Construction Kit");
		setSize (FrameWidth, FrameHeight);

		balls = new Vector();
		scoreLabel = new Label ("score: 0");
		add ("North", scoreLabel);
		addMouseListener (new MouseKeeper());
			// create the targets 
		targets = new Vector();
			//
		targets.addElement(new Wall(50, 50, 2, 350));
		targets.addElement(new Wall(50, 50, 340, 2));
		targets.addElement(new Wall(390, 50, 2, 380));
			// 
		targets.addElement(new Hole(30, 100));
		targets.addElement(new Peg(30, 140, 100));
		targets.addElement(new Peg(30, 180, 200));
		targets.addElement(new ScorePad(30, 220, 100));
		targets.addElement(new ScorePad(30, 260, 200));
		targets.addElement(new Spring(15, 300));
		targets.addElement(new Wall(30, 340, 2, 15));
	}

	private class PinBallThread extends Thread {
		private Ball theBall;

		public PinBallThread (Ball aBall) {
			theBall = aBall; 
		}

		public void run () {
			while (theBall.y() < FrameHeight) {
				theBall.move ();
					// see if we ran into anything
				for (int j = 0; j < targets.size(); j++) {
					PinBallTarget target = (PinBallTarget) targets.elementAt(j);
					if (target.intersects(theBall)) target.hitBy(theBall);
					}
				repaint();
					// then sleep for a while
				try {
					sleep(10);
				} catch (InterruptedException e) { System.exit(0); }
			}
		}
	}

	private class MouseKeeper extends MouseAdapter {

		private PinBallTarget element;

		public void mousePressed (MouseEvent e) { 
			element = null;
			int x = e.getX();
			int y = e.getY();
			if ((x > FrameWidth-40) && (y > FrameHeight -40)) {
				PinBall newBall = new PinBall(e.getX(), e.getY());
				balls.addElement (newBall);
				Thread newThread = new PinBallThread (newBall);
				newThread.start();
			} 
			if (x < 40) {
				switch (y / 40) {
					case 2: element = new Hole(0, 0); break;
					case 3: element = new Peg(0, 0, 100); break;
					case 4: element = new Peg(0, 0, 200); break;
					case 5: element = new ScorePad(0, 0, 100); break;
					case 6: element = new ScorePad(0, 0, 200); break;
					case 7: element = new Spring(0, 0); break;
					case 8: element = new Wall(0, 0, 2, 15); break;
				}
			}
		}

		public void mouseReleased (MouseEvent e) {
			int x = e.getX();
			int y = e.getY();
			if ((element != null) && (x > 50)) {
				element.moveTo(x, y);
				targets.addElement (element);
				repaint();
			}
		}
	}

	synchronized public void addScore (int v) { 
		score = score + v; 
		scoreLabel.setText("score = " + score); 
		}

	public void paint (Graphics g) {
		g.setColor (Color.white);
		g.fillRect (FrameWidth-40, FrameHeight-40, 30, 30);
		g.setColor (Color.red);
		g.fillOval (FrameWidth-40, FrameHeight-40, 30, 30);
			// draw balls
		for (int i = 0; i < balls.size(); i++) {
			Ball aBall = (Ball) balls.elementAt(i);
			aBall.paint(g);
			}
			// draw targets
		for (int j = 0; j < targets.size(); j++) {
			PinBallTarget target = (PinBallTarget) targets.elementAt(j);
			target.paint(g);
			}	
		}
}
