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

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

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