import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.Random;
import Circle;
import Square;

/**
 * Draw some circles or squares on the screen.  Created as an example
 * solution for HW3 of CSC152 99S.
 *
 * @author Samuel A. Rebelsky
 * @version 1.0 of February 1999
 */
public class DrawingAssistant {

  // +---------+-------------------------------------------------
  // | Methods |
  // +---------+

  /**
   * Draw a circle in a graphics region, centered at a particular 
   * point in the region.
   * <br>Precondition: The circle has been initialized.
   * <br>Precondition: The center is in the graphics area.
   * <br>Postcondition: The circle (or appropriate portion thereof)
   *    is drawn.
   * <br>Postcondition: The circle is not affected (it has the
   *    same color and size).
   */
  public void drawOne(Circle circle, int x, int y, Graphics g) {
    circle.draw(x,y,g);
  } // drawOne(Circle,int,int,Graphics)

  /**
   * Draw a square in a graphics region, centered at a particular 
   * point in the region.
   * <br>Precondition: The square has been initialized.
   * <br>Precondition: The center is in the graphics area.
   * <br>Postcondition: The square (or appropriate portion thereof)
   *    is drawn.
   * <br>Postcondition: The square is not affected (it has the
   *    same color and size).
   */
  public void drawOne(Square square, int x, int y, Graphics g) {
    square.draw(x,y,g);
  } // drawOne(Square,int,int,Graphics)

  /**
   * Draw a sequence of circles in a graphics region. 
   * <br>Precondition: The circle has been initialized.
   * <br>Postcondition: The portions of the circles that fall within
   *   the graphics region should now be within the graphics region.
   * <br>Postcondition: The circle is not affected (it has the
   *    same color and size).
   */
  public void drawSequence(Circle circle,
                           int n, 
                           int x, int y, 
                           int deltaX, int deltaY, 
                           Graphics g) {
    for (int i = 0; i < n; ++i) {
      // It's the ith circle, so offset by i*deltaX and i*deltaY.
      // Another strategy would be to add deltaX to x and deltaY
      // to y each time.
      drawOne(circle, x+i*deltaX, y+i*deltaY, g);
    } // for
  } // drawSequence(Circle,int,int,int,int,Graphics)

  /**
   * Draw a sequence of copies of a square in a graphics region. 
   * <br>Precondition: The square has been initialized.
   * <br>Postcondition: The portions of the copies that fall within
   *   the graphics region should now be within the graphics region.
   * <br>Postcondition: The square is not affected (it has the
   *    same color and size).
   */
  public void drawSequence(Square square,
                           int n, 
                           int x, int y, 
                           int deltaX, int deltaY, 
                           Graphics g) {
    for (int i = 0; i < n; ++i) {
      // It's the ith square , so offset by i*deltaX and i*deltaY.
      // Another strategy would be to add deltaX to x and deltaY
      // to y each time.
      drawOne(square, x+i*deltaX, y+i*deltaY, g);
    }
  } // drawSequence(Square,int,int,int,int,Graphics)

  /**
   * Draw a sequence of concentric circles in a graphics region.
   * Depending on how the circle is drawn, this may not be obvious.
   * <br>Precondition: The circle has been initialized.
   * <br>Postcondition: The portions of the circles that fall within
   *   the graphics region should now be within the graphics region.
   * <br>Postcondition: The circle is not affected (it has the
   *    same color and size at the end that it had at the start).
   */
  public void drawConcentric(Circle circle, 
                             int n, 
                             int x, int y, 
                             int deltaSize,
                             Graphics g) {
    // Remember the size.  Yes, I know I could write a formula,
    // but this is much easier and less error-prone.
    int startSize = circle.getSize();
    for (int i = 0; i < n; ++i) {
      // Draw the ith concentric circle.  All of them are centered
      // around the same point, but differ in their size.
      drawOne(circle, x,y, g);
      // Change the size for the next go-round
      circle.setSize(circle.getSize() + deltaSize);
    } // for
    // Restore the size.
    circle.setSize(startSize);
  } // drawConcentric(int,Circle,int,int,int,Graphics)

  /**
   * Draw a sequence of concentric squares in a graphics region.
   * Depending on how each square is drawn, this may not be obvious.
   * <br>Precondition: The square has been initialized.
   * <br>Postcondition: The portions of the squares that fall within
   *   the graphics region should now be within the graphics region.
   * <br>Postcondition: The square is not affected (it has the
   *    same color and size at the end that it had at the start).
   */
  public void drawConcentric(Square square, int n, 
                             int x, int y, 
                             int deltaSize,
                             Graphics g) {
    // Remember the size.  Yes, I know I could write a formula,
    // but this is much easier and less error-prone.
    int startSize = square.getSize();
    for (int i = 0; i < n; ++i) {
      // Draw the ith concentric square.  All of them are centered
      // around the same point, but differ in their size.
      drawOne(square, x,y, g);
      // Change the size for the next go-round
      square.setSize(square.getSize() + deltaSize);
    } // for
    // Restore the size.
    square.setSize(startSize);
  } // drawConcentric(Square,int,int,int,int,Graphics)

  /**
   * Draw n copies of the given circle.  Note that a failing of
   * this class is that there seems to be no way to get the bounds 
   * of the current drawing region.  Hence, this uses the area
   * 1..100 x 1..100.
   * <br>Precondition: The circle has been initialized.
   * <br>Postcondition: N copies of the circle have been drawn.
   * <br>Postcondition: The circle is not otherwise affected.
   */
  public void drawRandom(Circle circle, int n, Graphics g) {
    // Create something that knows how to generate random numbers.
    Random generator = new Random();
    // The x and y coordinates of the center of the ``random'' circle.
    int x;
    int y;

    // For the appropriate number of times, pick a random point
    // and draw the circle.
    for (int i = 0; i < n; ++i) {
      x = Math.abs(generator.nextInt()) % 100;
      y = Math.abs(generator.nextInt()) % 100;
      drawOne(circle,x,y,g);
    } // for
  } // drawRandom(Circle,int,Grpahics)

  /**
   * Draw n copies of the given square.  Uses a clever trick
   * to determine where those squares might go.  (Yes, it's bad
   * design for the two drawRandom's to behave so differently,
   * but this is more as an exercise.
   * <br>Precondition: The square has been initialized.
   * <br>Precondition: The clipping region (legally drawable area)
   *    of the graphics region is nonempty.
   * <br>Postcondition: N copies of the square have been drawn.
   * <br>Postcondition: The square is not otherwise affected.
   */
  public void drawRandom(Square square, int n, Graphics g) {
    // Create something that knows how to generate random numbers.
    Random generator = new Random();
    // The x and y coordinates of the center of the ``random'' circle.
    int x;
    int y;
    // Get information about the graphics object.
    Rectangle clip = g.getClipBounds();
    int leftBorder = clip.x;
    int topBorder = clip.y;
    int width = clip.width;
    int height = clip.height;

    // For the appropriate number of times, pick a random point
    // and draw the square.  Note that some squares will be drawn
    // partially outside of the boundaries.
    for (int i = 0; i < n; ++i) {
      x = leftBorder + (Math.abs(generator.nextInt()) % width);
      y = topBorder + (Math.abs(generator.nextInt()) % width);
      drawOne(square,x,y,g);
    } // for
  } // drawRandom(Square,int,Graphics)
} // class DrawingAssistant

