/*
 * Java
 *
 * Copyright 2010-2024 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.
 * This document has been released and published by E-S-R consortium, a non-profit entity.
 * To learn more about E-S-R consortium, please visit http://www.e-s-r.net/.
 * The matter contained in this document is not subject to copyright; you are free to use it for any purpose, for more information see E-S-R consortium policies.
 */
package ej.microui.display;

import ej.microui.MicroUIException;

/**
 * A <code>GraphicsContext</code> provides access to a modifiable pixel buffer.
 * <p>
 * For example, a graphics context can be used to read or write the pixels of the {@link Display} or of a
 * {@link BufferedImage}.
 * <p>
 * Painting classes such as {@link Painter} provide utility methods to draw specific shapes and objects using a graphics
 * context.
 * <p>
 * Colors are interpreted as 24-bit RGB colors. If the display or image associated with the graphics context does not
 * support such color depth, its implementation is in charge of mapping the desired colors to the most appropriate
 * supported colors.
 * <p>
 * A graphics context defines a translation vector in order to change the position of subsequent drawings.
 * <p>
 * It also defines a clipping rectangle which restricts the pixels that will be modified by subsequent drawings. Empty
 * clipping areas are supported, in which case no pixel will be modified when a drawing operation is performed. The
 * position of this clipping area is relative to the origin of this graphics context, regardless of the value of the
 * translation vector.
 * <p>
 * A graphics context uses the following coordinate system:
 * <ul>
 * <li>its origin is the top-left corner of the top-left pixel of the destination.</li>
 * <li>its x axis is positive towards the right.</li>
 * <li>its y axis is positive towards the bottom.</li>
 * </ul>
 */
public class GraphicsContext {

	/**
	 * Maximum opacity.
	 * <p>
	 * The opacity level (called <code>alpha</code>) is used by some {@link Painter} drawing methods to specify the
	 * drawing global opacity. When the opacity is maximal, the drawing is fully opaque. When opacity is a value between
	 * {@link #TRANSPARENT} and {@link #OPAQUE}, the drawing is merging the foreground color with the destination pixel
	 * color or with the global background color. When the opacity is {@link GraphicsContext#TRANSPARENT}, the drawing
	 * is fully transparent (nothing is drawn).
	 * <p>
	 * The opacity is an unsigned byte value between 0 (fully transparent) and 255 (fully opaque). All other values are
	 * meaningless.
	 * <p>
	 * The method {@link #getAlpha(int)} allows to convert an opacity expressed in percentage (0% means fully
	 * transparent and 100% fully opaque) in an opacity understandable by the {@link Painter} drawing methods.
	 *
	 * @see #getAlpha(int)
	 * @see Painter#drawImage(GraphicsContext, Image, int, int, int)
	 * @since 2.0
	 */
	public static final int OPAQUE = 0xFF;

	/**
	 * Minimum opacity.
	 * <p>
	 * See {@link #OPAQUE} comment.
	 *
	 * @since 2.0
	 */
	public static final int TRANSPARENT = 0x00;

	/**
	 * Value used when no incident occurred.
	 */
	public static final int DRAWING_SUCCESS = 0;

	/**
	 * Flag stating that an error occurred during a drawing.
	 *
	 * This flag will cause an exception to be thrown when checking the flags in the application. No exception will be
	 * thrown if this flag is not set, although other flags will keep their state and be readable in the application.
	 * This flag is to be combined with other flags describing the error.
	 */
	public static final int DRAWING_LOG_ERROR = 1 << 31;

	/**
	 * Flag stating that a drawing function is lacking an implementation.
	 *
	 * This flag is typically set when the format of the graphics context is not supported by the implementation.
	 */
	public static final int DRAWING_LOG_NOT_IMPLEMENTED = 1 << 0;

	/**
	 * Flag stating that a function was called in a context that does not allow that operation.
	 *
	 * This flag is typically set when a drawing function has been disabled for a specific format, like a vector drawing
	 * function called on a raster-only graphics context.
	 */
	public static final int DRAWING_LOG_FORBIDDEN = 1 << 1;

