package nxm.sys.test;

import nxm.sys.lib.Data;
import nxm.sys.lib.DataFile;
import nxm.sys.lib.Primitive;
import nxm.sys.lib.Time;
import nxm.sys.lib.TimeLine;

/**
 * Add Jitter to timestamp values to test TimeLine
 * @author J. Czechowski
 * @since NeXtMidas 3.8.0 for NXM-3174 and NXM-3042
 */
public class addjitter extends Primitive {
  private DataFile inFile;     // Input File
  private DataFile outFile;    // Output File
  private Data     data;       // Output data buffer
  private double   jitter;     // Max value for jitter
  private double   delta;
  private double   tolr;
  private boolean  randomJitter;
  private long     count;

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

  @Override
  public int open() {

    inFile = MA.getDataFile("IN");
    inFile.open(DataFile.INPUT);
    delta = inFile.getDelta();
    tolr  = inFile.getTimeLineTolerance();

    outFile = MA.getDataFile("OUT", inFile, 0);
    outFile.setDefaultQualifier("TYPE", inFile.getType());
    outFile.open(DataFile.OUTPUT);

    if ((outFile.getType() % 1000 == 1)) {
      xfer = Math.max(1, (int)(bufSize/inFile.getBPE()));
    } else {
      xfer = 1; // Default to 1 for Type 2000/3000 files
    }

    xfer    = MA.getL("/TL",xfer);
    jitter  = MA.getD("JITTER", 0.0);
    randomJitter = MA.getZ("/RANDOM");

    count   = 0;
    data    = inFile.getDataBuffer(xfer);
    if ((jitter > delta) && randomJitter) {
      M.warning("Random jitter mode with max jitter ("+jitter+") greater than delta ("+delta+") may result in back-in-time timeline entries");
    }

    return NORMAL;
  }

  @Override
  public int process() {
    double jitterMultiplier = (randomJitter) ? (Math.random() * 2.0 - 1.0) : (0.01 * (count % 100));
    double dt = jitterMultiplier * jitter;
    Time   t0 = inFile.getTimeAtCurrent();
    Time   t1 = t0.addSec(dt);
    int    n  = inFile.read(data);

    count++;

    if (n == 0) return NOOP;
    if (n < -0) return FINISH;

    outFile.setTimeAt(t1,TimeLine.NotifyInvalidEntry.WARNING);
    outFile.write(data, n);
    return NORMAL;
  }

  @Override
  public int close() {
    if (inFile  != null) inFile.close();
    if (outFile != null) outFile.close();
    return NORMAL;
  }
}
