"""
Created on Nov 10, 2022

@author: Robert Duvall

This module represents the basics of using Views to manage simple flow within a game.
"""
import random
import arcade


# Choose a name for your game to appear in the title bar of the game window
GAME_NAME = 'TO BE DETERMINED'
# Choose the size of your game board
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 800
# Choose placement of game text
TEXT_OFFSET = 100
# Choose values that determine game play
SPRITE_MOVE_TIME = 0.25
SPRITE_RADIUS = 40


###
# Game view related classes to show text messages without worrying about interacting with the game.
#
# Views are similar to the Window class (you will override the same methods) but allow you to switch
# between them to make it easy to keep different Sprite collections, updates, and responses to input.
#
# These are a simple as possible, just displaying text until the user interacts with it.
###
class InstructionsView(arcade.View):
    """
    This class represents a screen that displays text for the game instructions until the user clicks the mouse.
    Overrides typical methods:
    - setting up any objects to appear in game (in constructor)
    - setting up anything extra when the view actually appears (in method on_show_view)
    - drawing them (in method on_draw)
    - responding to mouse input (in method on_mouse_press)
    """
    def __init__(self):
        super().__init__()
        # game instructions, could be read from a file instead
        self.instructions = "Click to win or lose - it's random :)"

    def on_show_view(self):
        """
        Called when the view is displayed, can be used to set up the game's initial state.
        """
        # set background color just once
        arcade.set_background_color(arcade.color.BABY_BLUE_EYES)

    def on_draw(self):
        """
        Draw the instructions on the screen.
        """
        # DO NOT CHANGE -- always clear the screen as the FIRST step
        self.clear()
        # draw the instruction text
        arcade.draw_text(self.instructions, SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2,
                         arcade.color.DUKE_BLUE, font_size=32, anchor_x='center')
        # tell player how to start the game
        arcade.draw_text('Click to start', SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - TEXT_OFFSET,
                         arcade.color.DUKE_BLUE, font_size=32, anchor_x='center')

    def on_mouse_press(self, x, y, button, modifiers):
        """
        Called whenever the mouse is pressed --- anywhere is fine.
        """
        # create and show a new instance of the game to get it started
        self.window.show_view(GameView())


class GameOverView(arcade.View):
    """
    This class represents a screen that displays the score, winning or losing message, and instructions for restarting.
    Overrides typical methods:
    - setting up any objects to appear in game (in constructor)
    - setting up anything extra when the view actually appears (in method on_show_view)
    - drawing them (in method on_draw)
    - responding to key input (in method on_key_press)
    """
    def __init__(self, isWinner):
        super().__init__()
        # save data from the game's end to determine which results to display
        self.is_winner = isWinner

    def on_show_view(self):
        """
        Called when the view is displayed, can be used to set up the game's initial state.
        """
        # set background color just once
        arcade.set_background_color(arcade.color.AIR_SUPERIORITY_BLUE)

    def on_draw(self):
        """
        Draw the results on the screen.
        """
        # DO NOT CHANGE -- always clear the screen as the FIRST step
        self.clear()
        # display either the winning or losing message
        if self.is_winner:
            arcade.draw_text('WINNER!', SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2,
                             arcade.color.DUKE_BLUE, font_size=48, anchor_x='center')
        else:
            arcade.draw_text('LOSER :(', SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2,
                             arcade.color.DUKE_BLUE, font_size=48, anchor_x='center')

        # tell player how to restart the game
        arcade.draw_text("Press any key to restart", SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - TEXT_OFFSET,
                         arcade.color.DUKE_BLUE, font_size=32, anchor_x='center')

    def on_key_press(self, key, modifiers):
        """
        Called whenever a key is pressed -- anywhere is fine.
        """
        # create and show a new instance of the game to restart it
        self.window.show_view(GameView())


###
# Main game view (used to extend Window) but now extends View so it can be switched with other views.
#
# Functionally, it is the same as before and overrides the same methods.
###
class GameView(arcade.View):
    """
    This class represents the entire game:
    - setting up any objects to appear in game (in constructor)
    - setting up anything extra when the view actually appears (in method on_show_view)
    - updating their values (in method on_update)
    - drawing them (in method on_draw)
    - responding to mouse input (in method on_mouse_press)
    """
    def __init__(self):
        # no need to pass size and title since this is just a view within the window
        super().__init__()
        # winning or losing is simply random :)
        self.is_winner = random.randint(0, 2) == 1
        self.sprite = arcade.SpriteCircle(SPRITE_RADIUS, arcade.color.BLUE_YONDER)

    def on_show_view(self):
        """
        Called when the view is displayed, can be used to set up the game's initial state.
        """
        arcade.set_background_color(arcade.color.BLIZZARD_BLUE)
        # ADD ONLY ONCE per View
        # when the given amount of time has passed, move the empty space by swapping it with another space
        arcade.schedule(self.move_sprite, SPRITE_MOVE_TIME)

    def on_hide_view(self):
        """
        Called when the view is displayed, can be used to stop any scheduled actions or save any data to a file.
        """
        arcade.unschedule(self.move_sprite)

    def move_sprite(self, dt):
        """
        Update each Sprite's value to match the game board's value in case it changed
        """
        self.sprite.center_x = random.randint(0, SCREEN_WIDTH)
        self.sprite.center_y = random.randint(0, SCREEN_HEIGHT)

    def on_mouse_press(self, x, y, button, modifiers):
        """
        Called whenever a mouse button is pressed.
        """
        # just clicking ends the game
        self.window.show_view(GameOverView(self.is_winner))

    def on_draw(self):
        """
        Draw all the game objects on the screen.
        """
        # DO NOT CHANGE -- always clear the screen as the FIRST step
        self.clear()
        # draw the Sprite
        self.sprite.draw()


# Create the game window (with its size and title)
window = arcade.Window(SCREEN_WIDTH, SCREEN_HEIGHT, GAME_NAME)
# Create and show the initial view
window.show_view(InstructionsView())
# Play the game forever
arcade.run()