	/**
	 * Flag stating that the system ran out of memory while attempting to perform a drawing.
	 */
	public static final int DRAWING_LOG_OUT_OF_MEMORY = 1 << 2;

	/**
	 * Flag stating that the clip area of a graphics context was modified by the low-level side.
	 *
	 * This flag merely warns the user that the clip values returned by {@link #getClipX()}, {@link #getClipY()},
	 * {@link #getClipWidth()} and {@link #getClipHeight()}` may not be identical to the clip values used in the
	 * low-level side, notably if the modified low-level values were not properly restored. It is meant to be used as a
	 * debugging hint if a drawing seems incorrect.
	 */
	public static final int DRAWING_LOG_CLIP_MODIFIED = 1 << 3;

	/**
	 * Flag stating that an undefined character was drawn.
	 *
	 * This happens when drawing a string that contains a character that is not included in the font used.
	 */
	public static final int DRAWING_LOG_MISSING_CHARACTER = 1 << 4;

	/**
	 * Flag describing incidents occurring in a drawing library.
	 *
	 * Refer to the MicroUI implementation in the VEE port for more information about this incident.
	 */
	public static final int DRAWING_LOG_LIBRARY_INCIDENT = 1 << 29;

	/**
	 * Flag describing incidents that do not match other values.
	 */
	public static final int DRAWING_LOG_UNKNOWN_INCIDENT = 1 << 30;

	/**
	 * Forbidden constructor: call {@link Display#getGraphicsContext()} or {@link BufferedImage#getGraphicsContext()} to
	 * get an instance of {@link GraphicsContext}.
	 */
	private GraphicsContext() {
		throw new RuntimeException();
	}

	/**
	 * Returns the alpha level for the given opacity percentage.
	 * <p>
	 * The returned value may be used in some painting methods such as
	 * {@link Painter#drawImage(GraphicsContext, Image, int, int, int)}.
	 *
	 * @param opacityPercent
	 *            the opacity, in percents.
	 * @return the alpha level.
	 * @since 2.0
	 */
	public static int getAlpha(int opacityPercent) {
		throw new RuntimeException();
	}

	/**
	 * Returns the width of this graphics context.
	 *
	 * @return the width of this graphics context, in pixels.
	 */
	public int getWidth() {
		throw new RuntimeException();
	}

	/**
	 * Returns the height of this graphics context.
	 *
	 * @return the height of this graphics context, in pixels.
	 */
	public int getHeight() {
		throw new RuntimeException();
	}

	/**
	 * Resets this graphics context to its initial configuration.
	 * <p>
	 * This methods
	 * <ul>
	 * <li>resets both the translation and the clip to their initial state,</li>
	 * <li>sets the color to {@link Colors#BLACK},</li>
	 * <li>removes the background color,</li>
	 * <li>resets the ellipsis.</li>
	 * </ul>
	 */
	public void reset() {
		throw new RuntimeException();
	}

	/**
	 * Resets the translation vector of this graphics context to the <code>(0,0)</code> vector.
	 */
	public void resetTranslation() {
		throw new RuntimeException();
	}

	/**
	 * Sets the translation vector of this graphics context to the <code>(x,y)</code> vector.
	 *
	 * @param x
	 *            the x coordinate of the translation vector, in pixels.
	 * @param y
	 *            the y coordinate of the translation vector, in pixels.
	 */
	public void setTranslation(int x, int y) {
		throw new RuntimeException();
	}

	/**
	 * Adds a given translation vector to the translation vector of this graphics context.
	 * <p>
	 * The new translation vector is equal to the sum of the given translation vector and the current translation
	 * vector.
	 *
	 * @param x
	 *            the x coordinate of the translation vector to add, in pixels.
	 * @param y
	 *            the y coordinate of the translation vector to add, in pixels.
	 */
	public void translate(int x, int y) {
		throw new RuntimeException();
	}

	/**
	 * Returns the x coordinate of the translation vector of this graphics context.
	 *
	 * @return the x coordinate of the translation vector of this graphics context, in pixels.
	 */
	public int getTranslationX() {
		throw new RuntimeException();
	}

