/*******************************************************************************
 * Copyright (c) 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jface.util;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;

/**
 * Contains static methods for performing simple geometric operations
 * on the SWT geometry classes.
 *
 * @since 3.0
 */
public class Geometry {

    /**
     * Prevent this class from being instantiated.
     * 
     * @since 3.0
     */
    private Geometry() {
    }

    /**
     * Returns the square of the distance between two points. 
     * <p>This is preferred over the real distance when searching
     * for the closest point, since it avoids square roots.</p>
     * 
     * @param p1 first endpoint
     * @param p2 second endpoint
     * @return the square of the distance between the two points
     * 
     * @since 3.0
     */
    public static int distanceSquared(Point p1, Point p2) {
        int term1 = p1.x - p2.x;
        int term2 = p1.y - p2.y;
        return term1 * term1 + term2 * term2;
    }

    /**
     * Returns the magnitude of the given 2d vector (represented as a Point)
     *  
     * @param p point representing the 2d vector whose magnitude is being computed
     * @return the magnitude of the given 2d vector
     * @since 3.0
     */
    public static double magnitude(Point p) {
        return Math.sqrt(magnitudeSquared(p));
    }

    /**
     * Returns the square of the magnitude of the given 2-space vector (represented
     * using a point)
     * 
     * @param p the point whose magnitude is being computed
     * @return the square of the magnitude of the given vector
     * @since 3.0
     */
    public static int magnitudeSquared(Point p) {
        return p.x * p.x + p.y * p.y;
    }

    /**
     * Returns the dot product of the given vectors (expressed as Points)
     * 
     * @param p1 the first vector
     * @param p2 the second vector
     * @return the dot product of the two vectors
     * @since 3.0
     */
    public static int dotProduct(Point p1, Point p2) {
        return p1.x * p2.x + p1.y * p2.y;
    }

    /**
     * Returns a new point whose coordinates are the minimum of the coordinates of the
     * given points
     * 
     * @param p1 a Point
     * @param p2 a Point
     * @return a new point whose coordinates are the minimum of the coordinates of the
     * given points
     * @since 3.0
     */
    public static Point min(Point p1, Point p2) {
        return new Point(Math.min(p1.x, p2.x), Math.min(p1.y, p2.y));
    }

    /**
     * Returns a new point whose coordinates are the maximum of the coordinates
     * of the given points
     * @param p1 a Point
     * @param p2 a Point
     * @return point a new point whose coordinates are the maximum of the coordinates
     * @since 3.0
     */
    public static Point max(Point p1, Point p2) {
        return new Point(Math.max(p1.x, p2.x), Math.max(p1.y, p2.y));
    }

    /**
     * Returns a vector in the given direction with the given
     * magnitude. Directions are given using SWT direction constants, and
     * the resulting vector is in the screen's coordinate system. That is,
     * the vector (0, 1) is down and the vector (1, 0) is right. 
     * 
     * @param distance magnitude of the vector
     * @param direction one of SWT.TOP, SWT.BOTTOM, SWT.LEFT, or SWT.RIGHT
     * @return a point representing a vector in the given direction with the given magnitude
     * @since 3.0
     */
    public static Point getDirectionVector(int distance, int direction) {
        switch (direction) {
        case SWT.TOP:
            return new Point(0, -distance);
        case SWT.BOTTOM:
            return new Point(0, distance);
        case SWT.LEFT:
            return new Point(-distance, 0);
        case SWT.RIGHT:
            return new Point(distance, 0);
        }

        return new Point(0, 0);
    }

    /**
     * Returns the point in the center of the given rectangle.
     * 
     * @param rect rectangle being computed
     * @return a Point at the center of the given rectangle.
     * @since 3.0
     */
    public static Point centerPoint(Rectangle rect) {
        return new Point(rect.x + rect.width / 2, rect.y + rect.height / 2);
    }

