package breakout;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Dimension;
import java.util.Vector;
import java.awt.*;
import java.awt.event.*;

/*keeps track of all the bricks displayed on the screen
 *makes instances of the bricks
 *checks if the bricks have been hit by a ball
 *deletes bricks from the screen
 *paints the bricks on the screen*/
public class BrickRepository
{
  
	private ScreenCanvas screen;
	private Vector brickvect;
	private Dimension scDim;
	private int scHeight; //height of screen field
	private int scWidth; //width of screen field
	private int vectSize;
	
	//constructor takes a screenCanvas, creates a vector, and sets its fields
	public BrickRepository (ScreenCanvas screen)
	{   
		this.screen = screen;
		this.brickvect = new Vector();
		this.scDim = screen.getSize();
		this.scHeight = (int)scDim.getHeight();
		this.scWidth = (int)scDim.getWidth();
		
	}
	
	//creates instances of the bricks and calls addBrick to add to vector
	//can be altered to change the display of bricks-for higher levels
	public void makeBricks()
	{	
		Point upperlft = new Point(0, 0); 
		Point lowerrt = new Point (0, 0);
		int x= 75, index=0;
		
		while (x<(this.screen.xMax-50)) //makes a top row of stationary bricks
		{ 
			upperlft.setLocation(x,50);
			x += 50;	
			lowerrt.setLocation(x,65);
			StationaryBrick statbrick = new StationaryBrick(this.screen, this, upperlft, lowerrt);
			this.addBrick (statbrick,index);
			index++;
		}
		
		//the rest of the rows are all brick100s
		x=50;
		index = vectSize;
		while(x<(this.screen.xMax-50))
		{ 
			upperlft.setLocation(x,65);
			x += 50;	
			lowerrt.setLocation(x,80);
			Brick100 hundbrick = new Brick100(this.screen, this, upperlft, lowerrt);
			this.addBrick (hundbrick,index);
			index++;
		}
		
		x=75;
		index=vectSize;
		while (x< (this.screen.xMax-50))
		{ 
			upperlft.setLocation(x, 80);
			x += 50;	
			lowerrt.setLocation(x,95);
			Brick100 hundbrick = new Brick100(this.screen, this, upperlft, lowerrt);
			this.addBrick (hundbrick,index);
			index++;
		}
		
		x=100;
		index=vectSize;
		while (x< (this.screen.xMax-100))
		{ 
			upperlft.setLocation(x, 95);
			x += 50;	
			lowerrt.setLocation(x,110);
			Brick100 hundbrick = new Brick100(this.screen, this, upperlft, lowerrt);
			this.addBrick (hundbrick,index);
			index++;
		}
		
		x=125;
		index=vectSize;
		while (x< (this.screen.xMax-125))
		{ 
			upperlft.setLocation(x, 110);
			x += 50;	
			lowerrt.setLocation(x,125);
			Brick100 hundbrick = new Brick100(this.screen, this, upperlft, lowerrt);
			this.addBrick (hundbrick,index);
			index++;
		}
		
		//adds a last row of stationary bricks for increased difficulty
		x = 100;
		while (x<  (this.screen.xMax-100))
		{ 
			upperlft.setLocation(x,125);
			x += 50;	
			lowerrt.setLocation(x,140);
			StationaryBrick statbrick = new StationaryBrick(this.screen, this, upperlft, lowerrt);
			this.addBrick (statbrick,index);
			index++;
		}
	
	}

	//adds bricks to the vector
	public void addBrick (BreakOutBrick brick, int vectorIndex)
	{
		brickvect.add (vectorIndex, brick);
		vectSize++;
		if (brick instanceof Brick100)
		{
			this.screen.numberOfBrick100s++;
		}
	}
	
	//deletes bricks from the vector
	public void deleteBrick (BreakOutBrick brick, int vectorIndex)
	{ 
		try 
		{
			brickvect.setElementAt (brick, vectorIndex);
			System.out.println(this.screen.numberOfBrick100s);
			
			
			if (brick instanceof Brick100)
			{
				this.screen.numberOfBrick100s--;
			}
			//this.screen.repaint();  //repaints screen without deleted brick
		}
		catch (ArrayIndexOutOfBoundsException outBoundExcep) {
			System.out.println("Invalid index for adding brick to repository");
		}
	}
	
				