	/**
	 * Returns the y coordinate of the translation vector of this graphics context.
	 *
	 * @return the y coordinate of the translation vector of this graphics context, in pixels.
	 */
	public int getTranslationY() {
		throw new RuntimeException();
	}

	/**
	 * Sets the color of this graphics context.
	 * <p>
	 * The given color value is interpreted as a 24-bit RGB color, where the high-order byte is ignored and the
	 * remaining bytes contain the red, green and blue channels, respectively.
	 *
	 * @param color
	 *            the color to set.
	 */
	public void setColor(int color) {
		throw new RuntimeException();
	}

	/**
	 * Sets the background color of this graphics context.
	 * <p>
	 * The given color value is interpreted as a 24-bit RGB color, where the high-order byte is ignored and the
	 * remaining bytes contain the red, green and blue channels, respectively.
	 * <p>
	 * The background color is only used by some drawing methods. If the background color is not set, these algorithms
	 * have to read the destination pixel color and blend it with the desired color.
	 * <p>
	 * The background color is irrelevant for black and white displays.
	 *
	 * @param color
	 *            the color to set.
	 */
	public void setBackgroundColor(int color) {
		throw new RuntimeException();
	}

	/**
	 * Removes the background color of this graphics context.
	 */
	public void removeBackgroundColor() {
		throw new RuntimeException();
	}

	/**
	 * Returns the color of this graphics context.
	 * <p>
	 * The returned color value is interpreted as a 24-bit RGB color, where the high-order byte is ignored and the
	 * remaining bytes contain the red, green and blue channels, respectively.
	 *
	 * @return the color of this graphics context.
	 */
	public int getColor() {
		throw new RuntimeException();
	}

	/**
	 * Returns the background color of this graphics context.
	 * <p>
	 * The returned color value is interpreted as a 24-bit RGB color, where the high-order byte is ignored and the
	 * remaining bytes contain the red, green and blue channels, respectively.
	 *
	 * @return the background color of this graphics context.
	 */
	public int getBackgroundColor() {
		throw new RuntimeException();
	}

	/**
	 * Returns whether this graphics context has a background color.
	 *
	 * @return <code>true</code> if a background color has been set, <code>false</code> otherwise.
	 */
	public boolean hasBackgroundColor() {
		throw new RuntimeException();
	}

	/**
	 * Combines the given clipping rectangle with the clipping area of this graphics context.
	 * <p>
	 * This method sets the clipping area to be the intersection of the given rectangle with the current clipping area.
	 * <p>
	 * Empty clipping areas are supported, in which case no pixel will be modified when a drawing operation is
	 * performed.
	 * <p>
	 * Given clip origin is translated according current graphics context translation.
	 *
	 * @param x
	 *            the x coordinate of the rectangle, in pixels.
	 * @param y
	 *            the y coordinate of the rectangle, in pixels.
	 * @param width
	 *            the width of the rectangle, in pixels.
	 * @param height
	 *            the height of the rectangle, in pixels.
	 */
	public void intersectClip(int x, int y, int width, int height) {
		throw new RuntimeException();
	}

	/**
	 * Sets the clipping area of this graphics context to the given rectangle.
	 * <p>
	 * Empty clipping areas are supported, in which case no pixel will be modified when a drawing operation is
	 * performed.
	 * <p>
	 * Given clip origin is translated according current graphics context translation.
	 *
	 * @param x
	 *            the x coordinate of the rectangle, in pixels.
	 * @param y
	 *            the y coordinate of the rectangle, in pixels.
	 * @param width
	 *            the width of the rectangle, in pixels.
	 * @param height
	 *            the height of the rectangle, in pixels.
	 */
	public void setClip(int x, int y, int width, int height) {
		throw new RuntimeException();
	}

	/**
	 * Resets the clipping area of this graphics context to its entire bounds.
	 * <p>
	 * The current graphics context translation is not taken into account.
	 * <p>
	 * This is equivalent to calling
	 * <code>gc.setClip(-gc.getTranslationX(), -gc.getTranslationY(), gc.getWidth(), gc.getHeight())</code>.
	 */
	public void resetClip() {
		throw new RuntimeException();
	}

