# state.py
# Walker M. White (wmw2)
# November 17, 2013
"""Module to show off how to use states.

We make a subclass of game, and override the update, init, and draw methods."""
import colormodel
import random
import math
from game2d import *

### CONSTANTS ###

# Window Size
WINDOW_WIDTH  = 512
WINDOW_HEIGHT = 512

# Distance from Window Center
ANIMATION_RADIUS = 100
# AMOUNT TO CHANGE THE ANGLE
ANIMATION_STEP   = 0.1
# Ellipse Radius
ELLIPSE_RADIUS = 20

### THE ANIMATION STATES ###
NUM_STATES = 3
STATE_CIRCLE     = 0
STATE_HORIZONTAL = 1
STATE_VERTICAL   = 2

### CONTROLLER CLASS ###

class State(Game):
    """Application to animate an ellipse about a center.
    
    At each step, the update() method computes a new angle.  It finds the (x,y)
    coordinate that corresponds to the polar coordinate (ANIMATION_RADIUS,angle)
    and puts the ellipse there.
    
    Instance Attributes (Not hiding any):
        view:      the view (inherited from Game) [GView]
        lastclick: last position clicked 
                   [GPoint, None if mouse not down last frame]     
        state:     animation state
                   [one of STATE_CIRCLE, STATE_HORIZONTAL, STATE_VERTICAL]
        factor:    ellipse animation factor [float, 0 if state changed]
        ellipse:   the ellipse to animate 
                   [GEllipse, 
                    center is (RADIUS,self.angle) in polar coords if STATE_CIRCLE,
                    center is (factor+width/2,height/2) if STATE_HORIZONTAL
                    center is (width/2,height/2+factor) if STATE_VERTICAL]
    """

    # THREE MAIN METHODS
    
    def init(self):
        """Special initialization method to create attributes.
        
        Not the SAME as __init__. DO NOT DEFINE __init___."""
        self.state     = STATE_CIRCLE
        self.lastclick = None
        self.factor    = 0
        self.ellipse   = GEllipse(x=0,y=0,width=ELLIPSE_RADIUS,height=ELLIPSE_RADIUS,
                                  fillcolor=colormodel.RED)
    
    def update(self,dt):
        """Determine the current state and animate the ellipse."""
        # helper method to process the mouse click
        self._changeOnClick()
        
        # Process the states.  Send to helper methods
        if self.state == STATE_CIRCLE:
            self._animateCircle()
        elif self.state == STATE_HORIZONTAL:
            self._animateHorizontal()
        elif self.state == STATE_VERTICAL:
            self._animateVertical()

        # Increment factor
        self.factor = (self.factor+ANIMATION_STEP) % (2*math.pi)
    
    def draw(self):
        """Draw the ellipse"""
        self.ellipse.draw(self.view)

    # HELPER METHODS

    def _animateCircle(self):
        """Animate on a circle."""
        x = ANIMATION_RADIUS*math.cos(self.factor)+self.width/2.0
        y = ANIMATION_RADIUS*math.sin(self.factor)+self.height/2.0
        self.ellipse.x = x
        self.ellipse.y = y

    def _animateHorizontal(self):
        """Animate on the horizontal access."""
        x = ANIMATION_RADIUS*math.cos(self.factor)+self.width/2.0
        self.ellipse.x = x
        self.ellipse.y = self.height/2.0

    def _animateVertical(self):
        """Animate on the vertical access."""
        y = ANIMATION_RADIUS*math.sin(self.factor)+self.height/2.0
        self.ellipse.x = self.width/2.0
        self.ellipse.y = y

    def _changeOnClick(self):
        """Check for a click and add a Rocket if necessary.
        
        A 'click' is the animation frame after the mouse is pressed for the first
        time in a while (so _lastclick is None)."""
        touch = self.view.touch # View stores the touch information
        if self.lastclick is None and not touch is None:
            # Click happened.  Change the state
            self.state = (self.state + 1) % NUM_STATES
            # State changed; reset factor
            self.factor = 0
        else:
            self.changed = False # No change in state
        
        # Update lastclick
        self.lastclick = touch


# Application Code
if __name__ == '__main__':
    State(width=WINDOW_WIDTH,height=WINDOW_HEIGHT,fps=60.0).run()