package nxm.sys.prim;

import nxm.sys.lib.BaseFile;
import nxm.sys.lib.Data;
import nxm.sys.lib.DataFile;
import nxm.sys.lib.DataOp;
import nxm.sys.lib.Parser;
import nxm.sys.lib.Primitive;

/**
  Multiplex real and imaginary components into one complex file.

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

  private DataFile hc,hr,hi;
  private Data dc,dr,di;
  private double constant;
  private int mode;
  /** list of available complex-file modes */
  public static String modeList = "RI,RR,II,IR";
  private static int mRI=1, mRR=2, mII=3, mIR=4;

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

  public int open() {

    mode = MA.getSelectionIndex("/MODE",modeList,mRI);

    hr = MA.getDataFile ("REAL","1000","S#",0);
    hr.open();

    hi = MA.getDataFile ("IMAG","1000","S#",0);
    if (!MA.getState("/CONST")) hi.open();

    byte dtype = hr.getFormatType();
    if (hi.isOpen) { // compatibility checks
      if (hr.getXDelta()!=hi.getXDelta()) M.error("File xdeltas do not match");
      if (hr.getXUnits()!=hi.getXUnits()) M.error("File xunits do not match");
      dtype = Data.promoteType(dtype,hi.getFormatType());
    }

    hc = MA.getDataFile ("COMP",hr,0);
    hc.setFormatMode(COMPLEX);
    hc.setFormatType(dtype);
    hc.open(BaseFile.OUTPUT);

    xfer = Math.max(1,(int)(bufSize/hc.dbpe));
    xfer = MA.getL("/TL",xfer);

    dr = hr.getDataBuffer(xfer,dtype);
    dc = hc.getDataBuffer(xfer,dtype);
    if (hi.isOpen) di = hi.getDataBuffer(xfer,dtype);
    else setConstant(MA.getD("IMAG"));

    return NORMAL;
  }

  public int process() {

    int nr = hr.read(dr);
    if (nr==0) return NOOP;
    else if (nr<0) return FINISH;

    int ni = hi.isOpen? hi.read(di) : nr;
    if (ni==0) return NOOP;
    else if (ni<0) return FINISH;

    int n = Math.min(nr,ni);
    if (hr.isOpen) {
      if (mode==mRI||mode==mRR) DataOp.copy (dr,0,dr.bpe, dc,0*dc.bps,dc.bpe, dr.bpe,n);
      if (mode==mIR||mode==mRR) DataOp.copy (dr,0,dr.bpe, dc,1*dc.bps,dc.bpe, dr.bpe,n);
    }
    if (hi.isOpen) {
      if (mode==mRI||mode==mII) DataOp.copy (di,0,di.bpe, dc,1*dc.bps,dc.bpe, di.bpe,n);
      if (mode==mIR||mode==mII) DataOp.copy (di,0,di.bpe, dc,0*dc.bps,dc.bpe, di.bpe,n);
    }
    hc.write(dc,n);

    return NORMAL;
  }

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

  /** Set numeric constant for the imaginary file name
   *  @param value the numeric constant
   */
  public void setConstant (double value) {
    constant = value;
    DataOp.fill(dc,0,value,xfer);
  }
  /** Get numeric constant for the imaginary file name
   *  @return the numeric constant
   */
  public double getConstant() {
    return constant;
  }
  /** set complex-file mode
   *  @param smode the complex-file mode
   */
  public void setMode (String smode) {
    mode = Parser.find(modeList,smode,mode);
  }

}
