package nxm.sys.inc;

import nxm.sys.lib.Position;

/** Definitions for the methods implemented by all Drawable objects. Since the NeXtMidas 3.5.x
 *  series, this interface is used as the common interface implemented by all objects that can
 *  be added to nxm.sys.libg LayerDrawable. This "change" in NeXtMidas 3.5.x was merely
 *  a design decision that recognized the place of {@link Drawable} as the common ancestor of
 *  both nxm.sys.libg Feature} and nxm.sys.libg Layer. <br>
 *  <br>
 *  Summary of draw methods:
 *  <pre>
 *              | Clear Plot First | Re-plot Axis |      Plot Data       |
 *    ----------+------------------+--------------+----------------------+
 *    DONE      |                  |              |                      |
 *    ----------+------------------+--------------+----------------------+
 *    FULL      |        X         |      X       | All Data             |
 *    ----------+------------------+--------------+----------------------+
 *    DATA      |        X         |              | All Data             |
 *    ----------+------------------+--------------+----------------------+
 *    DATAX     |                  |              | Additional Data Only |
 *    ----------+------------------+--------------+----------------------+
 *    FAST      |        X         |      X       | "Draft" Quality Plot |
 *    ----------+------------------+--------------+----------------------+
 *  </pre>
 *  @author Jeff Schoen / J. Czechowski IV
 */
public interface Drawable extends DrawableModSwap {

  /** The drawing mode indicating that nothing needs to be drawn.
      @see Drawable
   */
  int DONE=-1;

  /** The drawing mode indicating that everything should be drawn including axis.
      @see Drawable
   */
  int FULL=0;

  /** The drawing mode indicating that data objects should be drawn from scratch.
      @see Drawable
   */
  int DATA=1;

  /** The drawing mode indicating that additional data should be drawn. This
      implies that there is more data available to plot and that it should
      be plotted on top of any data that has already been plotted.
      @see Drawable
   */
  int DATAX=2;

  /** The drawing mode indicating that a "fast drawn" should be done. This is
      provided such that complex plotting algorithms can skip data (e.g. plot
      every tenth point) to give a "draft" quality view of the data that would
      be suitable for circumstances where plot quality is less important than
      computational speed (e.g. showing a plot while dragging a window).
      @see Drawable
   */
  int FAST=3;

  /** Draw the object.
      @param flag The draw mode to use. This should be one of:
                  {@link #DONE}, {@link #FULL}, {@link #DATA}, {@link #DATAX}, or {@link #FAST}.
   */
  void draw (int flag);

  /** Refreshes the drawable object. <br>
      <br>
      Different implementations may interpret this differently. Some may
      immediately refresh while others may do a partial refresh or just
      mark them selves as needing a refresh in the future.
      @since NeXtMidas 1.9.5
   */
  void refresh ();

  /** Resets the drawable object. This is only applicable to a nxm.sys.libg Layer (see
      nxm.sys.libg Layer.reset() for details) for all others this is a noop method that
      returns false.
      @return true if a reset was done, false otherwise.
   */
  boolean reset ();

  /** Indicates if the drawable needs to be refreshed.
      @return true if the drawable needs to be refreshed, false if it does not.
      @since NeXtMidas 2.5.4
   */
  boolean getNeedRefresh ();

  /** Called by nxm.sys.libg MPlot to clear the refresh flag(s) without actually drawing
      the drawable. This should clear all of the flags checked in {@link #getNeedRefresh()}. This
      method is also called at the top of nxm.sys.libg Layer.draw(int).
      @since NeXtMidas 2.5.4
   */
  void clearNeedRefresh ();

  /** Gets the name of this drawable object. <br>
      <br>
      Implementations that have no name should be implemented as:
      <pre>
        public String getName() {
          return toString();
        }
      </pre>
      @return The name of the object.
      @since NeXtMidas 1.9.5
   */
  String getName ();

  /** Sets the enable flags for the layer. Outside of the Layers and nxm.sys.libg MPlot the
      {@link #setEnable(String)} method should be used in place of this one.
      @param value The flags to enable (see nxm.sys.libg MPlot#enableList).
   */
  void setEnable (int value);

  /** Sets the enable flags for the layer.
      @param arg The flags to enable (see nxm.sys.libg MPlot.enableList).
   */
  void setEnable (String arg);

  /** Gets the enable flags for the layer. Outside of the Layers and nxm.sys.libg MPlot the
      {@link #getEnableString()} method should be used in place of this one.
      @return The flags that are enabled.
   */
  int getEnable ();

  /** Gets the enable flags for the layer.
      @return The flags that are enabled.
   */
  String getEnableString ();

