/* *****************************************************************
	Homework #6
	Author: Butler, Martin
	Date: 2004.12.02
	Due: 2004.12.09
	CMPT 505
***************************************************************** */
import java.awt.*;
import javax.swing.*;
import java.util.*;
import java.awt.event.*;

public class CanvasPanel extends JPanel
{

	boolean [] exists;			// display toogle for circle.
	int [] size;				// store random size of circle.
	int [] speed;				// store random speed of circle movement.
	int [] xPos;				// circle x coordinate
	int [] yPos;				// circle y coordinate
	int [] xDirection;			// store random value for x coordinate movement.
	int [] yDirection;			// store random value for y coordinate movement.
	boolean [] clearBubble;		// for clearing bubble from panel.
	int maxBubble;				// max number of concurrent circles.
	int width = 0;				// store the width of panel.
	int height = 0;				// store the height of panel.
	int totBubbles = 0;			// track number of circles created.
	int totHit = 0;				// track number of circles pressed by mouse
	boolean gameOver = false;
	boolean gameStarted = false;
	boolean goodbye = false;
	

  	public CanvasPanel (int max)
  	{
  		// *************************************************************
  		// initilization.  build all arrays with max number passed in.
  		// add mouse listener
  		// *************************************************************
  		System.out.println ("canvas panel constructed");
  		maxBubble = max;
  		
  		exists = new boolean [maxBubble];
  		size = new int[maxBubble];
  		speed = new int[maxBubble];
  		xPos = new int[maxBubble];
  		yPos = new int[maxBubble];
  		xDirection = new int[maxBubble];
  		yDirection = new int[maxBubble];
  		clearBubble = new boolean [maxBubble];
  		
  		for (int n =0; n<maxBubble;n++)
  		{
  			exists[n] = false;
  			size[n] = 0;
  			speed[n] = 0;
  			xPos[n] = 0;
  			yPos[n] = 0;
  			xDirection[n] = 0;
  			xDirection[n] = 0;
  			clearBubble[n] = false;
  		}
  		addMouseListener (new Pop());
  	}
  	
  	public void reset ()
  	{
  		// **************************************************
  		// Performed once after start button is pressed to
  		// init values, including turning off the exist of
  		// each circle.
  		// Turns on the gameStarted boolean and turns off
  		// gameover boolean.
  		// **************************************************
  		width = this.getWidth();
		height = this.getHeight();

  		totBubbles = 0;
  		totHit = 0;
  		gameStarted = true;
  		gameOver = false;
  		for (int n =0; n < maxBubble; n++)
  		{
  			exists[n] = false;
  			clearBubble[n] = false;
  		}
  	}
  	
  	public void clear()
  	{
  		// ***********************************************
  		// Perform when stop button is click.
  		// move all circles out of scope of window and
  		// turns on the gameover boolean.
  		// ***********************************************
  		for(int n =0; n < maxBubble; n++)
  		{
  			xPos[n] = -100;
  			yPos[n] = -100;
  			size[n] = 0;
  			clearBubble[n] = false;
   		}
   		gameOver = true;
  	}
  	
  	public void gbExit ()
  	{
  		// **********************************
  		// turn on the boolean for exiting
  		// **********************************
  		System.out.println("gbExit Performed");
  		goodbye = true;
  		
  	}

  	public void createBubble ()
	{
		// ************************************************
		// create a circle in the first available array by 
		// determining when value of exists is false
		// ************************************************

		for(int n =0; n < maxBubble; n++)
		{
			if(exists[n] == false)
			{
				System.out.println("Bubble Create: "+n);
				Random r = new Random ();
				float ranHold;
				// *******************************************
				// Offset and Range for random speed variable
				// *******************************************
				final float SPPOSOFFSET = 5;
				final float SPPOSRANGE = 25;
				ranHold = r.nextFloat() * SPPOSRANGE + SPPOSOFFSET;
				speed[n] = (int)ranHold;
				
				// *******************************************
				// Offset and Range for random size variable
				// *******************************************
				final float SZPOSOFFSET = 15;
				final float SZPOSRANGE = 50;
				ranHold = r.nextFloat() * SZPOSRANGE + SZPOSOFFSET;
				size[n] = (int)ranHold;
				
				// *************************************************
				// Offset and range for random x & y variable
				// *************************************************		
				final float OFFSET = -15;
				final float RANGE = 30;
				ranHold = r.nextFloat() * RANGE + OFFSET;
				xDirection[n] = (int)ranHold;
				ranHold = r.nextFloat() * RANGE + OFFSET;
				yDirection[n] = (int)ranHold;
		
				// *****************************************************
				// Offset and range set to dimension of the panel used
				// for random creation location of circle
				// *****************************************************
				ranHold = r.nextFloat() * height + 0;
				xPos[n] = (int)ranHold;
				ranHold = r.nextFloat() * width + 0;
				yPos[n] = (int)ranHold;
		
				exists[n] = true;
				totBubbles++;
				
				n = maxBubble;				// to insure creation of one circle.
			}
		}		
	}
	
