package nxm.sys.test;

import nxm.sys.inc.Units;
import nxm.sys.lib.BaseFile;
import nxm.sys.lib.Data;
import nxm.sys.lib.DataFile;
import nxm.sys.lib.Primitive;

/**
   PROTOTYPE ONLY!
   Takes type-3000 files with amplitude and time columns and creates a
   type-2000 file with time slices. Each bin has the maximum amplitude
   found in that bin's time range.

   @author Jeanette McCall
*/
public class timeslicer extends Primitive  {

    private DataFile hi;
    private Data data_in;

    private DataFile ho;    // We need one output header per record,
    private Data data_out;  // similarly for buffers, names, etc
    private int frameSize;
    private double frameStart;
    private double frameTimeLength;
    private double binTimeLength;

    /** The component byte offset of the name field. */
    private int bName = -1;
    /** The component byte offset of the name field. */
    private int bAmp = -1;
    /** The component byte offset of the name field. */
    private int bTime = -1;
    /** The component format for the name field. */
    private String fName = null;
    private int num_subrec, recLength;

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

    public int open () {
      double old_size;

      // Open file
      hi = MA.getDataFile ("IN");
      hi.open();
      int iName      = hi.findRec("NAME");
      int iAmp       = hi.findRec("AMP");
      int iTime      = hi.findRec("EVENT_TIME");
      bName  = (iName  >= 0) ? hi.getCompOffset(iName)  : -1;
      bAmp   = (iAmp   >= 0) ? hi.getCompOffset(iAmp)  : -1;
      bTime  = (iTime  >= 0) ? hi.getCompOffset(iTime)  : -1;
      fName  = hi.getCompFormat(iName);
      double xStart = hi.getXStart();
      frameStart = xStart;
      frameSize = MA.getI("FS");
      frameTimeLength = MA.getI("TIME_PER_FRAME");
      binTimeLength   = frameTimeLength / frameSize;
      data_in = new Data("SB", recLength);

      // Only read one record at a time (this is set by our buffer size)
      recLength = hi.getRecLength();

      num_subrec = hi.getSubSize();

      data_out   = new Data("SD",frameSize);

      ho = MA.getDataFile("OUT", "2000", "SD", 0);
      ho.setSubSize(frameSize);
      ho.setXStart(xStart);
      ho.setXDelta(binTimeLength);
      ho.setXUnits(Units.TIME);
      ho.setYStart(xStart);
      ho.setYDelta(frameTimeLength);
      ho.setYUnits(Units.TIME);
      ho.setInternals();
      ho.open(BaseFile.OUTPUT);

      data_in = new Data("SB", recLength);

      // Fake out the library routines (so much for encapsulation)

      old_size = hi.size;
      hi.setFormat("SB");  // Avoid reformats inside the read
      hi.setType(1000);
      hi.setFS(0);  // Cause typeClass to be set
      hi.setSize(old_size*recLength);

      return NORMAL;
    }

    public int process() {

      int n = hi.read(data_in, recLength);
      if (n==0) return NOOP;
      if (n<0) return FINISH;

      // Copy each input record into all of the various output records
      int len = Data.getBPA(fName);
      String name = data_in.unpackS(bName,len);
      double amp  = data_in.unpackD(bAmp);
      double time = data_in.unpackD(bTime);
      if (time > frameStart + frameTimeLength) {
        // need to write out old frame and start new frame
        ho.write (data_out);
        data_out   = new Data("SD",frameSize);
        frameStart += frameTimeLength;
        while (time > frameStart + frameTimeLength) {
          ho.write (data_out);
          frameStart += frameTimeLength;
        }
      }
      int bin = (int)((time - frameStart) / binTimeLength);
      bin = Math.min(frameSize, bin);
      double currentValue = data_out.getD(bin*data_out.getAPE());
      if (amp > currentValue) {
        data_out.setD(bin*data_out.getAPE(),amp);
      }

      return NORMAL;
    }

    public int close() {
      if (hi.getSize() > 0) {
        // need to flush data
        ho.write (data_out);
      }
      hi.close();
      ho.close(); // in case can get rid of restore
      return NORMAL;
    }


}
