package Challenge;

import java.awt.Color;
import java.awt.geom.*;

import Carmen.*;

import LocalNavigation.GUIMessage;

/**
 * <p>Message used to send an ellipse to the GUI</p>
 * 
 * <p>Examples:
 * <pre>
 *    (new GUIEllipseMessage(0.5, 0.5, 1.0, 2.0, false).publish(); //use curent color
 *    (new GUIEllipseMessage(Color.BLUE, e, true)).publish(); // e is a Ellipse2D.Double
 * </pre></p>
 *
 * @author vona
 **/
public class GUIEllipseMessage extends GUIMessage {

  /**
   * <p>The ellipse's llc x coordinate in world frame (m).</p>
   **/
  public double x;

  /**
   * <p>The ellipse's llc y coordinate in world frame (m).</p>
   **/
  public double y;

  /**
   * <p>The ellipse's width in world frame (m).</p>
   **/
  public double width;

  /**
   * <p>The ellipse's height in world frame (m).</p>
   **/
  public double height;

  /**
   * <p>Whether to fill the ellipse.</p>
   **/
  public int filled;
  
  private static final String CARMEN_GUI_ELLIPSE_NAME = "carmen_gui_ellipse";
  private static final String CARMEN_GUI_ELLIPSE_FMT =
    "{double, double, double, double, int, int, int, int, double, string};";
  private static final int IPC_QUEUE_LENGTH = 10;

  /**
   * <p>Create a new GUIEllipseMessage.</p>
   *
   * <p>{@link #timestamp} and {@link #host} are set to the current time and
   * host, respectively.</p>
   *
   * @param r the red color component, negative to use current color
   * @param g the green color component, negative to use current color
   * @param b the blue color component, negative to use current color
   * @param x the ellipse's llc x coordinate in world frame (m)
   * @param y the ellipse's llc y coordinate in world frame (m)
   * @param width the ellipse's width in world frame (m)
   * @param height the ellipse's height in world frame (m)
   * @param filled whether to fill the ellipse
   **/
  public GUIEllipseMessage(int r, int g, int b,
                           double x, double y, double width, double height,
                           boolean filled) {
    super(r, g, b);
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.filled = (filled) ? 1 : 0;
  }
 
  /**
   * <p>Covers {@link #GUIEllipseMessage(int, int, int, double, double, double,
   * double, boolean)}.</p>
   **/
  public GUIEllipseMessage(int r, int g, int b, Ellipse2D.Double ellipse,
                           boolean filled) {
    this(r, g, b, ellipse.x, ellipse.y, ellipse.width, ellipse.height, filled);
  }

  /**
   * <p>Covers {@link #GUIEllipseMessage(int, int, int, double, double,
   * double, double, boolean)}.</p>
   *
   * @param color the color, or null to use current
   **/
  public GUIEllipseMessage(Color color,
                           double x, double y, double width, double height,
                           boolean filled) {
    this((color != null) ? color.getRed() : -1,
         (color != null) ? color.getGreen() : -1,
         (color != null) ? color.getBlue() : -1,
         x, y, width, height, filled);
  }

  /**
   * <p>Covers {@link #GUIEllipseMessage(Color, double, double, double,
   * double, boolean)}.</p>
   **/
  public GUIEllipseMessage(Color color, Ellipse2D.Double e, boolean filled) {
    this(color, e.x, e.y, e.width, e.height, filled);
  }

  /**
   * <p>Convenience cover of {@link #GUIEllipseMessage(int, int, int,
   * double, double, double, double, boolean)}, always uses current color.</p>
   **/
  public GUIEllipseMessage(double x, double y, double width, double height,
                           boolean filled) {
    this(-1, -1, -1, x, y, width, height, filled);
  }
 
  /**
   * <p>Covers {@link #GUIEllipseMessage(double, double, double, double,
   * boolean)}.</p>
   **/
  public GUIEllipseMessage(Ellipse2D.Double e, boolean filled) {
    this(e.x, e.y, e.width, e.height, filled);
  }

  /**
   * <p>Create a new GUIEllipseMessage.</p>
   *
   */
  public GUIEllipseMessage() {
    timestamp = Util.getTime();
    host = Util.getHostName();    
  }
  
  /**
   * <p>Check whether this ellipse is filled.</p>
   *
   * @return true iff this ellipse is filled
   **/
  public boolean isFilled() {
    return (filled != 0);
  }
  
  /**
   * <p>Subscribe a class to GUIEllipseMessages.</p>
   * 
   * @param handler a GUIEllipseHandler
   */
  public static void subscribe(GUIEllipseHandler handler) {
    subscribe(CARMEN_GUI_ELLIPSE_NAME, CARMEN_GUI_ELLIPSE_FMT, handler, 
              GUIEllipseMessage.class, "handle");
    IPC.IPC.setMsgQueueLength(CARMEN_GUI_ELLIPSE_NAME, IPC_QUEUE_LENGTH);
  }
  
  /**
   * <p>Publish GUIEllipseMessage to subscribers</p>
   */
  public void publish() {
    publish(CARMEN_GUI_ELLIPSE_NAME, CARMEN_GUI_ELLIPSE_FMT, this);
  }
}
