package nxm.sys.libg;

import java.awt.Color;
import java.awt.Graphics;

import nxm.sys.inc.MessageHandler;
import nxm.sys.inc.ProvisionalUseOnly;
import nxm.sys.lib.Shell;

/** A class to display a graphical line across (or partly across) the control panel.
    This line is intended to be used as a means to separate controls on the control panel without using
    a GLabel.
    @author jwb
    @since NeXtMidas 2.9.1
 */
public class GLine extends GWidget {

  /** Start the line at the left edge of the panel */
  public static final int LEFT   = 1;
  /** Start the line at the right edge of the panel */
  public static final int RIGHT  = 2;
  /** Center the line in the panel */
  public static final int CENTER = 3;

  /** The default color of the line.  Defaults to {@link Theme#cfg}*/
  public static final Color DEF_COLOR = Theme.global().cfg;   // Theme foreground color
  private Color color = DEF_COLOR;

  /** The default thickness of the line. Defaults to {@link GWidget#DEFBW} */
  public static final int DEF_THICKNESS = GWidget.DEFBW;
  private int thickness = DEF_THICKNESS;    // thickness in pixels of the line to draw

  private int percent = 100; // how much of the control panel to draw across?

  /** The Default Line position */
  public  static final int DEF_LINE_POS = CENTER;
  private int              linePos      = DEF_LINE_POS;

  /**
    Empty constructor.
   */
  public GLine () {}

  /** Create a new GLine
      @param parent  The parent (should be null since these are not pop-ups)
      @param name    The name
      @param color   The color of the Line
      @param thickness The thickness of the line. Must be greater than 0
      @param percent The percent of the width of the control the line should cover. Must be between 0 and 100
      @param linePos  Where the line is positioned on the control panel ({@link #LEFT}, {@link #RIGHT}, or {@link #CENTER})
      @param flags  The GWidget flags
      @param mh     The message handler
   */
  public GLine (Object parent, String name, Color color, int thickness, int percent, int linePos, int flags, MessageHandler mh) {
    super("GLine",parent,name,flags,mh);
    if (thickness > 0) this.thickness = thickness;
    if (percent >= 0 && percent <= 100)  this.percent = percent;
    this.color = color;
    if (linePos==LEFT || linePos==RIGHT || linePos==CENTER) this.linePos = linePos;
    open();
    addTo(parent);
  }

  @Override
  public void open () {
    super.open();
    setSize();
  }

  private void setSize () {
    panel.setSize(pw, thickness+bw+bw+SB_BORDER+SB_BORDER); // add in border width for top and bottom
  }

  @Override
  public void setup () {
    // this method overrides GWidget setup() since GLine sets its own size... - added in 3.1.2 (Bug 2604)
    if (status==INIT) status=FRONT;
    setSize();
    if (is(INLINE)) bw=0; else bw=DEFBW;
    if (is(TITLE)) { titleh = th+ta; bw=DEFBW; } else titleh=0;
    if (pw>0 && thickness>0) {   // do not set sizes to 0, or else it will never leave INIT state and draw
      pos.w = pw;
      pos.h = thickness+bw+bw+SB_BORDER+SB_BORDER;
    }
    layout();
  }

 /**
  *  @deprecated Since NeXtMidas 3.9.0 to avoid graphical timing issues
  *  use {@link #paintComponent(Graphics)}
  */
  @Deprecated
  public void paint () {
    refresh();
  }

