package net.returnvoid.graphics.shape;

import processing.core.PVector;

/**
 * An interface for building two-dimensional shapes.
 * 
 * @author Diana Lange
 *
 */
public interface RShape {

	/**
	 * Returns the number of coordinates for this shape. Can be used to iterate
	 * over all coordinates for this shape (e.g. for drawing the shape).
	 * Example:<br>
	 * 
	 * <pre>
	 * for (int i = 0; i < myShape.size(); i++) {
	 * 	PVector p = myShape.get(i);
	 * }
	 * </pre>
	 * 
	 * 
	 * @return The number of coordinates for this shape.
	 */
	public int size();

	/**
	 * Returns the coordinate with index <b>i</b>. Please make sure <b>i</b> is
	 * within bounds, e.g. using the size() method. Example:<br>
	 * 
	 * <pre>
	 * for (int i = 0; i < myShape.size(); i++) {
	 * 	PVector p = myShape.get(i);
	 * }
	 * </pre>
	 * 
	 * @param i
	 *            The index of a coordinates of this shape.
	 * @return The coordinate of the shape with the given index.
	 */
	public PVector get(int i);

	/**
	 * Returns the start coordinate for this shape. The start is defined
	 * differently for each shape. For a Line it is one of the ends, for a Rect
	 * it is the top left corner (when no rotation is applied) and so on.
	 * 
	 * @return The start coordinate for the shape.
	 */
	public PVector getStart();

	/**
	 * Returns the bounding box of this shape (will mark the bounds of the
	 * shape).
	 * 
	 * @return The bounding box.
	 */
	public Rect getBoundingBox();

	/**
	 * Returns the center coordinate of this shape.
	 * 
	 * @return The center coordinate of this shape.
	 */
	public PVector getCenter();

	/**
	 * Returns the x-position of the start coordinate for this shape. The start
	 * is defined differently for each shape. For a Line it is one of the ends,
	 * for a Rect it is the top left corner (when no rotation is applied) and so
	 * on.
	 * 
	 * @return The x-position start coordinate for the shape.
	 */
	public Float getX();

	/**
	 * Returns the y-position of the start coordinate for this shape. The start
	 * is defined differently for each shape. For a Line it is one of the ends,
	 * for a Rect it is the top left corner (when no rotation is applied) and so
	 * on.
	 * 
	 * @return The y-position start coordinate for the shape.
	 */
	public Float getY();

	/**
	 * Returns all coordinates that defines this shape.
	 * 
	 * @return The coordinates of this shape.
	 */
	public PVector[] getCoordinates();

	/**
	 * Returns the angle of shape.
	 * 
	 * @return The angle of the shape.
	 */
	public Float getRotation();

	/**
	 * Rotates the shape to the given angle (past rotations will be overridden).
	 * The rotation center will be the <b>getStart()</b> of this shape.
	 * 
	 * @param a
	 *            The target rotation angle.
	 * @return The current shape.
	 */
	public RShape setRotation(float a);

	/**
	 * Rotates the shape to the given angle (past rotations will be overridden).
	 * The rotation center will be the given location <b>c</b>.
	 * 
	 * @param c
	 *            The rotation center.
	 * @param a
	 *            The target rotation angle.
	 * @return The current shape.
	 */
	public RShape setRotation(PVector c, float a);

	/**
	 * Translates the shape to the given x-location. After the translation
	 * getStart().x will be equal to the given <b>x</b>.
	 * 
	 * @param x
	 *            The new x-position of this shape.
	 * @return The current shape.
	 */
	public RShape setX(float x);

	/**
	 * Translates the shape to the given y-location. After the translation
	 * getStart().y will be equal to the given <b>y</b>.
	 * 
	 * @param y
	 *            The new y-position of this shape.
	 * @return The current shape.
	 */
	public RShape setY(float y);

	/**
	 * Translates the shape to the given location. After the translation
	 * getStart() will be equal to the given <b>x, y</b>.
	 * 
	 * @param x
	 *            The new x-position of this shape.
	 * @param y
	 *            The new y-position of this shape.
	 * @return The current shape.
	 */
	public RShape setLocation(float x, float y);

	/**
	 * Builds and returns a true copy of this shape.
	 * 
	 * @return The copy of this shape.
	 */
	public RShape copy();

	/**
	 * Translates the coordinates by the given parameters <b>x, y</b> ( "moves
	 * the shape by <b>x, y</b>").
	 * 
	 * @param x
	 *            The horizontal translation.
	 * @param y
	 *            The vertical translation.
	 * @return The current shape.
	 */
	public RShape translate(float x, float y);

	/**
	 * Turns the shape through the given angle. The rotation center will be the
	 * <b>getStart()</b> of this shape.
	 * 
	 * @param a
	 *            The rotation angle.
	 * @return The current shape.
	 */
	public RShape rotate(float a);

	/**
	 * Turns the shape through the given angle. The rotation center will be the
	 * given location <b>c</b>.
	 * 
	 * @param c
	 *            The rotation center.
	 * @param a
	 *            The rotation angle.
	 * 
	 * @return The current shape.
	 */
	public RShape rotate(PVector c, float a);

	/**
	 * Scale the shape by the given scaling factor. For scaling factor <b>s</b>
	 * <1 the shape will shrink. For scaling factor <b>s</b>>1 the shape will
	 * expand. The scaling center will be the <b>getStart()</b> of this shape.
	 * 
	 * @param s
	 *            The scaling factor (> 0).
	 * @return The current shape.
	 */
	public RShape scale(float s);

	/**
	 * Scale the shape by the given scaling factor. For scaling factor <b>s</b>
	 * <1 the shape will shrink. For scaling factor <b>s</b>>1 the shape will
	 * expand. The scaling center will be the given location <b>c</b>.
	 * 
	 * @param p
	 *            The scaling center.
	 * @param s
	 *            The scaling factor (> 0).
	 * @return The current shape.
	 */
	public RShape scale(PVector p, float s);

	/**
	 * Draws the shape-
	 * 
	 * @return The current shape.
	 */
	public RShape draw();
}