	/**
	 * Returns the x coordinate of the clipping area of this graphics context.
	 * <p>
	 * Returned clip origin is translated according current graphics context translation.
	 *
	 * @return the x coordinate of the clipping area of this graphics context, in pixels.
	 */
	public int getClipX() {
		throw new RuntimeException();
	}

	/**
	 * Returns the y coordinate of the clipping area of this graphics context.
	 * <p>
	 * Returned clip origin is translated according current graphics context translation.
	 *
	 * @return the y coordinate of the clipping area of this graphics context, in pixels.
	 */
	public int getClipY() {
		throw new RuntimeException();
	}

	/**
	 * Returns the width of the clipping area of this graphics context.
	 *
	 * @return the width of the clipping area of this graphics context, in pixels.
	 */
	public int getClipWidth() {
		throw new RuntimeException();
	}

	/**
	 * Returns the height of the clipping area of this graphics context.
	 *
	 * @return the height of the clipping area of this graphics context, in pixels.
	 */
	public int getClipHeight() {
		throw new RuntimeException();
	}

	/**
	 * Notifies that the current clip will be considered as a completely repainted region by subsequent drawings.
	 *
	 * A clip is already considered as a fully repainted region before each drawing. This method allows a larger region
	 * to be notified even if the first drawing in this region uses a smaller clip.
	 *
	 * This may avoid unnecessary restoration of the contents of this region (in whole or in part).
	 *
	 * This call has no effect when the graphics context does not target the display.
	 */
	public void notifyDrawingRegion() {
		throw new RuntimeException();
	}

	/**
	 * Enables ellipsis when drawing characters.
	 * <p>
	 * When ellipsis is enabled, characters are truncated if their rendering width is higher than the specified width
	 * limit. In this case, the last visible character is replaced by the ellipsis character (three dots).
	 * <p>
	 * To configure ellipsis using the clipping area as text limit, the given width should be equal to
	 * <code>getClipX() + getClipWidth() - x</code>, where <code>x</code> is the x coordinate of the drawing.
	 * <p>
	 * The ellipsis is only used by the methods drawing characters.
	 *
	 * @param width
	 *            the width limit, in pixels.
	 * @throws IllegalArgumentException
	 *             if <code>width</code> is negative or zero.
	 */
	public void enableEllipsis(int width) {
		throw new RuntimeException();
	}

	/**
	 * Returns the width limit before applying the ellipsis.
	 * <p>
	 * If ellipsis is disabled, this method returns zero.
	 *
	 * @return the width limit, in pixels.
	 */
	public int getEllipsisWidth() {
		throw new RuntimeException();
	}

	/**
	 * Disables ellipsis.
	 */
	public void disableEllipsis() {
		throw new RuntimeException();
	}

	/**
	 * Returns the color of a pixel of this graphics context.
	 * <p>
	 * For more information on the format of the color value returned by this method, refer to the first paragraphs of
	 * the {@link GraphicsContext#readPixels centralized pixel reading documentation}.
	 * <p>
	 * Given position is translated according to the current graphics context translation.
	 *
	 * @param x
	 *            the x coordinate of the pixel.
	 * @param y
	 *            the y coordinate of the pixel.
	 * @return the color of the pixel, in ARGB format.
	 * @throws IllegalArgumentException
	 *             if the given pixel coordinates are out of the bounds of this graphics context.
	 * @throws MicroUIException
	 *             if this graphics context is associated with a resource which has been closed.
	 */
	public int readPixel(int x, int y) {
		throw new RuntimeException();
	}

