package nxm.sys.prim;

import java.awt.Color;

import nxm.sys.lib.Data;
import nxm.sys.lib.DataFile;
import nxm.sys.lib.Primitive;
import nxm.sys.libg.MColor;

/** Primitive to convert a Midas Type 2000 file containing data values to one that contains
    ARGB colors with specified transparency to be rendered on a graphics display.
    Output file will be Midas Type 2000 with SF data (32 bit integer).
    This primitive is currently not configured and only used to convert input data file
    for testing the plotting onto {@link nxm.sys.libg.Layer2D}.

    @author Neon Ngo
    @since NeXtMidas 2.5.0
*/
public class convertargb extends Primitive {

  private DataFile hin,hout;   // input and output data files
  private Data data;           // input Data buffer from input DataFile
  private int alpha;           // alpha value for color [0-255], 0=transparent, 255=opaque
  private String colormapType; // see MColor.colorMapList for valid values
  private int numColors;       // number of colors
  private Color[] colormap;    // colormap
  private float scale0;        // minimum data value for determining color to map to from input
  private float scale1;        // scale factor for determining color to map to from input
  private int frameSize;       // input DataFile's frame size

  /** default constructor */
  public convertargb () {}

  /** Initialize input parameters */
  public int open () {
    hin = MA.getDataFile ("IN");
    hin.open();
    frameSize = hin.getFrameSize();

    hout = MA.getDataFile ("OUT",hin,0);
    hout.setFormat("SL"); // output file will contain 32 bit integer color values (SL)
    hout.open();

    alpha        = MA.getL("ALPHA", 127);
    colormapType = MA.getS("COLORMAP", "RAMP");
    numColors    = MA.getL("NUMCOLORS", -1); // -1 will default to 32 from MColor.getColorMap(..)
    colormap     = MColor.getColorMap(colormapType, numColors, alpha);
    if (colormap.length -1 != numColors) numColors = colormap.length - 1;

    float min = MA.getF("MIN", 0);
    float max = MA.getF("MAX", 1);
    scale0    = min;
    scale1    = numColors/(max-min);

    xfer = Math.max(1, (int)Math.min(hin.getSize(), (bufSize/hin.dbpe)));
    xfer = MA.getL("/TL",xfer);
    data = hin.getDataBuffer(xfer);

    if (verbose) M.info(toString());
    return NORMAL;
  }

  /** Process transfer length of data */
  public int process () {
    int n = hin.read(data);
    if (n>0) {
      float fbuf[] = data.castF(true);
      int[] buf    = fa2color(null, fbuf, frameSize*n, scale0, scale1, colormap);
      Data dataout = new Data(buf);
      hout.write(dataout,n);
      data.uncast(fbuf, false);
    }
    else if (n==0) { return NOOP;   }
    else           { return FINISH; }
    return NORMAL;
  }

  /** Convert a float array to an int array of colors, using specified colormap
      @param buf      Output int array to store color ARGB values.
      @param fbuf     Input float data array to convert to colors.
      @param min      Minimum value in fbuf data array.
      @param scale    Scale factor for determining color to map to from fbuf.
                      This should normally be (colormap.length-1)/(max-min).
      @param colormap Colormap to map float data to colors.
      @return int array of ARGB color values
      @throws NullPointerException if fbuf or colormap are null
      @deprecated Since NeXtMidas 3.1.2, use {@link #fa2color(int[], float[], int, float, float, Color[])}
   */
  @Deprecated
  public static int[] fa2color (int[] buf, float fbuf[], float min, float scale, Color[] colormap) {
    return fa2color(buf, fbuf, fbuf.length, min, scale, colormap);
  }

  /** Convert a float array to an int array of colors, using specified colormap
      @param buf      Output int array to store color ARGB values.
      @param fbuf     Input float data array to convert to colors.
      @param size     number of items to process from fbuf
      @param min      Minimum value in fbuf data array.
      @param scale    Scale factor for determining color to map to from fbuf.
                     This should normally be (colormap.length-1)/(max-min).
      @param colormap Colormap to map float data to colors.
      @return int array of ARGB color values
      @throws NullPointerException if fbuf or colormap are null
      @since NeXtMidas 3.1.2
   */
  public static int[] fa2color (int[] buf, float fbuf[], int size, float min, float scale, Color[] colormap) {
    int numColors = colormap.length - 1;
    if (buf == null || buf.length < fbuf.length) { buf = new int[fbuf.length]; }

    for (int i=0, len=fbuf.length; i<len && i<size; i++) {
      int colorIndex = (int) ((fbuf[i] - min) * scale);
      if      (  colorIndex < 0)         { colorIndex = 0;         }
      else if (++colorIndex > numColors) { colorIndex = numColors; }
      buf[i] = colormap[colorIndex].getRGB();
    }
    return buf;
  }

  /** Finalization of primitive */
  public int close () {
    hin.close();
    hout.close();
    return NORMAL;
  }

  /** return current settings as a String */
  public String toString () {
    StringBuilder sb = new StringBuilder(super.toString());
    sb.append(" - scale0=").append(scale0);
    sb.append(" scale1=").append(scale1);
    sb.append(" xfer=").append(xfer);
    sb.append(" numColors=").append(numColors);
    sb.append(" colormap.length=").append(colormap.length);
    sb.append(" colormap=").append(colormap);
    return sb.toString();
  }
}
