package com.srbenoit.geom;

import com.srbenoit.log.LoggedObject;

/**
 * A simple two-dimensional point.
 */
public class Point2 extends LoggedObject implements Point2Int {

    /** the X coordinate */
    private double posX;

    /** the Y coordinate */
    private double posY;

    /**
     * Constructs a point at the origin.
     */
    public Point2() {

        this.posX = 0;
        this.posY = 0;
    }

    /**
     * Constructs a point.
     *
     * @param  xCoord  the X coordinate
     * @param  yCoord  the Y coordinate
     */
    public Point2(final double xCoord, final double yCoord) {

        this.posX = xCoord;
        this.posY = yCoord;
    }

    /**
     * Constructs a point.
     *
     * @param  source  the point whose coordinates are to be copied
     */
    public Point2(final Point2Int source) {

        this.posX = source.getPosX();
        this.posY = source.getPosY();
    }

    /**
     * Gets the X coordinate.
     *
     * @return  the X coordinate
     */
    public double getPosX() {

        return this.posX;
    }

    /**
     * Sets the X coordinate.
     *
     * @param  xCoord  the X coordinate
     */
    public void setPosX(final double xCoord) {

        this.posX = xCoord;
    }

    /**
     * Gets the Y coordinate.
     *
     * @return  the Y coordinate
     */
    public double getPosY() {

        return this.posY;
    }

    /**
     * Sets the Y coordinate.
     *
     * @param  yCoord  the Y coordinate
     */
    public void setPosY(final double yCoord) {

        this.posY = yCoord;
    }

    /**
     * Sets the coordinates of the point.
     *
     * @param  xCoord  the x coordinate
     * @param  yCoord  the y coordinate
     */
    public void setPos(final double xCoord, final double yCoord) {

        this.posX = xCoord;
        this.posY = yCoord;
    }

    /**
     * Sets the coordinates of the point from another point.
     *
     * @param  source  the point whose position is to be copied
     */
    public void setPos(final Point2Int source) {

        this.posX = source.getPosX();
        this.posY = source.getPosY();
    }

    /**
     * Moves the coordinates of the point.
     *
     * @param  xDelta  the change to the x coordinate
     * @param  yDelta  the change to the y coordinate
     */
    public void move(final double xDelta, final double yDelta) {

        this.posX += xDelta;
        this.posY += yDelta;
    }

    /**
     * Moves the coordinates of the point by a vector.
     *
     * @param  vector  the vector by which to move the point
     */
    public void move(final Vector2Int vector) {

        this.posX += vector.getVecX();
        this.posY += vector.getVecY();
    }

    /**
     * Adds a scaled version of a vector to this point's position (this = this + scale tuple).
     *
     * @param  scale   the scalar value
     * @param  vector  the vector to be scaled then added
     */
    public void moveScaled(final double scale, final Vector2Int vector) {

        this.posX += vector.getVecX() * scale;
        this.posY += vector.getVecY() * scale;
    }

    /**
     * Computes the square of the Euclidean distance between this point and another point.
     *
     * @param   otherPoint  the other point
     * @return  the square of the distance
     */
    public double distSquared(final Point2Int otherPoint) {

        double distX;
        double distY;

        distX = this.posX - otherPoint.getPosX();
        distY = this.posY - otherPoint.getPosY();

        return (distX * distX) + (distY * distY);
    }

    /**
     * Computes the Euclidean distance between this point and another point.
     *
     * @param   otherPoint  the other point
     * @return  the distance
     */
    public double dist(final Point2Int otherPoint) {

        double distX;
        double distY;

        distX = this.posX - otherPoint.getPosX();
        distY = this.posY - otherPoint.getPosY();

        return Math.sqrt((distX * distX) + (distY * distY));
    }

    /**
     * Generates the string representation of the point.
     *
     * @return  the <code>String</code> representation
     */
    @Override public String toString() {

        StringBuilder str;

        str = new StringBuilder(30);

        str.append('(');
        str.append(this.posX);
        str.append(", ");
        str.append(this.posY);
        str.append(')');

        return str.toString();
    }
}
