import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

import javax.swing.JPanel;

public class Arena extends JPanel implements Runnable
{
    int MOVE_LEFT = -1;
    int MOVE_RIGHT = 1;
    int MOVE_NONE = 0;
    int PAUSE = 30;
    
    Color DARK_BLUE = new Color(0, 0, 100);
    
    int ballWidth = 8;
    int ballHeight = 8;
    
    int paddleWidth = 55;
    int paddleHeight = 10;
    int bottomGap = 20;
    
    int brickWidth = 30;
    int brickHeight = 10;
    int brickGapHeight = 20;
    int brickGapWidth = 16;
    
    
    Thread thread = null;
    int pause = PAUSE;
    
    int x = 100;
    int move = MOVE_NONE;
    
    int bx = -1;
    int by = -1;
    int dx = -2;
    int dy = 3;
    
    boolean gameOver = true;
    Game parent;
    Brick bricks[][] = new Brick[6][8];
    
    public Arena(Game parent)
    {
        super();
        
        this.parent = parent;
        initBricks();
    }
    
    public void initBricks()
    {
       for (int row = 0; row < bricks.length; row++)
       {
           for (int col = 0; col < bricks[row].length; col++)
           {
               bricks[row][col] = new Brick(brickToX(col), brickToY(row), Color.green);
               if ((row % 2) == 0)
               {
                   if ((col % 4) == 0)
                       bricks[row][col].setFast(true);
                   else if ((col % 4) == 2)
                       bricks[row][col].setSlow(true);    
               }
               else
               {
                   if ((col % 4) == 0)
                       bricks[row][col].setGrow(true);
                   else  if ((col % 4) == 2)
                       bricks[row][col].setShrink(true);    
               }
           }
       }
    }
    
    public void drawBricks(Graphics g)
    {
        g.setColor(Color.green);
        
        for (int row = 0; row < bricks.length; row++)
        {
            for (int col = 0; col < bricks[row].length; col++)
            {
                bricks[row][col].draw(g);
            }
        }    
    }
    
    private void checkHitBrick()
    {
        for (int row = 0; row < bricks.length; row++)
        {
            for (int col = 0; col < bricks[row].length; col++)
            {
                int bcenterX = bx + ballWidth/2;
                int bcenterY = by + ballHeight/2;
                
                if (bricks[row][col].contains(bcenterX, bcenterY))
                {
                    bricks[row][col].setValid(false);
                    parent.advanceCounter();                      
                    parent.soundPing();
                    dy *= (-1);
                    
                    if (bricks[row][col].isFast())
                        this.faster();
                    if (bricks[row][col].isSlow())
                        this.slower();
                    if (bricks[row][col].isShrink())
                        paddleWidth = (int)(1.5*paddleWidth);
                    if (bricks[row][col].isGrow())
                        paddleWidth = (int)(0.75*paddleWidth);
               
                }
            }
        }
    }

    private void checkHitPaddle()
    {
        int bcenterX = bx + ballWidth/2;
        int bcenterY = by + ballHeight/2;
        
        if ((dy > 0) &&
            (bcenterY >=  getHeight() - paddleHeight - bottomGap))
        {
            if ((x <= bcenterX) && (bcenterX < x + paddleWidth))
            {
                dy = -dy;// + randomSign()*(int)(2*Math.random());
                dx += randomSign()*(int)(2*Math.random());
                parent.advanceCounter();
                parent.soundPing();
            }
            else
            {
                stop();
            }
        }
    }


    private int brickToY(int i)
    {
        return i * (brickHeight + brickGapHeight) + brickGapHeight;
    }

    private int brickToX(int i)
    {
        return i * (brickWidth + brickGapWidth) + brickGapWidth;
    }
    
    int randomSign()
    {
        if (Math.random() > 0.5)
            return 1;
        else
            return -1;
    }

    public void restart()
    {
        if (thread == null)
        {
            thread = new Thread(this);
            thread.start();
        }        
    }
    
    public void start()
    {
        if (thread == null)
        {
            thread = new Thread(this);
            thread.start();
            bx = x + paddleWidth/2;
            by = getHeight() - paddleHeight - bottomGap;
            dx = randomSign()*(int)(4*Math.random()) + 1;
            dy = -2;
            pause = PAUSE;
            parent.resetCounter();
            move = MOVE_NONE;
            gameOver = false;
        }
    }
    
    public void stop()
    {
        thread = null;
        move = MOVE_NONE;
        gameOver = true;
        repaint();
    }
    
    public void pause()
    {
        thread = null;
        move = MOVE_NONE;        
    }
    
    public void faster()
    {
        if (pause >= 10)
            pause -= 5;
    }
    
    public void slower()
    {
        pause += 5;        
    }
    
    public void run()
    {
        while (thread != null)
        {
            if (move == MOVE_LEFT)
                moveLeft();
            else if (move == MOVE_RIGHT)
                moveRight();
            
            bx += dx;
            by += dy;
       
            if (by <= 0)
            {
                parent.soundPong();
                dy *= (-1);
            }
            else if ((bx <= 0) || (bx >= getWidth()))
            {
                parent.soundPong();
                dx*= (-1);
            }
            else
            {
                checkHitBrick();
                checkHitPaddle();
            }
            
            repaint();
            try
            {
                thread.sleep(pause);
            }
            catch (InterruptedException e)
            {
                move = MOVE_NONE;
                e.printStackTrace();
            }
        }
    }    
    
    
    public void stopMoving()
    {
        move = MOVE_NONE;
    }
    
    public void moveRight()
    {
        if (x < getWidth() - paddleWidth)
        {
            move = MOVE_RIGHT;
            x += 8;
            repaint();
        }
        else
            move = MOVE_NONE;
    }
    
    public void moveLeft()
    {
        if (x >= 0)
        {
            move = MOVE_LEFT;
            x -= 8;
            repaint();
        }
        else
            move = MOVE_NONE;
    }

    public void drawPaddle(Graphics g)
    {
        g.setColor(DARK_BLUE);
        g.drawRect(x, getHeight()-paddleHeight-bottomGap, paddleWidth, paddleHeight);
        g.setColor(Color.BLUE);
        g.fillRect(x, getHeight()-paddleHeight-bottomGap, paddleWidth, paddleHeight);
    }
    
    public void drawBall(Graphics g)
    {
        if (gameOver)
        {
            bx = x + paddleWidth/2 - ballWidth/2;
            by = getHeight()-paddleHeight-bottomGap-ballHeight;;
        }
        g.setColor(Color.RED);
        g.fillOval(bx, by, ballHeight, ballWidth);
    }
    
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        drawBricks(g);
        drawPaddle(g);
        drawBall(g);
    }
    
    public Dimension getPreferredSize()
    {
        return new Dimension(400, 400);
    }
}
