/*
 * 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;

    /**
     * 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();
    }

    /**
     * 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();
    }
}