    /**
     * Returns a copy of the given point
     * 
     * @param toCopy point to copy
     * @return a copy of the given point
     */
    public static Point copy(Point toCopy) {
        return new Point(toCopy.x, toCopy.y);
    }
    
    /**
     * Sets result equal to toCopy
     * 
     * @param result object that will be modified
     * @param toCopy object that will be copied
     * @since 3.1
     */
    public static void set(Point result, Point toCopy) {
    	result.x = toCopy.x;
    	result.y = toCopy.y;
    }
    
    /**
     * Sets result equal to toCopy
     * 
     * @param result object that will be modified
     * @param toCopy object that will be copied
     * @since 3.1
     */
    public static void set(Rectangle result, Rectangle toCopy) {
    	result.x = toCopy.x;
    	result.y = toCopy.y;
    	result.width = toCopy.width;
    	result.height = toCopy.height;
    }

    /**
     * Adds two points as 2d vectors. Returns a new point whose coordinates are
     * the sum of the original two points.
     * 
     * @param point1 the first point (not null)
     * @param point2 the second point (not null)
     * @return a new point whose coordinates are the sum of the given points
     * @since 3.0
     */
    public static Point add(Point point1, Point point2) {
        return new Point(point1.x + point2.x, point1.y + point2.y);
    }

    /**
     * Performs vector subtraction on two points. Returns a new point equal to
     * (point1 - point2).
     * 
     * @param point1 initial point
     * @param point2 vector to subtract
     * @return the difference (point1 - point2)
     * @since 3.0
     */
    public static Point subtract(Point point1, Point point2) {
        return new Point(point1.x - point2.x, point1.y - point2.y);
    }

    /**
     * Swaps the X and Y coordinates of the given point.
     * 
     * @param toFlip modifies this point
     * @since 3.1
     */
    public static void flipXY(Point toFlip) {
    	int temp = toFlip.x;
    	toFlip.x = toFlip.y;
    	toFlip.y = temp;
    }

    /**
     * Swaps the X and Y coordinates of the given rectangle, along with the height and width.
     * 
     * @param toFlip modifies this rectangle
     * @since 3.1
     */
    public static void flipXY(Rectangle toFlip) {
    	int temp = toFlip.x;
    	toFlip.x = toFlip.y;
    	toFlip.y = temp;
    	
    	temp = toFlip.width;
    	toFlip.width = toFlip.height;
    	toFlip.height = temp;
    }
    
    /**
     * Returns the height or width of the given rectangle.
     * 
     * @param toMeasure rectangle to measure
     * @param width returns the width if true, and the height if false
     * @return the width or height of the given rectangle
     * @since 3.0
     */
    public static int getDimension(Rectangle toMeasure, boolean width) {
        if (width) {
            return toMeasure.width;
        } else {
            return toMeasure.height;
        }
    }

    /**
     * Returns the x or y coordinates of the given point.
     * 
     * @param toMeasure point being measured
     * @param width if true, returns x. Otherwise, returns y.
     * @return the x or y coordinate
     * @since 3.1
     */
    public static int getCoordinate(Point toMeasure, boolean width) {
    	return width ? toMeasure.x : toMeasure.y;
    }
    
    /**
     * Returns the x or y coordinates of the given rectangle.
     * 
     * @param toMeasure rectangle being measured
     * @param width if true, returns x. Otherwise, returns y.
     * @return the x or y coordinate
     * @since 3.1
     */
    public static int getCoordinate(Rectangle toMeasure, boolean width) {
    	return width ? toMeasure.x : toMeasure.y;
    }
    
    /**
     * Sets one dimension of the given rectangle. Modifies the given rectangle.
     * 
     * @param toSet rectangle to modify
     * @param width if true, the width is modified. If false, the height is modified.
     * @param newCoordinate new value of the width or height
     * @since 3.1
     */
    public static void setDimension(Rectangle toSet, boolean width, int newCoordinate) {
    	if (width) {
    		toSet.width = newCoordinate;
    	} else {
    		toSet.height = newCoordinate;
    	}
    }

