package nxm.sys.prim;

import nxm.sys.lib.Convert;
import nxm.sys.lib.Data;
import nxm.sys.lib.DataFile;
import nxm.sys.lib.Primitive;
import nxm.sys.lib.SDDSPacket;
import nxm.sys.lib.Time;
import nxm.sys.lib.UdpResource;

/**
  Copies data from one file to an SDDS formatted file or UDP port.

  @author Jeff Schoen
*/
public class sinksdds extends Primitive {

  private DataFile hi,ho;
  private Data data;
  private SDDSPacket pkho,pkh;
  private boolean rt,wrap,swap,inputIsSDDS;
  private double tdelta,tstart;
  private Time time;

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

  public int open() {

    hi = MA.getDataFile ("IN","1000","SN,SB,SI",0);
    hi.open();

    pkh = new SDDSPacket();
    pkh.setFormat(hi.getFormat());
    pkho = (SDDSPacket) hi.getPacketHandler();
    inputIsSDDS = (pkho!=null);

    ho = MA.getDataFile ("OUT",hi,0);
    if (inputIsSDDS) pkh=pkho;		// use output packet handler
    else ho.setPacketHandler(pkh);	// add output packet handler
    ho.open();

    // a UDP output resource handles its own UDP header fields
    if (ho.io instanceof UdpResource) pkh.setUDP(false);

    wrap = MA.getState("/WRAP");
    rt   = MA.getState("/RT");
    xfer = (int)(1024/hi.dbpe);
    data = hi.getDataBuffer(xfer);
    swap = (data.bps==2) && !Convert.isBigEndian(data.rep);

    tdelta = hi.getDelta();
    tstart = 0;

    time = hi.getTime();
    if (time.getWSec()==0) time.fromCurrent();
    if (rt && tdelta>=0.1) M.warning("Realtime with dt>0.1 ?");

    return (NORMAL);
  }

  public int process() {
    if (rt) {
      if (tstart==0 && hi.avail()<xfer) return (NOOP);
      if (tstart==0) tstart = Time.current();
      if (Time.current()<tstart+ho.seek()*tdelta) return (NOOP);
    }
    int n = hi.read(data);
    if (n>0) {
      if (swap) Convert.swap2 (data.buf,0,n);
      if (n<xfer) M.warning("Partial packet of "+n+" elements not output");
      else if (inputIsSDDS) ho.write(data);	// just write
      else {					// update timecode and write
        pkh.setTC (0,tdelta,time.getWSec(),time.getFSec());
        ho.write(data);
        pkh.upCount();
        time.addSec(xfer*tdelta);
      }
    }
    else if (n==0) return (NOOP);
    else if (wrap && (hi.isFile() || hi.isJarFile())) hi.seek(0.0);
    else return (FINISH);
    return (NORMAL);
  }

  public int close() {
    hi.close();
    ho.close();
    return (NORMAL);
  }

}
