/*
 * Copyright 2015-2021 MicroEJ Corp. All rights reserved.
 * This library is provided in source code for use, modification and test, subject to license terms.
 * Any modification of the source code will break MicroEJ Corp. warranties on the whole library.
 */
package ej.mwt.util;

/**
 * Represents a rectangle with a position and a size.
 * <p>
 * For heap optimization the position and size are stored as a <code>short</code> and therefore are limited between
 * <code>-32768</code> and <code>32767</code>.
 */
public class Rectangle implements Outlineable {

	private short x;
	private short y;
	private short width;
	private short height;

	/**
	 * Creates a rectangle specifying its bounds.
	 *
	 * @param x
	 *            the x.
	 * @param y
	 *            the y.
	 * @param width
	 *            the width.
	 * @param height
	 *            the height.
	 *
	 */
	public Rectangle(int x, int y, int width, int height) {
		this.x = (short) x;
		this.y = (short) y;
		this.width = (short) width;
		this.height = (short) height;
	}

	/**
	 * Creates a rectangle from the bounds of another rectangle.
	 *
	 * @param rectangle
	 *            the other rectangle.
	 */
	public Rectangle(Rectangle rectangle) {
		this.x = rectangle.x;
		this.y = rectangle.y;
		this.width = rectangle.width;
		this.height = rectangle.height;
	}

	/**
	 * Gets the x coordinate.
	 *
	 * @return the x.
	 */
	public int getX() {
		return this.x;
	}

	/**
	 * Sets the x coordinate.
	 *
	 * @param x
	 *            the x.
	 */
	public void setX(int x) {
		this.x = (short) x;
	}

	/**
	 * Gets the y coordinate.
	 *
	 * @return the y.
	 */
	public int getY() {
		return this.y;
	}

	/**
	 * Sets the y coordinate.
	 *
	 * @param y
	 *            the y.
	 */
	public void setY(int y) {
		this.y = (short) y;
	}

	/**
	 * Gets the width.
	 *
	 * @return the width.
	 */
	public int getWidth() {
		return this.width;
	}

	/**
	 * Sets the width.
	 *
	 * @param width
	 *            the width.
	 */
	public void setWidth(int width) {
		this.width = (short) width;
	}

	/**
	 * Gets the height.
	 *
	 * @return the height.
	 */
	public int getHeight() {
		return this.height;
	}

	/**
	 * Sets the height.
	 *
	 * @param height
	 *            the height.
	 */
	public void setHeight(int height) {
		this.height = (short) height;
	}

	/**
	 * Sets the position of this rectangle.
	 *
	 * @param x
	 *            the x.
	 * @param y
	 *            the y.
	 */
	public void setPosition(int x, int y) {
		this.x = (short) x;
		this.y = (short) y;
	}

	/**
	 * Sets the size of this rectangle.
	 *
	 * @param width
	 *            the width.
	 * @param height
	 *            the height.
	 */
	public void setSize(int width, int height) {
		this.width = (short) width;
		this.height = (short) height;
	}

	/**
	 * Sets the bounds of this rectangle.
	 *
	 * @param x
	 *            the x.
	 * @param y
	 *            the y.
	 * @param width
	 *            the width.
	 * @param height
	 *            the height.
	 */
	public void setBounds(int x, int y, int width, int height) {
		this.x = (short) x;
		this.y = (short) y;
		this.width = (short) width;
		this.height = (short) height;
	}

	@Override
	public void addOutline(int left, int top, int right, int bottom) {
		this.x -= left;
		this.y -= top;
		this.width += left + right;
		this.height += top + bottom;
		assert (this.width > 0 && this.height > 0);
	}

	@Override
	public void removeOutline(int left, int top, int right, int bottom) {
		this.x += left;
		this.y += top;
		this.width -= left + right;
		this.height -= top + bottom;
	}
}
