/*
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * "The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations under
 * the License.
 *
 * The Original Code is ICEpdf 3.0 open source software code, released
 * May 1st, 2009. The Initial Developer of the Original Code is ICEsoft
 * Technologies Canada, Corp. Portions created by ICEsoft are Copyright (C)
 * 2004-2009 ICEsoft Technologies Canada, Corp. All Rights Reserved.
 *
 * Contributor(s): _____________________.
 *
 * Alternatively, the contents of this file may be used under the terms of
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"
 * License), in which case the provisions of the LGPL License are
 * applicable instead of those above. If you wish to allow use of your
 * version of this file only under the terms of the LGPL License and not to
 * allow others to use your version of this file under the MPL, indicate
 * your decision by deleting the provisions above and replace them with
 * the notice and other provisions required by the LGPL License. If you do
 * not delete the provisions above, a recipient may use your version of
 * this file under either the MPL or the LGPL License."
 *
 */
package com.softwareimaging.jpdf.core.pobjects;

import java.util.Vector;

import android.graphics.PointF;

import com.softwareimaging.android.graphics.RectangleF;

/**
 * <p>
 * A rectangle in a PDF document is slightly different than the
 * <code>Rectangle</code> class in Java. A PDF rectangle is written as an array
 * of four numbers giving the coordinates of a pair of diagonally opposite
 * corners. Typically, the array takes the form:
 * </p>
 * <p/>
 * <ul>
 * [II<sub>x</sub> II<sub>y</sub> UR<sub>x</sub> UR<sub>y</sub>]
 * </ul>
 * <p/>
 * <p>
 * This specifies the lower-left x, lower-left y, upper-right x, and upper-right
 * y coordinates of the rectangle, in that order. However, this format is not
 * guaranteed and this class normalizes such rectangles.
 * </p>
 * <p/>
 * <p>
 * Another very important difference between PRectangles Rectangles is that
 * PRectangles use the Cartesian Coordinate system, where Rectangles use the
 * Java2D coordinates system. As a result, the user of this class must know the
 * context in which the PRectangle is being used. For example there is a
 * significant difference between the inherited method createIntersection and
 * PRectangles createCartesianIntersection.
 * </p>
 * 
 * @since 2.0
 */
public class PRectangle extends RectangleF {

	private float p1x;
	private float p1y;
	private float p2x;
	private float p2y;

	/**
	 * <p>
	 * Creates a new PRectangle object. The points are automatically normalized
	 * by the constructor. These two coordinates represent the diagonal corners
	 * of the rectangle.
	 * 
	 * @param p1
	 *            first point of diagonal, in the Cartesian coordinate space
	 * @param p2
	 *            second point of diagonal, in the Cartesian coordinate space
	 */
	public PRectangle(PointF p1, PointF p2) {
		super();
		normalizeCoordinates(p1.x, p1.y, p2.x, p2.y);
		// assign original data
		p1x = p1.x;
		p1y = p1.y;
		p2x = p2.x;
		p2y = p2.y;
	}

	/**
	 * <p>
	 * Creates a new PRectangle object assumed to be in the Cartesian coordinate
	 * space.
	 * </p>
	 * 
	 * @param x
	 *            the specified x coordinate
	 * @param y
	 *            the specified y coordinate
	 * @param width
	 *            the width of the Rectangle
	 * @param height
	 *            the height of the Rectangle
	 */
	private PRectangle(float x, float y, float width, float height) {
		super(x, y, width, height);
	}

	/**
	 * Creates a new PRectangle object. The points are automatically normalized
	 * by the constructor.
	 * 
	 * @param coordinates
	 *            a vector containing four elements where the first and second
	 *            elements represent the x and y coordinates of one point and
	 *            the third and fourth elements represent the x and y
	 *            cooordinates of the second point. These two coordinates
	 *            represent the diagonal corners of the rectangle.
	 * @throws IllegalArgumentException
	 *             thrown if coordinates is null or does not have four elements
	 */
	public PRectangle(Vector coordinates) throws IllegalArgumentException {
		if (coordinates == null || coordinates.size() < 4)
			throw new IllegalArgumentException();
		float x1 = ((Number) coordinates.elementAt(0)).floatValue();
		float y1 = ((Number) coordinates.elementAt(1)).floatValue();

		float x2 = ((Number) coordinates.elementAt(2)).floatValue();
		float y2 = ((Number) coordinates.elementAt(3)).floatValue();

		// assign original data
		p1x = x1;
		p1y = y1;
		p2x = x2;
		p2y = y2;

		// System.out.println(x1 + " : " + y1 + " : " + x2 + " : " + y2 );
		normalizeCoordinates(x1, y1, x2, y2);
	}