    /**
     * Sets one coordinate of the given rectangle. Modifies the given rectangle.
     * 
     * @param toSet rectangle to modify
     * @param width if true, the x coordinate is modified. If false, the y coordinate is modified.
     * @param newCoordinate new value of the x or y coordinates
     * @since 3.1
     */
    public static void setCoordinate(Rectangle toSet, boolean width, int newCoordinate) {
    	if (width) {
    		toSet.x = newCoordinate;
    	} else {
    		toSet.y = newCoordinate;
    	}
    }
    
    /**
     * Sets one coordinate of the given point. Modifies the given point.
     * 
     * @param toSet point to modify
     * @param width if true, the x coordinate is modified. If false, the y coordinate is modified.
     * @param newCoordinate new value of the x or y coordinates
     * @since 3.1
     */
    public static void setCoordinate(Point toSet, boolean width, int newCoordinate) {
    	if (width) {
    		toSet.x = newCoordinate;
    	} else {
    		toSet.y = newCoordinate;
    	}
    }
    
    /**
     * Returns the distance of the given point from a particular side of the given rectangle.
     * Returns negative values for points outside the rectangle.
     * 
     * @param rectangle a bounding rectangle
     * @param testPoint a point to test
     * @param edgeOfInterest side of the rectangle to test against
     * @return the distance of the given point from the given edge of the rectangle
     * @since 3.0
     */
    public static int getDistanceFromEdge(Rectangle rectangle, Point testPoint,
            int edgeOfInterest) {
        switch (edgeOfInterest) {
        case SWT.TOP:
            return testPoint.y - rectangle.y;
        case SWT.BOTTOM:
            return rectangle.y + rectangle.height - testPoint.y;
        case SWT.LEFT:
            return testPoint.x - rectangle.x;
        case SWT.RIGHT:
            return rectangle.x + rectangle.width - testPoint.x;
        }

        return 0;
    }

    /**
     * Extrudes the given edge inward by the given distance. That is, if one side of the rectangle
     * was sliced off with a given thickness, this returns the rectangle that forms the slice. Note
     * that the returned rectangle will be inside the given rectangle if size > 0.
     * 
     * @param toExtrude the rectangle to extrude. The resulting rectangle will share three sides
     * with this rectangle.
     * @param size distance to extrude. A negative size will extrude outwards (that is, the resulting
     * rectangle will overlap the original iff this is positive). 
     * @param orientation the side to extrude.  One of SWT.LEFT, SWT.RIGHT, SWT.TOP, or SWT.BOTTOM. The 
     * resulting rectangle will always share this side with the original rectangle.
     * @return a rectangle formed by extruding the given side of the rectangle by the given distance.
     * @since 3.0
     */
    public static Rectangle getExtrudedEdge(Rectangle toExtrude, int size,
            int orientation) {
        Rectangle bounds = new Rectangle(toExtrude.x, toExtrude.y,
                toExtrude.width, toExtrude.height);

        if (!isHorizontal(orientation)) {
            bounds.width = size;
        } else {
            bounds.height = size;
        }

        switch (orientation) {
        case SWT.RIGHT:
            bounds.x = toExtrude.x + toExtrude.width - bounds.width;
            break;
        case SWT.BOTTOM:
            bounds.y = toExtrude.y + toExtrude.height - bounds.height;
            break;
        }

        normalize(bounds);

        return bounds;
    }

    /**
     * Returns the opposite of the given direction. That is, returns SWT.LEFT if
     * given SWT.RIGHT and visa-versa.
     * 
     * @param swtDirectionConstant one of SWT.LEFT, SWT.RIGHT, SWT.TOP, or SWT.BOTTOM
     * @return one of SWT.LEFT, SWT.RIGHT, SWT.TOP, or SWT.BOTTOM
     * @since 3.0
     */
    public static int getOppositeSide(int swtDirectionConstant) {
        switch (swtDirectionConstant) {
        case SWT.TOP:
            return SWT.BOTTOM;
        case SWT.BOTTOM:
            return SWT.TOP;
        case SWT.LEFT:
            return SWT.RIGHT;
        case SWT.RIGHT:
            return SWT.LEFT;
        }

        return swtDirectionConstant;
    }