  @ProvisionalUseOnly("Treat this as protected and should only be called by subclass paintComponent methods")
  @Override
  public void paintComponent (Graphics g) {
    super.paintComponent(g);
    int x1;

    shadowbox(g,0,0,pw,ph,SB_FLAT); // Updated to use g in 3.9.0 for NXM-3213
    g.setClip(SB_BORDER+SB_BORDER, SB_BORDER, pw-(4*SB_BORDER), panel.getHeight()-(2*SB_BORDER));
    g.setColor(color);

    int panelWidth  = panel.getWidth();
    int lineWidth   = (int)(panelWidth * (percent/100.0));
    int panelCenter =      (panelWidth/2);

    switch (linePos) {
      case CENTER: x1 = panelCenter - (lineWidth/2);   break;
      case RIGHT:  x1 = panelWidth - lineWidth;        break;
      default:     x1 = 0;                             break;
    }

    g.fillRect(x1, 0, lineWidth, thickness);

//System.out.println("GLine paint: x1="+x1+" %="+percent+"  lineWidth="+lineWidth+" panW="+panelWidth+" centerPos="+panelCenter);
  }

  /** Set the color of the line. This method takes in a String and converts the String to a Color
      via {@link MColor#getColor(Object)}.
      @param color The color in String form
   */
  public void setColor (String color) {
    setColor(MColor.getColor(color));
  }

  /** Set the color of the line.
      @param color The color
   */
  @Override
  @SuppressWarnings("deprecation")
  public void setColor (Color color) {
    if (color.getRGB() != this.color.getRGB()) {
      this.color = color;
      panel.repaint();
    }
  }

  /** Get the color of the line
   *  @return the color of the line   */
  public Color getColor () {
    return color;
  }

  /** Get the color of the line as a String
   *  @return the color of the line as a String. */
  public String getColorString () {
    return MColor.toString(color);
  }

  /** Set the thickness of the line in pixels. Must be greater than zero
   *  @param pix the thickness in pixels
   */
  public void setThickness (int pix) {
    if (pix != thickness && pix > 0) {
      thickness = pix;
      setSize();
      panel.repaint();
    }
  }

  /** Get the thickness of the line
   *  @return the thickness of the line, in pixels */
  public int getThickness () {
    return thickness;
  }

  /** Set the position on the panel where the line is drawn.
      @param pos The position. Must be 'LEFT', 'RIGHT', or 'CENTER'.
   */
  public void setLinePos (String pos) {
    pos = pos.toUpperCase();
    int iPos = -1; // invalid value to start

    // convert to int form
    switch (pos) {
      case "LEFT":   iPos = LEFT;   break;
      case "RIGHT":  iPos = RIGHT;  break;
      case "CENTER": iPos = CENTER; break;
      default:
        Shell.warning("Invalid Line Position given: '"+pos+"'. Position must be 'LEFT', 'RIGHT', or 'CENTER'.");
        break;
    }

    // only update if different
    if (iPos > 0 && iPos != linePos) {
      linePos = iPos;
      panel.repaint();
    }
  }

  /** Get the position on the panel where the line is drawn
      @return the position ('Left', 'RIGHT', or 'CENTER')
   */
  public String getLinePos () {
    switch (linePos) {
      case LEFT:  return "LEFT";
      case RIGHT: return "RIGHT";
      default:    return "CENTER";
    }
  }

  /** Set the percentage of the panel width that the line covers
      @param val An int val between 0 (no line) and 100 (covers the entire width of the panel)
   */
  public void setPercent (int val) {
    if (percent != val) {
      percent = val;
      panel.repaint();
    }
  }

  /** Get the percentage of the panel width covered by the line
      @return The percentage as an int between 0 (no line) and 100 (covers the entire width of the panel)
   */
  public int getPercent () {
    return percent;
  }

  /** Gets the int value of the the given Start Position String.
      @param pos Must be LEFT, RIGHT, or CENTER.
      @return The position in int form. Will return {@link #DEF_LINE_POS} if given an invalid value.
   */
  public static int getLinePosValue (String pos) {
    switch (pos.toUpperCase()) {
      case "LEFT":  return GLine.LEFT;
      case "RIGHT": return GLine.RIGHT;
      default:      return GLine.DEF_LINE_POS;
    }
  }

  @Override
  protected int processEventMessage (String name, int info, Object data) {
    if (button==3 && !is(PERM)) { // right mouse button (close if NOT permanent)
      close();
      return 1;
    }
    return -1;
  }
}