	/*checks to see if a ball has hit a brick
	 *only called with a Classic ball
	 *only called if in the range of the bricks
	 *if ball hits brick and ball==classic ball: deletes brick100, changes balls velocity,
	 *bounces of stationary brick, creates multiple balls
	 */
	public void checkHitBrick (BreakOutBall boball)
	{
	    
		int i;
		vectSize = brickvect.size(); //gets the current size of the vector
		
		//ball variables
		Point ballCent = new Point(boball.getCenter());
		double ballRad = boball.getRadius();
		double xVel = boball.getXvelocity();
		double yVel = boball.getYvelocity();

		//brick variables
		BreakOutBrick bobrick;
		DudBrick toDelBrick;
		Point holdUL, holdLR;
		
		//checks each element of the vector if ball hit that element
		for (i=0; i<vectSize; i++)
		{
			bobrick = (BreakOutBrick)brickvect.get(i);
			holdUL = new Point( bobrick.getUpperLft() );
			holdLR = new Point( bobrick.getLowerRt() );
			
			//checks if ball has hit a brick (in range of brick)
			if (  ((ballCent.x+ballRad) >= holdUL.x) 
					&& ((ballCent.x-ballRad) <= holdLR.x) 
					&& ((ballCent.y+ballRad) >= holdUL.y)
					&& ((ballCent.y-ballRad) <= holdLR.y) )
		
			{
				if (bobrick instanceof DudBrick) {} //nothing is done if brick is Dud, Dud is just place holder
			
				/*checks if the brick that the ball has hit is an instance of Brick100
				 *changing the balls repository
				 *updating the score
				 *deleting the brick from the vector
				 * if ghostball replaces brick with stationary brick*/ 
				if (bobrick instanceof Brick100) 
				{		
				
					if (ballCent.x+ballRad >= holdLR.x)  //if ball hit brick from right
					{
						boball.changeXvelocity(Math.abs(xVel));
					}
					
					
					if (ballCent.x-ballRad <= holdUL.x)  //if ball hit from left
					{
						boball.changeXvelocity(-Math.abs(xVel));
								
					}
					
					if (ballCent.y+ballRad >= holdLR.y)  //if ball hit from bottom
					{
						boball.changeYvelocity(Math.abs(yVel));
					}						

					if (ballCent.y-ballRad <= holdUL.y)  //if ball hit from top
					{
						boball.changeYvelocity(-Math.abs(yVel));
					}	
				
					this.screen.myScore += 100;  //updates score
					Toolkit.getDefaultToolkit().beep();  // makes the cool beeping sound
					
					
					//deletes a Brick100
					toDelBrick = new DudBrick( bobrick.getCanvas(), 
												bobrick.getBrickRepos(),
												bobrick.getUpperLft(),
												bobrick.getLowerRt());
					deleteBrick(toDelBrick, i);
				
					//creating multiple balls
					if ( ((Brick100)bobrick).multiBrickTag > 0.9 && (boball instanceof ClassicBall)) 
					{
						this.screen.ballrepos.makeMultiBalls ((ClassicBall)boball);
					}
					
				}//end of if bobrick instanceof Brick100 loop
				
				/*checks if brick hit is a stationary brick
				 *ball bounces off*/
				else if (bobrick instanceof StationaryBrick) //check last because other bricks extend StationaryBrick
				{   
					if (ballCent.x+ballRad >= holdLR.x)  //check if ball hit from right
					{
						boball.changeXvelocity(Math.abs(xVel));
					}
					
					
					if (ballCent.x-ballRad <= holdUL.x)  //check if ball hit from left
					{
						boball.changeXvelocity(-Math.abs(xVel));
								
					}
					
					if (ballCent.y+ballRad >= holdLR.y)  //check if ball hit from bottom
					{
						boball.changeYvelocity(Math.abs(yVel));
					}						

					if (ballCent.y-ballRad <= holdUL.y)  //check if ball hit from top
					{
						boball.changeYvelocity(-Math.abs(yVel));
					}
				
				}//end of stationary brick check
				
			}//end of if hit brick loop
			
		}//end of for loop
		 
	}//end of method checkHitBrick
	
	
	/*checks to see if a ghost ball has hit a brick
	 *if so then converts that brick into a stationary brick*/
	public void checkGhostHit(GhostBall boball)
	{
		int i;
		this.vectSize = this.brickvect.size(); //gets the current size of the vector
		
		//ball variables
		Point ballCent = new Point(boball.getCenter());
		double ballRad = boball.getRadius();
	
		//brick variables
		BreakOutBrick bobrick;
		Point holdUL, holdLR;
		
		//checks each element of the vector if ball hit that element
		for (i=0; i<vectSize; i++)
		{
			bobrick = (BreakOutBrick)(brickvect.get(i));
			holdUL = new Point( bobrick.getUpperLft() );
			holdLR = new Point( bobrick.getLowerRt() );
			
			//checks if has hit in range of a brick	
			if (  ((ballCent.x+ballRad) >= holdUL.x) 
						&& ((ballCent.x-ballRad) <= holdLR.x) 
						&& ((ballCent.y+ballRad) >= holdUL.y)
						&& ((ballCent.y-ballRad) <= holdLR.y) )
			
			{
				if (bobrick instanceof Brick100)
				{
					StationaryBrick convertToStatBrick = new StationaryBrick(
																	bobrick.getCanvas(), 
																	bobrick.getBrickRepos(),
																	bobrick.getUpperLft(),
																	bobrick.getLowerRt());
					System.out.println("going to convert to stat brick");
					deleteBrick(convertToStatBrick, i);												
					
				}	
			}// end of if loop checking range of bricks
		
		}//end of for loop of going through vector
	}//end of CheckGhostHit
	
	
	/*paints the bricks in the repository
	 *called by ScreenCanvas's paintFrame()*/
	public void paintBricks(Graphics g)
	{	int i;
		BreakOutBrick o;
		
		for (i=0; i<vectSize; i++)  
		{
			o = (BreakOutBrick)brickvect.get(i);
			
			if( o instanceof StationaryBrick)  //painting a stationary brick
			{
				int x = o.getUpperLft().x;
				int y = o.getUpperLft().y;
				int width = o.getLowerRt().x - o.getUpperLft().x;
				int height = o.getLowerRt().y - o.getUpperLft().y;
				
				g.setColor(Color.gray);
				g.fill3DRect( x, y, width, height,true);
			}//end of if statement- stationary brick
			
			if( o instanceof Brick100)  //painting a brick100
			{
				int x = o.getUpperLft().x;
				int y = o.getUpperLft().y;
				int width = o.getLowerRt().x - o.getUpperLft().x;
				int height = o.getLowerRt().y - o.getUpperLft().y;
				
				g.setColor(Color.orange);
				g.fill3DRect( x, y, width, height,true);
			}//end of if statement- stationary brick
			
		}//end of for loop

	}//end of paintBricks method
	
}