package nxm.sys.test;

import java.util.List;

import nxm.sys.inc.ProvisionalUseOnly;
import nxm.sys.lib.Data;
import nxm.sys.lib.DataFile;
import nxm.sys.lib.MidasException;
import nxm.sys.lib.Parser;
import nxm.sys.lib.Primitive;
import nxm.sys.lib.Table;
import nxm.sys.lib.Time;

/** Convert a Table with appropriate keys/value pairs to a 1000 or 2000 file
 *  @author Jeanette McCall
 *  @since  NeXtMidas 3.9.1
 */
@ProvisionalUseOnly("This was created to create educational and test data and has not been fully tested")
public class table2blue10002000 extends Primitive {
    private int throttle;
    private double  delta, tstart;
    private String form;
    private DataFile hcb;
    private Data data;
    private List<Double> tabData;

    /** The throttle mode {@value}.
        FULL - the primitive runs as fast as it can.
        REALTIME - the data is produced at the defined sample rate.
        BLOCK - no data is produced. */
    public  static final String throttleList = "RealTime,Full,Block";
    private static final int REALTIME=1,FULL=2,BLOCK=3;

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

    @Override
    public int open () {

      Table configTable = MA.getTable("IN");
      String type = configTable.getS("TYPE","1000");
      String format = configTable.getS("FORMAT","SD");
      String xUnits = configTable.getS("XUNITS","NONE");
      double xStart = configTable.getD("XSTART",0);
      double xDelta = configTable.getD("XDELTA",1);
      tabData   = configTable.getList("DATA", null);

      // Open output file
      hcb = MA.getDataFile("OUT",type,format,0);
      hcb.setXStart(xStart);
      hcb.setXDelta(xDelta);
      hcb.setXUnits(xUnits);

      if (hcb.getType() == 2000) {
        int    frameSz = configTable.getL("FRAMESIZE",1);
        String yUnits = configTable.getS("YUNITS","NONE");
        double yStart = configTable.getD("YSTART",0);
        double yDelta = configTable.getD("YDELTA",1);
        hcb.setFrameSize(frameSz);
        hcb.setYUnits(yUnits);
        hcb.setYStart(yStart);
        hcb.setYDelta(yDelta);
      }

      double size = 0;
      switch (hcb.getType()) {
        case 1000: size = tabData.size()/hcb.getSPA(); break;
        case 2000: size = tabData.size()/(hcb.getSPA()*hcb.getFrameSize()); break;
        default: throw new MidasException("Type "+hcb.getType()+" is not supported");
      }
      hcb.setSize(size);
      hcb.open(DataFile.OUTPUT);

      // Setup throttling mode
      throttle = MA.getState("/RT")? REALTIME : FULL;
      throttle = MA.getChoice("/THROTTLE",throttleList,throttle); // Override any /RT input
      if (throttle==REALTIME) hcb.setTimeAt(Time.current());

      // Setup processing
      xfer  = MA.getL("/TL",4096);
      data  = hcb.getDataBuffer(xfer,DOUBLE);
      todo(size);

      return NORMAL;
    }

    @Override
    public int process () {
      // handle data throttling
      if (throttle>0) {
        if (throttle==REALTIME) {
          if (tstart==0) tstart = Time.current()-hcb.seek()*delta;
          if (Time.current() < tstart+hcb.seek()*delta) return NOOP;
        }
        else tstart=0;
        if (throttle==BLOCK) return NOOP;
      }

      int ndo = todo();
      if (ndo==0) return FINISH;


      int i = 0;

      double[] dbuf = data.castD(false);  // get array
      for (double value : tabData) {
        dbuf[i++] = value;
      }
      data.uncast(dbuf,true);


      hcb.write(data,ndo);

      return NORMAL;
    }

    @Override
    public int close () {
      hcb.close();
      return NORMAL;
    }

    @Override
    public int restart () {
      hcb.close();
      hcb = MA.getDataFile("OUT",hcb,0);
      hcb.setFormat (form);
      hcb.setSize (todo);
      hcb.open();
      data = hcb.getDataBuffer(xfer,FLOAT);
      tstart = 0;
      return NORMAL;
    }

    @Override
    public int processReady () {
      if (state!=PROCESS) return 0;
      return hcb.processReady(xfer);
    }

    // set run-time properties
    /** Set the throttling mode
     *  @param value the new throttling mode
     */
    public void setThrottle (String value) { throttle = Parser.find(throttleList,value,throttle,0,Parser.E_WARNING); }
    /** Set the data format
     *  @param format the new data format
     */
    public void setFormat (String format) { if (form.equals(format)) return; form = format; setState(RESTART); }

    // get run-time properties
    /** Get the throttling mode
     *  @return the current throttling mode
     */
    public String getThrottle () { return Parser.get(throttleList,throttle); }
    /** Get the data format
     *  @return the current data format
     */
    public String getFormat () { return MA.getS("FORM"); }


}