	/**
	 * Returns a new PRectangle object representing the intersection of this
	 * PRectangle with the specified PRectangle using the Cartesian coordinate
	 * system. If a Java2D coordinate system is used, then the rectangle should
	 * be first converted to that space {@see #toJava2dCoordinates() }.
	 * 
	 * @param src2
	 *            the Rectangle2D to be intersected with this Rectangle2D.
	 * @return object representing the intersection of the two PRectangles.
	 */
	public PRectangle createCartesianIntersection(PRectangle src2) {
		PRectangle rec = new PRectangle(src2.x, src2.y, src2.width(), src2.height());
		float xLeft = (x > rec.x) ? x : rec.x;
		float xRight = ((x + width()) > (rec.x + rec.width())) ? (rec.x + rec.width())
				: (x + width());

		float yBottom = ((y - height()) < (rec.y - rec.height()) ? (rec.y - rec.height())
				: (y - height()));
		float yTop = (y > rec.y) ? rec.y : y;

		rec.setRect(xLeft, yTop, xRight - xLeft, yTop - yBottom);

		// If rectangles don't intersect, return zeroed intersection.
		if (rec.width() < 0 || rec.height() < 0) {
			rec.setEmpty();
		}
		return rec;
	}

	/**
	 * <p>
	 * Gets the orgional two points that created the PRectangle object. The
	 * first point is represented by the the rectangle positions x, y and the
	 * second poitn is represented by the width and height of the rectangle.
	 * 
	 * @return rectangle representing the PRectangle object initial two point.
	 */
	public RectangleF getOriginalPoints() {
		return new RectangleF(p1x, p1y, p2x, p2y);
	}

	/**
	 * <p>
	 * Converts the Cartesian representation of the Rectangle into Rectangle in
	 * the Java2D coordinate space.
	 * </p>
	 * 
	 * @return rectangle in the Java2D coordinate space.
	 */
	public RectangleF toJava2dCoordinates() {
		return new RectangleF(x, y - height(), width(), height());
	}

	/**
	 * Normalizes the given coordinates so that the rectangle is created with
	 * the proper dimensions.
	 * 
	 * @param x1
	 *            x value of coordinate 1
	 * @param y1
	 *            y value of coordinate 1
	 * @param x2
	 *            x value of coordinate 2
	 * @param y2
	 *            y value of coordinate 2
	 */
	private void normalizeCoordinates(float x1, float y1, float x2, float y2) {
		float x = x1, y = y1, w = Math.abs(x2 - x1), h = Math.abs(y2 - y1);
		// get smallest x
		if (x1 > x2) {
			x = x2;
		}
		// get largest y
		if (y1 < y2) {
			y = y2;
		}
		setRect(x, y, w, h);
	}

	/**
	 * Converts the Cartesian representation of the Rectangle into Rectangle in
	 * the JPrintEngine coordinate space.
	 * 
	 * @return rectangle in the JPrintEngine coordinate space.
	 */
	public com.softwareimaging.geometry.RectangleF toJPECoordinates() {
		float xOffset;
		float width;
		float yOffset;
		float height;

		// get smallest x
		if (p1x > p2x) {
			xOffset = p2x;
			width = p1x - p2x;
		} else {
			xOffset = p1x;
			width = p2x - p1x;
		}

		// get largest y
		if (p1y < p2y) {
			yOffset = p2y;
			height = p2y - p1y;
		} else {
			yOffset = p1y;
			height = p1y - p2y;
		}
		yOffset = -yOffset; // swap y direction

		return new com.softwareimaging.geometry.RectangleF(xOffset, yOffset, width, height);
	}
}