	/**
	 * Retrieves the color of the pixels of a region of this graphics context.
	 * <p>
	 * Each pixel color is stored in 32-bit ARGB format, where the high-order byte contains the alpha channel and the
	 * remaining bytes contain the red, green and blue channels, respectively. This is relevant regardless of the format
	 * in which the pixels are stored internally. The alpha channel specifies the opacity of the pixel, ranging between
	 * {@link GraphicsContext#TRANSPARENT} and {@link GraphicsContext#OPAQUE}.
	 * <p>
	 * The retrieved colors are not guaranteed to be identical to the colors from the original source. Indeed, color
	 * values may be resampled to reflect the display capabilities of the device. For example, red, green and blue
	 * pixels may all be represented by the same color value on a grayscale device.
	 * <p>
	 * On displays which do not support alpha blending, the alpha component will be equal to
	 * {@link GraphicsContext#OPAQUE} for opaque pixels and {@link GraphicsContext#TRANSPARENT} for every other pixel.
	 * On displays that support alpha blending, alpha channel values may be resampled to reflect the number of levels of
	 * opacity supported by the display.
	 * <p>
	 * The data is stored in the given <code>int</code> array, which should be big enough to hold the color of all the
	 * pixels of the region.
	 * <p>
	 * The scan length specifies the relative offset within the array between two pixels of consecutive rows. In order
	 * to prevent rows of stored pixels from overlapping, the absolute value of the scan length should be greater than
	 * or equal to the width of the region. Negative values of scan length are allowed if the order of rows is inverted
	 * in the array.
	 * <p>
	 * If an exception occurs during this method, the contents of the given array will remain unchanged.
	 * <p>
	 * Given position is translated according to the current graphics context translation.
	 *
	 * @param array
	 *            the array in which the pixel data should be stored.
	 * @param offset
	 *            the index of the array at which the first pixel color should be stored.
	 * @param scanLength
	 *            the relative offset in the array between two corresponding pixels in consecutive rows.
	 * @param x
	 *            the x-coordinate of the top-left pixel of the region.
	 * @param y
	 *            the y-coordinate of the top-left pixel of the region.
	 * @param width
	 *            the width of the region.
	 * @param height
	 *            the height of the region.
	 * @throws ArrayIndexOutOfBoundsException
	 *             if the array is not big enough to hold the color of all the pixels of the region.
	 * @throws IllegalArgumentException
	 *             if a part of the region is out of the bounds of this graphics context.
	 * @throws IllegalArgumentException
	 *             if the absolute value of <code>scanLength</code> is lower than <code>width</code>.
	 * @throws MicroUIException
	 *             if this graphics context is associated with a resource which has been closed.
	 */
	public void readPixels(int[] array, int offset, int scanLength, int x, int y, int width, int height) {
		throw new RuntimeException();
	}

	/**
	 * Returns the SNI context data of this graphics context.
	 * <p>
	 * The SNI context can be used to call a native method with SNI. This allows to identify and to use a graphics
	 * context in the native world in order to perform drawings on the graphics context or to use it as a source.
	 * <p>
	 * The data format is implementation specific.
	 *
	 * @return the SNI context of this graphics context.
	 * @throws MicroUIException
	 *             if this graphics context is associated with a resource which has been closed.
	 */
	public byte[] getSNIContext() {
		throw new RuntimeException();
	}

	/**
	 * Gets and clears the drawing log flags from a graphics context.
	 *
	 * The flags are reset to their success value after retrieving their value.
	 *
	 * This method is identical to {@link #checkDrawingLogFlags()}, except it does not throw an exception if the error
	 * flag has been set. Both methods are meant to help investigate drawing errors.
	 *
	 * @return the drawing log flags
	 */
	public int getAndClearDrawingLogFlags() {
		throw new RuntimeException();
	}

	/**
	 * Throws an exception if the error flag is currently set.
	 *
	 * The drawing log flags are reset to their success value after retrieving their value.
	 *
	 * This method is identical to {@link #getAndClearDrawingLogFlags()}, except it throws an exception if the error
	 * flag has been set. Both methods are meant to help investigate drawing errors.
	 *
	 * @see GraphicsContext#DRAWING_LOG_ERROR Error flag
	 *
	 * @return the drawing log flags
	 * @throws MicroUIException
	 *             if the error flag was set
	 */
	public int checkDrawingLogFlags() {
		throw new RuntimeException();
	}

}
