package nxm.sys.libg;

import java.awt.Color;

import nxm.sys.inc.MessageHandler;
import nxm.sys.lib.Message;
import nxm.sys.lib.Parser;

/**
  A class to define a 2D Surface rendering.
  This class must attach to a Line class.

  @author Jeff Schoen
*/
public class Surface extends Object
    implements MessageHandler {

  /** Comma-delimited list of valid Surface types. */
  public static final String typeList = "Fill,Mesh,Dot,Contour";

  /** Surface type constant */
  public static final int FILL = 0x01;

  /** Surface type constant */
  public static final int MESH = 0x02;

  /** Surface type constant */
  public static final int DOTS = 0x04;

  /** Surface type constant */
  public static final int CONT=0x08;

  /** the surface type (one of {@link Surface#FILL }, {@link Surface#MESH },
     {@link Surface#DOTS }, or {@link Surface#CONT })
   */
  public int type = FILL;

  /** the number of colors in the color map for this Surface */
  public int ncolors;

  /** the color map */
  public int cmap;

  /** the array of colors in the color map for this Surface */
  public Color[] colors;

  /** the layer of the Line object to which this surface is attached */
  public Layer layer;

  /** the MPlot of the Line object to which this surface is attached */
  public MPlot MP;

  /** Construct a new Surface object */
  public Surface () {
    super();
  }

  /** Set the Surface type
      @param value the new Surface type
   */
  public void setType (int value) { type = value; refresh(); }

  /** Set the Surface type
      @param value the name of the new value
   */
  public void setType (String value) {
    setType( Parser.mask(typeList,value,type) );
  }

  /** Issue configuration menus. */
  public void configure () {
    new GMenu (MP,"Surface.cfg",typeList
  +",ColorMap>,Colors>", type, GMenu.TOGGLE, this);
  }

  /**
     {@inheritDoc} Process a message from parent process or config menu.
     @param msg {@inheritDoc}
     @return {@inheritDoc}
   */
  public int processMessage (Message msg) {
    if (msg.name.equals("SURFACE.CFG")) {
      String text = (String)msg.data;
      if (text.equals("COLORMAP>")) {
        new GMenu (MP,"Colormap",MColor.colorMapList, cmap, 0, this);
      }
      else if (text.equals("COLORS>")) {
        new GPrompt (MP,"Colors","", 0, this);
      }
      else setType(msg.info);
    }
    else if (msg.name.equals("COLORMAP")) setColorMap (msg.info);
    else if (msg.name.equals("COLORS")) setColors ((String)msg.data);
    else if (msg.name.equals("TYPE")) setType ((String)msg.data);
    else return 0;
    return 1;
  }

  /** Set the color map for this Surface
      @param value the color map type
   */
  public void setColors (String value) {
    if (value.length()==0) return;
    colors = MColor.getColorMap(value,-1);
    ncolors = colors.length-1;
    refresh();
  }

  /** Set the color map for this Surface
      @param value the color map number in {@link MColor#colorMapList}
   */
  public void setColorMap (int value) { setColorMap(value,-1); }

  /** Set the color map for this Surface
      @param value the color map number in {@link MColor#colorMapList}
      @param ncolors the number of colors
   */
  public void setColorMap (int value, int ncolors) {
    if (value==-1) value = cmap;
    if (value<1 || value>MColor.MAXTYPE) return;
    if (value==cmap && ncolors==this.ncolors) return;
    cmap = value;
    colors = MColor.getColorMap(value,ncolors);
    this.ncolors = colors.length-1;
    refresh();
  }

  /** Refresh the display of this Surface */
  public void refresh() { layer.refresh(); }
}
