/*
 * 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.annotation.Nullable;
import ej.microui.MicroUI;
import ej.microui.MicroUIException;
import ej.microui.event.EventHandler;

/**
 * The <code>Display</code> object represents the pixelated screen in the platform.<br>
 * The display of the system may be retrieved by calling {@link #getDisplay()}.<br>
 * <br>
 * The display is able to render a <code>Displayable</code> on its implementation screen. Only one
 * <code>Displayable</code> can be set on the display at a time; it is said to be visible or to be shown. The visible
 * <code>Displayable</code> can be retrieved with the method {@link #getDisplayable()}.<br>
 * <br>
 * {@link Display#requestShow(Displayable)} allows the Displayable to be selected for rendering on the display. It can
 * be called at any time by the application, for instance in response to user inputs.<br>
 * <br>
 * <code>Display</code> uses a {@link GraphicsContext} to draw on its corresponding screen. All draw actions are
 * serialized. The application should not use the display's graphics context outside the events mechanism
 * <code>requestRender()</code> and <code>render()</code>. Nevertheless, for exceptional cases a new
 * <code>GraphicsContext</code> may be created using <code>getGraphicsContext()</code>. This
 * <code>GraphicsContext</code> bypasses the standard serialized drawing mechanism and allows drawings to be rendered on
 * the display at any time.<br>
 * <br>
 * All events on the display are serialized: requestRender, callSerially, handleEvent etc. The display uses a <code>
 * FIFOPump</code> to manage its serialized event mechanism. Some events are internally executed and some events are
 * calling some application code. <br>
 * <br>
 * When a visible object has to be painted on a <code>Display</code>, the <code>render</code> method gives a
 * <code>GraphicsContext</code> as argument and should use it to render the visible object.<br>
 * <br>
 * Direct drawing on the display can be done from application by retrieving a <code>GraphicsContext</code> with
 * {@link Display#getGraphicsContext()}. Using this mechanism does not ensure drawings will be performed before, during
 * or after the current <code>render()</code>, since it bypasses the serialization system events.<br>
 */
public class Display {

    /**
     * Returns the display's event serializer.
     *
     * @return the display's event serializer.
     * @since 2.0
     */
    public EventHandler getEventHandler() {
        throw new RuntimeException();
    }

    /**
     * Returns the height in pixels of the display screen area available to the application.
     *
     * @return height of the display screen area.
     */
    public int getHeight() {
        throw new RuntimeException();
    }

    /**
     * Returns the width in pixels of the display screen area available to the application.
     *
     * @return width of the display screen area.
     */
    public int getWidth() {
        throw new RuntimeException();
    }

    /**
     * Returns the number of bits per pixel of the display.
     *
     * @return the number of bits per pixel
     */
    public int getPixelDepth() {
        throw new RuntimeException();
    }

    /**
     * Tells whether the display offers color.
     *
     * @return if display has color
     */
    public boolean isColor() {
        throw new RuntimeException();
    }

    /**
     * Gets the number of colors that can be represented on the device.<br>
     * Note that the number of colors for a black and white display is 2.
     *
     * @return the number of colors
     */
    public int getNumberOfColors() {
        throw new RuntimeException();
    }

    /**
     * Returns if the display uses an underlying double buffer (either hardware or software). This technique is useful
     * to avoid flickering while the user is drawing.
     *
     * @return true if and only if a double buffer is used for the display
     */
    public boolean isDoubleBuffered() {
        throw new RuntimeException();
    }

    /**
     * Gets the color that will be displayed if the specified color is requested.<br>
     * For example, with a monochrome display, this method will return either 0xFFFFFF (white) or 0x000000 (black)
     * depending on the brightness of the specified color.
     *
     * @param color
     *            the desired color in 0x00RRGGBB format.
     * @return the corresponding color that will be displayed on the graphics context (in 0x00RRGGBB format).
     */
    public int getDisplayColor(int color) {
        throw new RuntimeException();
    }

    /**
     * Tells whether the display has backlight.
     *
     * @return if display has backlight
     */
    public boolean hasBacklight() {
        throw new RuntimeException();
    }

    /**
     * Sets the contrast of the display. <code>contrast</code> value range is 0-100
     *
     * @param contrast
     *            the new value of the contrast
     */
    public void setContrast(int contrast) {
        throw new RuntimeException();
    }

    /**
     * Returns the contrast of the display.
     *
     * @return the current contrast of the display (range 0-100)
     */
    public int getContrast() {
        throw new RuntimeException();
    }

    /**
     * Sets the backlight of the display. <code>backlight</code> value range is 0-100
     *
     * @param backlight
     *            the new value of the backlight
     */
    public void setBacklight(int backlight) {
        throw new RuntimeException();
    }

    /**
     * Returns the current backlight setting
     *
     * @return the current backlight setting (range 0-100)
     */
    public int getBacklight() {
        throw new RuntimeException();
    }

    /**
     * Returns the display of the system. Throws a {@link MicroUIException} when there is no display.
     *
     * @return the unique display.
     * @throws MicroUIException
     *             if MicroUI is not started or if there is no display.
     */
    public static Display getDisplay() {
        throw new RuntimeException();
    }

    /**
     * Returns the current <code>Displayable</code> object in the <code>Display</code>.<br>
     * The value returned by <code>getDisplayable()</code> may be <code>null</code> if no <code>Displayable</code> is
     * visible.
     *
     * @return the current <code>Displayable</code> object in the <code>Display</code>
     */
    @Nullable
    public Displayable getDisplayable() {
        throw new RuntimeException();
    }

