// DrawJPanel4.java
// Demos a JPanel used as a dedicated drawing area
// Listens to its own mouse events
// Uses anonymous inner class
// Uses arrays for the three balls
// Priovides for suspending and resuming of threads
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class DrawJPanel4 extends JPanel implements Runnable {
	private int width, height;
	private int k = 0; 		// counter for balls
	private final int NUMBALLS = 3;
	private Color colors[ ] = { Color.red, Color.green, Color.blue };
	private int x[ ] = new int[ NUMBALLS ];		// arrays of x and y coordinates
	private int y[ ] = new int[ NUMBALLS ];
	private int xMove[ ] = new int[ NUMBALLS ];	// x and y "speeds"
	private int yMove[ ] = new int[ NUMBALLS ];	
	private boolean isBall[ ] = new boolean[ NUMBALLS ];	// does ball exist	
	private Thread threads[ ] = new Thread[ NUMBALLS ];
	
	private boolean suspended[ ] = new boolean[ NUMBALLS ];	// is ball suspended
	private int index;

	public DrawJPanel4( ) {
		initialize( );
		addMouseListener(
			new MouseAdapter( ) {
				public void mousePressed( MouseEvent e ) {
					if ( k > 2 )
						return;
					
					isBall[ k ] = true;
					x[ k ] = e.getX( ) - width / 2;	// make mouse in center
					y[ k ] = e.getY( ) - height / 2;	// make mouse in center
					threads[ k++ ].start( );
					repaint( );
				}
			}
		);
	}

	// utility method to initialize arrays
	private void initialize( ) {
		for ( int i = 0; i < NUMBALLS; i++) {
			xMove[ i ] = ( int ) ( 5 * Math.random( ) + 1 );
			yMove[ i ] = ( int ) ( 5 * Math.random( ) + 1 );
		}

		for ( int i = 0; i < NUMBALLS; i++ ) {
			isBall[ i ] = false;
		}

		for ( int i = 0; i < NUMBALLS; i++ ) {
			threads[ i ] = new Thread( this, "Ball "+ i );
		}
	}

	public void run( ) {
		Thread executingThread = Thread.currentThread( );

		while ( true ) {
			// sleep for .01 seconds
			try {
				Thread.sleep( 10 );
				
				synchronized( this ) {
					while ( suspended[ index ] && threads[ index ] == executingThread )
						wait( );
				}
			}
			catch ( InterruptedException ex ) {
				ex.printStackTrace( );
			}

			for ( int i = 0; i < NUMBALLS; i++ ) {
				if ( executingThread == threads[ i ] ) {
					x[ i ]  += xMove[ i ];

					if ( x[ i ] >= 940 || x[ i ] <= 4 )
						xMove[ i ] *= -1;		// reverse direction if wall is hit

					y[ i ] += yMove[ i ];

					if ( y[ i ] >= 438 || y[ i ] <= 4 )
						yMove[ i ] *= -1;		// reverse direction if wall is hit
				}
			}
			repaint( );
		}
	}

	public void drawingStuff( int w, int h ){
		// receives two size arguments from applet
		width = w;
		height = h;
		repaint( );		// calls paintComponent
	}

	// all of the actual drawing takes place here
	public void paintComponent( Graphics g ) {
		// call to super class
		super.paintComponent( g );
		// my drawing code
		g.setColor( Color.blue );
		g.drawRect( 3, 3, 989, 490 );
		g.drawRect( 4, 4, 987, 488 );

		for ( int i = 0; i < NUMBALLS; i++ ) {
			if ( isBall[ i ] ) {
				g.setColor( colors[ i ] );
				g.fillOval( x[ i ], y[ i ], width, height );
			}
		}
	}

	// method for suspending and resuming the threads
	public synchronized boolean flip( int i ) {
		index = i;
		suspended[ i ] = !suspended[ i ];
		System.out.println( "Thread " + i + " is suspended?" + suspended[ i ] );
		if ( !suspended[ i ] )
			notify( );
		return suspended[ i ];
	}

	public synchronized void stop( ) {
		// stop threads everytime stop is called
		// as the user browses another web page
		for ( int i = 0; i < threads.length; i++ )
			threads[ i ] = null;
		notifyAll( );
	}
}