    /**
     * Converts the given boolean into an SWT orientation constant.
     * 
     * @param horizontal if true, returns SWT.HORIZONTAL. If false, returns SWT.VERTICAL 
     * @return SWT.HORIZONTAL or SWT.VERTICAL.
     * @since 3.0
     */
    public static int getSwtHorizontalOrVerticalConstant(boolean horizontal) {
        if (horizontal) {
            return SWT.HORIZONTAL;
        } else {
            return SWT.VERTICAL;
        }
    }

    /**
     * Returns true iff the given SWT side constant corresponds to a horizontal side
     * of a rectangle. That is, returns true for the top and bottom but false for the
     * left and right.
     * 
     * @param swtSideConstant one of SWT.TOP, SWT.BOTTOM, SWT.LEFT, or SWT.RIGHT
     * @return true iff the given side is horizontal.
     * @since 3.0
     */
    public static boolean isHorizontal(int swtSideConstant) {
        return !(swtSideConstant == SWT.LEFT || swtSideConstant == SWT.RIGHT);
    }

    /**
     * Moves the given rectangle by the given delta.
     * 
     * @param rect rectangle to move (will be modified)
     * @param delta direction vector to move the rectangle by
     * @since 3.0
     */
    public static void moveRectangle(Rectangle rect, Point delta) {
        rect.x += delta.x;
        rect.y += delta.y;
    }

    /**
     * Normalizes the given rectangle. That is, any rectangle with
     * negative width or height becomes a rectangle with positive
     * width or height that extends to the upper-left of the original
     * rectangle. 
     * 
     * @param rect rectangle to modify
     * @since 3.0
     */
    public static void normalize(Rectangle rect) {
        if (rect.width < 0) {
            rect.width = -rect.width;
            rect.x -= rect.width;
        }

        if (rect.height < 0) {
            rect.height = -rect.height;
            rect.y -= rect.height;
        }
    }

    /**
     * Converts the given rectangle from display coordinates to the local coordinate system 
     * of the given object into display coordinates.
     * 
     * @param coordinateSystem local coordinate system being converted to
     * @param toConvert rectangle to convert
     * @return a rectangle in control coordinates
     * @since 3.0
     */
    public static Rectangle toControl(Control coordinateSystem,
            Rectangle toConvert) {
        Point start = coordinateSystem.toControl(toConvert.x, toConvert.y);
        return new Rectangle(start.x, start.y, toConvert.width,
                toConvert.height);
    }

    /**
     * Converts the given rectangle from the local coordinate system of the given object
     * into display coordinates.
     * 
     * @param coordinateSystem local coordinate system being converted from
     * @param toConvert rectangle to convert
     * @return a rectangle in display coordinates
     * @since 3.0
     */
    public static Rectangle toDisplay(Control coordinateSystem,
            Rectangle toConvert) {
        Point start = coordinateSystem.toDisplay(toConvert.x, toConvert.y);
        return new Rectangle(start.x, start.y, toConvert.width,
                toConvert.height);
    }

