/**
 * Represents a point in the plane.
 */
public class Point {

	/** The {@code x}-coordinate of the point. */
	private double x;
	/** The {@code y}-coordinate of the point. */
	private double y;

	/**
	 * Constructs a point in the origin of the plane (i.e. (0,0)).
	 */
	public Point() {
		this.x = 0;
		this.y = 0;
	}

	/**
	 * Constructs a point at the specified coordinates.
	 * @param x the {@code x}-coordinate
	 * @param y the {@code y}-coordinate
	 */
	public Point( double x, double y ) {
		this.x = x;
		this.y = y;
	}

	/**
	 * Returns the {@code x}-coordinate of the point.
	 * @return the {@code x}-coordinate of the point
	 */
	public double getX() {
		return this.x;
	}

	/**
	 * Returns the {@code y}-coordinate of the point.
	 * @return the {@code y}-coordinate of the point
	 */
	public double getY() {
		return this.y;
	}

	/**
	 * Sets the {@code x}-coordinate to the specified real value.
	 * @param x the new {@code x}-coordinate
	 */
	public void setX( double x ) {
		this.x = x;
	}

	/**
	 * Sets the {@code y}-coordinate to the specified real value.
	 * @param y the new {@code y}-coordinate
	 */
	public void setY( double y ) {
		this.y = y;
	}

	/**
	 * Adds a given point to this point.
	 * @param p a given point
	 */
	public void add( Point p ) {
		x += p.x;
		y += p.y;
	}

	/**
	 * Mirrors this point at {@code y}-axis.
	 */
	public void mirrorY() {
		this.x = -this.x;
	}

	/**
	 * Mirrors this point at {@code x}-axis.
	 */
	public void mirrorX() {
		this.y = -this.y;
	}

	/**
	 * Mirrors this point at {@code x} and {@code <}-axis.
	 */
	public void mirror() {
		mirrorX();
		mirrorY();
	}

	/**
	 * Multiplicates the point with an scalary value.
	 * @param s the scalary value
	 */
	public void scalaryMultiplicate( double s ) {
		x *= s;
		y *= s;
	}

	/**
	 * Returns the euclidean distance between this point and a specified point {@code p}
	 * @param p the other point
	 * @return the distance between p and this point
	 */
	public double distance( Point p ) {
		return Math.sqrt( (this.x - p.x) * (this.x - p.x) + (this.y - p.y) * (this.y - p.y) );
	}

	/**
	 * Compares this point with another instance. Points are equal if they both
	 * have the same {@code x}- and {@code y}-coordinates.
	 * @param p point that is compared to this point
	 * @return {@code true} if both coordinates are equal, {@code false} otherwise
	 */
	public boolean equals( Point p ) {
		return (this.x == p.x && this.y == p.y);
	}

	/**
	 * Transforms this point into a text representation of the form <i>({@code x}, {@code y}})</i>.
	 */
	@Override
	public String toString() {
		return "(" + Math.round( x*100 )/100.0 + ", " + Math.round( y*100 )/100.0 + ")";
	}

	/**
	 * A method that clones this point and returns the new instance.
	 * @return the new copied instance.
	 */
	@Override
	public Point clone() {
		return new Point( this.x, this.y );
	}
}