    /**
     * Returns the display's <code>GraphicsContext</code>. With this <code>GraphicsContext</code>, it is possible to
     * draw on the screen at any time without following the display events serializer. The graphics context has the same
     * dimensions as the display, which allows to modify every pixel of the display.
     * <p>
     * If the normal system execution is repainting at the same time, the last unflushed draw actions will be visible
     * (the previous one will be hidden by the last one). It is not possible to determine which draw action will be done
     * last.
     * <p>
     * This method should be only used in {@link MicroUI#callSerially(Runnable)} context to synchronize the use of this
     * graphics context with all display events.
     *
     * @return the display's graphics context.
     * @see MicroUI#callSerially(Runnable)
     * @see #flush()
     */
    public GraphicsContext getGraphicsContext() {
        throw new RuntimeException();
    }

    /**
     * Asks to set the given displayable as visible on the display. The treatment is synchronized with the other
     * {@link Display} events. If the {@link Display}'s current displayable is not this displayable, the methods
     * {@link Displayable#onShown()}, then {@link Displayable#render(GraphicsContext)} and then {@link Display#flush()}
     * will be called.
     *
     * @param displayable
     *            the displayable to show
     *
     * @throws SecurityException
     *             if a security manager exists and does not allow the caller to get the display.
     */
    public void requestShow(Displayable displayable) {
        throw new RuntimeException();
    }

    /**
     * Asks to set the given displayable as hidden on the display. The treatment is synchronized with the other
     * {@link Display} events. If the {@link Display}'s current displayable is this displayable, the method
     * {@link Displayable#onHidden()} will be called.
     *
     * @param displayable
     *            the displayable to hide
     */
    public void requestHide(Displayable displayable) {
        throw new RuntimeException();
    }

    /**
     * Checks whether the given displayable is visible on the display.
     *
     * @param displayable
     *            the displayable to check
     *
     * @return <code>true</code> if the displayable is currently visible, <code>false</code> otherwise
     */
    public boolean isShown(Displayable displayable) {
        throw new RuntimeException();
    }

    /**
     * Asks to render the <i>current</i> displayable. The treatment is synchronized with the other {@link Display}
     * events. The methods {@link Displayable#render(GraphicsContext)} and then {@link Display#flush()} will be called
     * when the event is executed.
     * <p>
     * The <i>current</i> displayable is the displayable which is shown when the event is executed and not the
     * displayable which is currently shown (see {@link #getDisplayable()} which returns the current displayable). This
     * displayable will be different than the displayable currently shown if the method
     * {@link Display#requestShow(Displayable)} is called with another displayable.
     * <p>
     * By consequence, this method <b>has not</b> the same behavior than {@link Displayable#requestRender()}: this other
     * method requests the rendering on the displayable itself (if and only if this displayable is the current
     * displayable), and the method {@link Displayable#render(GraphicsContext)} is called if only if the displayable is
     * the current displayable when the event is executed.
     */
    public void requestRender() {
        throw new RuntimeException();
    }

    /**
     * Requests a flush updating the display with the draw actions since the last flush if and only if the display is
     * double buffered. The treatment is synchronized with the other {@link Display} events. If there is already this
     * event in {@link Display}'s events queue, the new event is not added.
     */
    public void requestFlush() {
        throw new RuntimeException();
    }

    /**
     * Performs immediately a flush updating the display with the draw actions since the last flush if and only if the
     * display is double buffered. The treatment is not synchronized with the other {@link Display} events; for this
     * reason, this method should be used in {@link MicroUI#callSerially(Runnable)} context.
     */
    public void flush() {
        throw new RuntimeException();
    }

    /**
     * Blocks the current thread (with all its locks) until previous call {@link #flush()} has been processed.
     * <p>
     * The following code does not block the caller (assuming there is no pending flush before calling first line):
     *
     * <pre>
     * display.requestFlush();
     * display.waitFlushCompleted();
     * </pre>
     *
     * because the call to <code>display.requestFlush();</code> only adds the request in the event serializer: no
     * <code>flush</code> is running so there is nothing to wait.
     * <p>
     * On the other hand, the following code blocks the current thread until the call to {@link #flush()} has been
     * processed:
     *
     * <pre>
     * display.flush();
     * display.waitFlushCompleted();
     * </pre>
     *
     * @throws MicroUIException
     *             if the current thread is the <code>Display</code>'s events thread.
     */
    public void waitFlushCompleted() {
        throw new RuntimeException();
    }

    /**
     * Prepares a call event which will be serialized in the system event stream when the next executed flush will be
     * done. This flush can already be launched or serialized (will be executed in few time) or not programmed yet.
     * <p>
     * When the event is processed, the <code>run()</code> method of the <code>Runnable</code> object is called.<br>
     * The call to the <code>run()</code> method of the <code>Runnable</code> object is performed asynchronously.
     * Therefore <code>callOnFlushCompleted()</code> will never block waiting for the <code>run()</code> method to
     * finish.
     * <p>
     * Only one event can be serialized at any time. When a new event is added while the previous one has not been
     * executed, the new one replaces the old one. The <code>Runnable</code> object of the old event will not be
     * notified about the end of next flush.
     * <p>
     * The event can be cleared by calling {@link #cancelCallOnFlushCompleted()}. In this case,The <code>Runnable</code>
     * object of the event will not be notified about the end of next flush.
     * <p>
     * The <code>run()</code> method should return quickly, as with other callback methods.
     *
     * @param run
     *            a <code>Runnable</code> object to call
     */
    public void callOnFlushCompleted(Runnable run) {
        throw new RuntimeException();
    }

    /**
     * Cancels the event previously registered by the call to {@link #callOnFlushCompleted(Runnable)}. The
     * <code>Runnable</code> object of the old event will not be notified about the end of next flush.
     */
    public void cancelCallOnFlushCompleted() {
        throw new RuntimeException();
    }
}
