package GlobalNavigation;

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

import Carmen.*;

import LocalNavigation.GUIMessage;

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

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

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

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

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

  /**
   * <p>Whether to fill the rect.</p>
   **/
  public int filled;
  
  private static final String CARMEN_GUI_RECT_NAME = "carmen_gui_rect";
  private static final String CARMEN_GUI_RECT_FMT =
    "{double, double, double, double, int, int, int, int, double, string};";
  private static final int IPC_QUEUE_LENGTH = 10;

  /**
   * <p>Create a new GUIRectMessage.</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 rectangle's llc x coordinate in world frame (m)
   * @param y the rectangle's llc y coordinate in world frame (m)
   * @param width the rectangle's width in world frame (m)
   * @param height the rectangle's height in world frame (m)
   * @param filled whether to fill the rect
   **/
  public GUIRectMessage(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 #GUIRectMessage(int, int, int, double, double, double,
   * double, boolean)}.</p>
   **/
  public GUIRectMessage(int r, int g, int b, Rectangle2D.Double rect,
                        boolean filled) {
    this(r, g, b, rect.x, rect.y, rect.width, rect.height, filled);
  }

  /**
   * <p>Covers {@link #GUIRectMessage(int, int, int, double, double,
   * double, double, boolean)}.</p>
   *
   * @param color the color, or null to use current
   **/
  public GUIRectMessage(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 #GUIRectMessage(Color, double, double, double,
   * double, boolean)}.</p>
   **/
  public GUIRectMessage(Color color, Rectangle2D.Double r, boolean filled) {
    this(color, r.x, r.y, r.width, r.height, filled);
  }

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

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