# controller.py
# YOUR NAME(S) AND NETID(S) HERE
# skeleton by Walker M. White (wmw2), Lillian Lee (LJL2), Steve Marschner (SRM2)
# Spring 2013
# DATE YOU COMPLETED THIS HERE
"""Controller module for Breakout

This module contains a class and global constants for the game Breakout.
Unlike the other files in this assignment, you are 100% free to change
anything in this file. You can change any of the constants in this file
(so long as they are still named constants), and add or remove classes."""
import colormodel
import random
from graphics import *

# CONSTANTS

# Width of the game display (all coordinates are in pixels)
GAME_WIDTH  = 480
# Height of the game display
GAME_HEIGHT = 620

# Width of the paddle
PADDLE_WIDTH = 58
# Height of the paddle
PADDLE_HEIGHT = 11
# Distance of the (bottom of the) paddle up from the bottom
PADDLE_OFFSET = 30

# Horizontal separation between bricks
BRICK_SEP_H = 5
# Vertical separation between bricks
BRICK_SEP_V = 4
# Height of a brick
BRICK_HEIGHT = 8
# Offset of the top brick row from the top
BRICK_Y_OFFSET = 70

# Number of bricks per row
BRICKS_IN_ROW = 10
# Number of rows of bricks, in range 1..10.
BRICK_ROWS = 10
# Width of a brick
BRICK_WIDTH = float(GAME_WIDTH)/BRICKS_IN_ROW - BRICK_SEP_H

# Diameter of the ball in pixels
BALL_DIAMETER = 18

# Number of attempts in a game
NUMBER_TURNS = 3

# Basic game states
# Game has not started yet
STATE_INACTIVE = 0
# Game is active, but waiting for next ball
STATE_PAUSED   = 1
# Ball is in play and being animated
STATE_ACTIVE   = 2
# Game is over, deactivate all actions
STATE_COMPLETE = 3

# ADD MORE CONSTANTS (PROPERLY COMMENTED) AS NECESSARY


# CLASSES
class Breakout(GameController):
    """Instance is the primary controller for a Breakout game.

    This class extends GameController and implements the various methods
    necessary for running the game.

        Method initialize starts up the game.

        Method update animates the ball and provides the physics.

        The on_touch methods handle mouse (or finger) input.

    Below are instance variables we (strongly) suggest you use.  You may also
    add other instance variables (such as those suggested in the handout); if
    you do, BE SURE TO ADD CLASS-INVARIANT COMMENTS: what your variables mean,
    and what's always true about them.  This is a *very important* habit for
    your later programming lives.

    _state [int]: Current play state of the game; needed by the on_touch methods
                  Invariant: One of STATE_INACTIVE, STATE_PAUSED, STATE_ACTIVE,
                  STATE_COMPLETE

    _bricks [list of Brick]: List of currently active "bricks" in the game.
                             Empty if and only if _state is STATE_INACTIVE
                             or STATE_COMPLETE

    _paddle [Paddle]: The player's paddle.  Is None if and only if _state is
                      STATE_INACTIVE or STATE_COMPLETE

    _ball [Ball]: The ball.  Is None if and only if _state is not STATE_ACTIVE

    _message[Message]: A message displayed on the screen.  Is None if and
                       only if _state is STATE_ACTIVE
    """


    # METHODS

    def initialize(self):
        """Initialize the game state.

        Initialize any state variables as necessary to satisfy invariants.
        When done, set the state to STATE_INACTIVE, and display a message
        saying that the user should press to play a game."""

        self._state  = STATE_INACTIVE
        self._bricks = []
        self._paddle = None
        self._ball = None
        self._message = None

        pass  # IMPLEMENT ME

    def update(self, dt):
        """Animate a single frame in the game.

        This is the method that does most of the work.  It moves the ball
        (if there is one), and looks for any collisions.  If there is a
        collision, it changes the velocity of the ball and removes any bricks
        if necessary.

        This method may need to change the state of the game.  If the ball
        goes off the screen, change the state to either STATE_PAUSED (if the
        player still has some tries left) or STATE_COMPLETE (game over).  If
        the last brick is removed, change _state to STATE_COMPLETE (game over).
        Display messages as appropriate.

        Precondition: dt is the time since last update (a float).  You can
        ignore it."""
        pass  # IMPLEMENT ME

    def on_touch_down(self,view,touch):
        """Respond to the mouse (or finger) being pressed (but not released)

        This method changes the game state, possibly moving from the current
        state to STATE_ACTIVE, doing whatever work is required to carry out that
        transition.  It also moves the paddle if appropriate.

        Precondition: <view> is just the view attribute (unused because we have
        access to the view attribute).  <touch> is a MotionEvent, which has
        attributes <x> and <y> that store the location in the window of the
        mouse (or finger)."""
        pass  # IMPLEMENT ME

    def on_touch_move(self,view,touch):
        """Respond to the mouse (or finger) being moved.

        If state is STATE_ACTIVE or STATE_PAUSED, then this method should move
        the paddle. For all other states, this method is ignored.

        Precondition: <view> is just the view attribute (unused because we have
        access to the view attribute).  <touch> is a MotionEvent, which has
        attributes <x> and <y> that store the location in the window of the
        mouse (or finger)."""
        pass  # IMPLEMENT ME

    def on_touch_up(self,view,touch):
        """Respond to the mouse (or finger) being released.

        If state is STATE_ACTIVE, then this method should stop moving the
        paddle. For all other states, it is ignored.

        Precondition: <view> is just the view attribute (unused because we have
        access to the view attribute).  <touch> is a MotionEvent, which has
        attributes <x> and <y> that store the location in the window of the
        mouse (or finger)."""
        pass  # IMPLEMENT ME

    # ADD MORE HELPER METHODS (PROPERLY SPECIFIED) AS NECESSARY