    /**
     * Determines where the given point lies with respect to the given rectangle.
     * Returns a combination of SWT.LEFT, SWT.RIGHT, SWT.TOP, and SWT.BOTTOM, combined
     * with bitwise or (for example, returns SWT.TOP | SWT.LEFT if the point is to the
     * upper-left of the rectangle). Returns 0 if the point lies within the rectangle.
     * Positions are in screen coordinates (ie: a point is to the upper-left of the
     * rectangle if its x and y coordinates are smaller than any point in the rectangle)
     *  
     * @param boundary normalized boundary rectangle 
     * @param toTest point whose relative position to the rectangle is being computed
     * @return one of SWT.LEFT | SWT.TOP, SWT.TOP, SWT.RIGHT | SWT.TOP, SWT.LEFT, 0,
     * SWT.RIGHT, SWT.LEFT | SWT.BOTTOM, SWT.BOTTOM, SWT.RIGHT | SWT.BOTTOM
     * @since 3.0
     */
    public static int getRelativePosition(Rectangle boundary, Point toTest) {
        int result = 0;

        if (toTest.x < boundary.x) {
            result |= SWT.LEFT;
        } else if (toTest.x >= boundary.x + boundary.width) {
            result |= SWT.RIGHT;
        }

        if (toTest.y < boundary.y) {
            result |= SWT.TOP;
        } else if (toTest.y >= boundary.y + boundary.height) {
            result |= SWT.BOTTOM;
        }

        return result;
    }

    /**
     * Returns the edge of the given rectangle is closest to the given
     * point.
     * 
     * @param boundary rectangle to test
     * @param toTest point to compare
     * @return one of SWT.LEFT, SWT.RIGHT, SWT.TOP, or SWT.BOTTOM
     * 
     * @since 3.0
     */
    public static int getClosestSide(Rectangle boundary, Point toTest) {
        int[] sides = new int[] { SWT.LEFT, SWT.RIGHT, SWT.TOP, SWT.BOTTOM };

        int closestSide = SWT.LEFT;
        int closestDistance = Integer.MAX_VALUE;

        for (int idx = 0; idx < sides.length; idx++) {
            int side = sides[idx];

            int distance = getDistanceFromEdge(boundary, toTest, side);

            if (distance < closestDistance) {
                closestDistance = distance;
                closestSide = side;
            }
        }

        return closestSide;
    }

    /**
     * Returns a copy of the given rectangle
     * 
     * @param toCopy rectangle to copy
     * @return a copy of the given rectangle
     * @since 3.0
     */
    public static Rectangle copy(Rectangle toCopy) {
        return new Rectangle(toCopy.x, toCopy.y, toCopy.width, toCopy.height);
    }

    /**
     * Returns the size of the rectangle, as a Point
     * 
     * @param rectangle rectangle whose size is being computed
     * @return the size of the given rectangle
     * @since 3.0
     */
    public static Point getSize(Rectangle rectangle) {
        return new Point(rectangle.width, rectangle.height);
    }

    /**
     * Sets the size of the given rectangle to the given size
     * 
     * @param rectangle rectangle to modify
     * @param newSize new size of the rectangle
     * @since 3.0
     */
    public static void setSize(Rectangle rectangle, Point newSize) {
        rectangle.width = newSize.x;
        rectangle.height = newSize.y;
    }

    /**
     * Sets the x,y position of the given rectangle. For a normalized
     * rectangle (a rectangle with positive width and height), this will
     * be the upper-left corner of the rectangle. 
     * 
     * @param rectangle rectangle to modify
     * @param newSize new size of the rectangle
     * 
     * @since 3.0
     */
    public static void setLocation(Rectangle rectangle, Point newSize) {
        rectangle.width = newSize.x;
        rectangle.height = newSize.y;
    }

    /**
     * Returns the x,y position of the given rectangle. For normalized rectangles
     * (rectangles with positive width and height), this is the upper-left
     * corner of the rectangle.
     * 
     * @param toQuery rectangle to query
     * @return a Point containing the x,y position of the rectangle
     * 
     * @since 3.0
     */
    public static Point getLocation(Rectangle toQuery) {
        return new Point(toQuery.x, toQuery.y);
    }

    /**
     * Returns a new rectangle with the given position and dimensions, expressed
     * as points.
     * 
     * @param position the (x,y) position of the rectangle
     * @param size the size of the new rectangle, where (x,y) -> (width, height)
     * @return a new Rectangle with the given position and size
     * 
     * @since 3.0
     */
    public static Rectangle createRectangle(Point position, Point size) {
        return new Rectangle(position.x, position.y, size.x, size.y);
    }
    
}