  /** Indicates if the drawable is enabled and/or set in backing-store --
      <b>note that this does not check to see if a flag from {@link #getEnable()}
      is set as may be implied by the name</b>. The following "truth table"
      applies to the checks against the nxm.sys.libg MPlot.EN_GLOBAL and
      nxm.sys.libg MPlot.EN_BSTORE flags done by this method.
      <pre>
        flag | EN_GLOBAL | EN_BSTORE | isEnabled(flag)
        -----+-----------+-----------+----------------
         +1  |   false   |   false   |    false
             |   false   |   true    |    false
             |   true    |   false   |    true
             |   true    |   true    |    false
        -----+-----------+-----------+----------------
          0  |   false   |   false   |    false
             |   false   |   true    |    false
             |   true    |   false   |    true
             |   true    |   true    |    true
        -----+-----------+-----------+----------------
         -1  |   false   |   false   |    false
             |   false   |   true    |    false
             |   true    |   false   |    false
             |   true    |   true    |    true
        -----+-----------+-----------+----------------
        Note: Although other values for flag may be passed in, their behavior
              is considered "undocumented" and may change in the future.
      </pre>
      Prior to NeXtMidas 3.3.0 this was not marked {@link InternalUseOnly} and
      was documented to imply that any flag from nxm.sys.libg MPlot.enableList
      could be passed in with a behavior that effectively checked to see that the
      given flag and nxm.sys.libg MPlot.EN_GLOBAL were set. Since the
      functionality never matched this, the NeXtMidas 3.3.0 release began marking
      this as {@link InternalUseOnly}. Users who implement {@link Drawable} by
      extending link nxm.sys.libg Layer or link nxm.sys.libg Feature should
      simply treat the version of {@link #isEnabled(int)} in the parent class as
      if it was declared <code>final</code> and not override it. <br>
      <br>
      Users looking to check to see if a flag is set within the layer should
      use the {@link #getEnable()} method.
      @param flag One of the following:
                  <pre>
                    +1 (check EN_GLOBAL &amp; !EN_BSTORE)
                     0 (check EN_GLOBAL),
                    -1 (check EN_GLOBAL &amp; EN_BSTORE)
                  </pre>
      @return true or false (as shown in the "truth table" above)
      @since NeXtMidas 2.5.4
      @see #setEnable(int)
      @see #getEnable()
   */
  @InternalUseOnly("Since NeXtMidas 3.3.0, see method docs for details.")
  boolean isEnabled (int flag);


  /** Finds the bounds of the drawable object. The bounds can then be accessed by the
   *  various <code>get_Min()</code> and <code>get_Max()</code> methods. If the bounds do not
   *  require initialization, calling this method will have no affect (e.g. for
   *   nxm.sys.libg Feature). If the bounds require initialization but are not
   *  known, calling this method will set the minimum values to 0.0 and the maximum
   *  values to 1.0 (e.g. in the default method in nxm.sys.libg Layer).
   *  @since NeXtMidas 3.5.4
   */
  @InternalUseOnly
  void findRange ();

  /** Gets the minimum X-axis value that bounds the drawable object.
   *  @return The value in RWC.
   *  @see #findRange()
   *  @since NeXtMidas 3.5.4
   */
  @InternalUseOnly
  double getXMin ();

  /** Gets the maximum X-axis value that bounds the drawable object.
   *  @return The value in RWC.
   *  @see #findRange()
   *  @since NeXtMidas 3.5.4
   */
  @InternalUseOnly
  double getXMax ();

  /** Gets the minimum Y-axis value that bounds the drawable object.
   *  @return The value in RWC.
   *  @see #findRange()
   *  @since NeXtMidas 3.5.4
   */
  @InternalUseOnly
  double getYMin ();

  /** Gets the maximum Y-axis value that bounds the drawable object.
   *  @return The value in RWC.
   *  @see #findRange()
   *  @since NeXtMidas 3.5.4
   */
  @InternalUseOnly
  double getYMax ();

  /** Gets the minimum Z-axis value that bounds the drawable object.
   *  @return The value in RWC.
   *  @see #findRange()
   *  @since NeXtMidas 3.5.4
   */
  @InternalUseOnly
  double getZMin ();

  /** Gets the maximum Z-axis value that bounds the drawable object.
   *  @return The value in RWC.
   *  @see #findRange()
   *  @since NeXtMidas 3.5.4
   */
  @InternalUseOnly
  double getZMax ();

  /** Is the drawable present at the specified position? This is used by methods such as
   *  nxm.sys.libg LayerDrawable.getDrawablesAt(nxm.sys.lib.Position} to determine
   *  if the drawable is roughly present at a given position.
   *  <br>
   *  The 'dpx' and 'dpy' parameters specify a <u>suggested</u> "fudge factor" to use:
   *  <pre>
   *     N = N-pixel fudge-factor
   *     0 = No fudge factor, strict position match (not good for small features)
   *    -1 = Use default N-pixel fudge-factor
   *    -2 = Don't consider this axis.
   *  </pre>
   *  The fudge-factor is converted from pixels (in the current plot) to RWC and then checked
   *  against the size of the drawable. If the drawable is larger (e.g. a big box) this does a
   *  strict inclusion check as if no fudge-factor was used. If the drawable is smaller (e.g.
   *  a very small symbol), the fudge-factor is treated as the size of the drawable. The goal
   *  of the fudge-factor is to make it easier for users to select (with a mouse) a drawable
   *  that is close, but not exactly under the mouse pointer. <b>Implementations are free to
   *  ignore the fudge-factor and treat all requests as if the fudge-factor was disabled (i.e.
   *  set to 0).</b><br>
   *  <br>
   *  In the case of a bounded drawable, the drawable is free to decide if any position within
   *  the bounds is valid or if only a position that coincides with a drawn feature is considered.
   *  It is also legal that the bounds are selected to make computation easy, such as bounding
   *  a feature (which could be a circle) with a box and then seeing if the given position is
   *  within that bounding box.
   *  @param pos The given position (not null).
   *  @param dpx The delta in pixels along the x-axis.
   *  @param dpy The delta in pixels along the y-axis.
   *  @return true this feature is at the position, false otherwise.
   *  @since NeXtMidas 3.5.4
   */
  @InternalUseOnly
  @ProvisionalUseOnly("Added in NeXtMidas 3.5.4")
  boolean isAtPosition (Position pos, int dpx, int dpy);
}
