"""
This project demonstrates NESTED LOOPS (i.e., loops within loops)
in the context of TWO-DIMENSIONAL GRAPHICS.

Authors: David Mutchler, Valerie Galluzzi, Mark Hays, Amanda Stouder,
         their colleagues and Elijah Williams.
"""  # DONE: 1. PUT YOUR NAME IN THE ABOVE LINE.

import rosegraphics as rg


def main():
    """ Calls the other functions to demonstrate them. """
    nested_loops_in_graphics_example()


def nested_loops_in_graphics_example():
    """
    Demonstrates nested loops in a TWO-DIMENSIONAL GRAPHICS example.
    """
    width = 800
    height = 600
    title = 'Rectangles and Triangles of Circles'
    window = rg.RoseWindow(width, height, title)

    window.continue_on_mouse_click('Click to run Example 1.')

    # ------------------------------------------------------------------
    starting_point = rg.Point(50, 50)
    # ------------------------------------------------------------------

    # ------------------------------------------------------------------
    # First set of circles
    # ------------------------------------------------------------------
    radius = 20
    starting_circle = rg.Circle(starting_point, radius)

    rectangle_of_circles(window, starting_circle.clone(), 4, 12)
    window.continue_on_mouse_click('Click to run Example 2.')

    # ------------------------------------------------------------------
    # Second set of circles
    # ------------------------------------------------------------------
    starting_circle.move_by(180, 400)

    rectangle_of_circles(window, starting_circle.clone(), 14, 2)
    window.continue_on_mouse_click('Click to run Example 3.')

    # ------------------------------------------------------------------
    # Third and last set of circles
    # ------------------------------------------------------------------
    starting_circle.move_by(200, -400)

    triangle_of_circles(window, starting_circle.clone(), 8)
    window.close_on_mouse_click()

# ----------------------------------------------------------------------
# DONE: 2.
#  *** Unless your instructor directs you otherwise,
#      watch the video
#          nested_loops_in_GRAPHICS.mp4
#      in Preparation for Session 18
#          ** NOW **
#      As the video proceeds, LOOK AT THE CODE BELOW.
#      It is the same as the video.
#      (Pause the video when it completes the following problem.)
#
#  *** USE THE VIDEO to understand the TECHNIQUE used in this example.
#
#   AFTER you have watched the video, asking questions as needed,
#   and you feel that you understand the TECHNIQUE it presents, THEN:
#
#     *** Change the TO DO above to DONE. ***
# ----------------------------------------------------------------------


def rectangle_of_circles(window, circle, m, n):
    """
    Draws an m x n rectangle of circles (i.e. m columns and n rows)
    on the given rg.RoseWindow.  The given rg.Circle specifies:
      - The position of the upper-left circle drawn and also
      - The radius that all the circles have.
    After drawing each circle, pauses briefly (0.1 second).

    Preconditions:
      :type window: rg.RoseWindow
      :type circle: rg.Circle
      :type m: int
      :type n: int
    and m and n are small, positive integers.
    """
    original_x = circle.center.x
    original_y = circle.center.y
    radius = circle.radius

    x = original_x
    y = original_y
    for i in range(n):  # Loop through the rows
        for j in range(m):  # Loop through the columns
            new_circle = rg.Circle(rg.Point(x, y), radius)
            new_circle.attach_to(window)
            window.render(0.1)

            x = x + (2 * radius)  # Move x to the right, for next circle

        y = y + 2 * radius  # Move y down, for the next row of circles
        x = original_x  # Reset x to the left-edge, for the next row


# ----------------------------------------------------------------------
# DONE: 3.
#  *** Unless your instructor directs you otherwise,
#      watch the video
#          nested_loops_in_GRAPHICS.mp4
#      in Preparation for Session 18
#          ** NOW **
#      As the video proceeds, LOOK AT THE CODE BELOW.
#      It is the same as the video.
#      (Continue the video from where you paused it in the previous problem.)
#
#  *** USE THE VIDEO to understand the TECHNIQUE used in this example.
#
#   AFTER you have watched the video, asking questions as needed,
#   and you feel that you understand the TECHNIQUE it presents, THEN:
#
#     *** Change the TO DO above to DONE. ***
# ----------------------------------------------------------------------


def triangle_of_circles(window, circle, n):
    """
    Draws an n x n right-triangle of circles
    (1 circle in the top row, 2 in the next row, etc., until n rows)
    on the given rg.RoseWindow.  The given rg.Circle specifies:
      - The position of the upper-left circle drawn and also
      - The radius that all the circles have.
    After drawing each circle, pauses briefly (0.1 second).

    Preconditions:
      :type window: rg.RoseWindow
      :type circle: rg.Circle
      :type n: int
    and m is a small, positive integer.
    """
    # ------------------------------------------------------------------
    # NOTE: The solution below is IDENTICAL to the rectangle_of_circles
    #       solution except that the INNER loop has  j+1  instead of m.
    # Make sure you understand why this works!
    # ------------------------------------------------------------------
    original_x = circle.center.x
    original_y = circle.center.y
    radius = circle.radius

    x = original_x
    y = original_y
    for j in range(n):  # Loop through the rows
        for _ in range(j + 1):  # Loop through the columns
            new_circle = rg.Circle(rg.Point(x, y), radius)
            new_circle.attach_to(window.initial_canvas)
            window.render(0.1)

            x = x + (2 * radius)  # Move x to the right, for next circle

        y = y + 2 * radius  # Move y down, for the next row of circles
        x = original_x  # Reset x to the left-edge, for the next row


# ----------------------------------------------------------------------
# Calls  main  to start the ball rolling.
# ----------------------------------------------------------------------
main()