	public void moveBubble (float move)
	{
		// ****************************************************************
		// move circle if bubble needs to be moved by as
		// defined by its speed attribute.
		// if circle is moved by adding the direction coordinates to
		// circles x & y coordinates.
		// After x & y coordinates are updated, circle is check
		// for visiblity in the panel.  If visiblity is gone, clearBubble
		// is turned on
		// ****************************************************************
		for(int n=0; n < maxBubble; n++)
		{
			if (exists[n] == true)
			{
				if(speed[n] >= move)
				{
					xPos[n] += xDirection[n];
					yPos[n] += yDirection[n];
					
					if (((xPos[n] + size[n]) < 0) || ((xPos[n] - size[n]) > height) ||
					  ((yPos[n] + size[n]) < 0) || ((yPos[n] - size[n]) > width))
					{
						System.out.println("Bubble off screen:x="+xPos[n]+" y="+yPos[n]+" size="+size[n]);
						xPos[n] = -100;
  						yPos[n] = -100;
  						size[n] = 0;
  						clearBubble[n] = true;
					}
				}
			}
		}
	}

  	public void paint (Graphics g)
  	{
    	System.out.println ("paint method called for canvas");
    	for (int n=0;n<maxBubble;n++)
    	{
    		g.drawOval (xPos[n], yPos[n], size[n], size[n]);
    		if (clearBubble[n] == true)
    		{
    			exists[n] = false;
    			clearBubble[n] = false;
    		}
    	}
    	if (gameOver == true)
    	{
    		g.drawString ("GAME OVER.  Your Score was " + totHit + " Hits", 10, 10);
    	}
    	if (gameStarted == true)
    	{
    		gameStarted = false;
    	}
    	if (goodbye == true)
    	{
    		System.out.println("paint goodbye = true");
    		g.drawString ("Goodbye!  Thank you for playing.", 50, 50);
      		{
      		}
    	}
    	
  	}
  	
  	// *****************************************
  	// called when loading in parameters from saved game
  	// *****************************************
  	public void loadGame (BubbleGame bg)
  	{
  		for (int n =0; n <bg.canvas.maxBubble; n++)
  		{
  			exists[n] = bg.canvas.exists[n];
  			size[n] = bg.canvas.size[n];
  			speed[n] = bg.canvas.speed[n];
  			xPos[n] = bg.canvas.xPos[n];
  			yPos[n] = bg.canvas.yPos[n];
  			xDirection[n] = bg.canvas.xDirection[n];
  			yDirection[n] = bg.canvas.yDirection[n];
  			clearBubble[n] = bg.canvas.clearBubble[n];
  			maxBubble = bg.canvas.maxBubble;
  			gameOver = bg.canvas.gameOver;
  			gameStarted = bg.canvas.gameStarted;
  			totBubbles = bg.canvas.totBubbles;
  			totHit = bg.canvas.totHit;
  			width = bg.canvas.width;
  			height = bg.canvas.height;
  		}
  		System.out.println ("restored values from saved game");
  	}
  			
  	
  	public class Pop implements MouseListener
	{
		public void mousePressed (MouseEvent e)
		{
			// **************************************************
			// Check to see if pointer is pressed inside bubble
			// **************************************************
			// **************************************************
			// store the x, y coordinates of mouse press
			// Set up variables for boolean operations
			// **************************************************
			int xClick;
			int yClick;
			xClick = (e.getX());	// store x cord. of mouse press
			yClick = (e.getY());	// store y cord. of mouse press
			
			int dx;					// distance on x axle from center of circle to pointer press
			int dy;					// distance on y axle from center of circle to pointer press
			double dxy;				// store distance from center of circle to pointer press
			
			System.out.println("Click:" + xClick + "," + yClick);
			for(int p = 0; p < maxBubble; p++)
			{
				if (exists[p] == true)
				{
					dx = ((xPos[p] + (size[p] / 2)) - xClick);
					dy = ((yPos[p] + (size[p] / 2)) - yClick);
					dxy = Math.sqrt((double)((dx*dx) + (dy*dy)));
					System.out.println("pressed px,y:" + xClick +","+ yClick+" dxy:" + dxy);
					
					// *******************************************************************
					// verify, for each circle, that distance from center of circle
					// to pointer press is less then or equal to the radius of the circle
					// *******************************************************************
					if (dxy <= (size[p] / 2))
					{
						xPos[p] = -100;
  						yPos[p] = -100;
  						size[p] = 0;
  						totHit++;
						clearBubble[p] = true;
					}
					
				}
			}
		}
	
		public void mouseClicked (MouseEvent e)
		{
		}
		public void mouseReleased (MouseEvent e)
		{
		}
		public void mouseEntered (MouseEvent e)
		{
		}
		public void mouseExited (MouseEvent e)
		{
		}

	}
}

