package nxm.dsp.prim;

import nxm.dsp.lib.FilterFIR;
import nxm.dsp.lib.FilterFIR.FilterType;
import nxm.sys.lib.Data;
import nxm.sys.lib.DataFile;
import nxm.sys.lib.Primitive;
import nxm.sys.libm.Fft;

/** Creates FIR filter using window method
    @author  Jeff Schoen
 */
public class firwind extends Primitive {

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

  @Override
  public int open () {
    // Get parameters
    // Allow old X-Midas abbreviations "LOW", "HIGH", etc.
    // FilterType type  = MA.getSelection("TYPE", FilterType.BandPass);
    int        _type = MA.getSelectionIndex("TYPE",typeList,0);
    FilterType type  = FilterType.values()[_type-1];
    String     wname = MA.getS("WIND");
    int        ntap  = MA.getL("NTAP");
    double     freqF = MA.getD("FREQF");
    double     freq1 = MA.getD("FREQ1");
    double     freq2 = MA.getD("FREQ2");
    double     scale = MA.getD("/SCALE",1.0);
    boolean    sym   = MA.getState("/SYM");
    boolean    fsym  = MA.getState("/FILTER_SYM", false); // Testing Use Only: should be false
    boolean    cx    = MA.getState("/CMPLX");

    // derived parameters
    ntap  = Fft.validSize(ntap,cx?Fft.COMPLEX:Fft.REAL);
    int    spa   = cx? 2 : 1;
    int    mtap  = sym? ntap-1 : ntap;
    double delta = 0.5/freqF;

    // Open output file
    DataFile ho = MA.getDataFile("OUT","1000",cx?"CF":"SF",0);
    ho.setSize(mtap);
    ho.setXStart(-0.5*delta*(sym?mtap-1:ntap));
    ho.setXDelta(delta);
    ho.open(DataFile.OUTPUT);

    // generate FIR taps
    FilterFIR f    = new FilterFIR(M, type, ntap, freq1, freq2, freqF, cx, fsym, wname, scale);
    Data      filt = new Data(f.makeFilter(ntap+2), spa);

    // write data buffers
    if (sym) filt.boff=filt.bps*spa;
    ho.write(filt,mtap);
    ho.close();

    return FINISH;
  }

  //////////////////////////////////////////////////////////////////////////////
  // DEPRECATED CODE -- TODO: DELETE IN 3.7.x SERIES
  //////////////////////////////////////////////////////////////////////////////

  /** @deprecated Since NeXtMidas 3.3.1 use {@link FilterType} in place of this. */
  @Deprecated public static final String typeList = "LowPass,HighPass,BandPass,StopBand";
  /** @deprecated Since NeXtMidas 3.3.1 use {@link FilterType} in place of this. */
  @Deprecated public static final int LOW=1, HIGH=2, BAND=3, STOP=4;

  /** @param type  Filter type.
      @param ntap  Number of taps.
      @param f1    1st transition frequency (Hz).
      @param f2    2nd transition frequency (Hz).
      @param wind  window
      @param filt  output filter
      @param cx    complex filter?
      @deprecated Since NeXtMidas 3.3.1 use {@link FilterFIR} in place of this.
   */
  @Deprecated
  public static void generate (int type, int ntap, double f1, double f2, float[] wind, float[] filt, boolean cx) {
    int bin1,bin2;

    // zero all bins
    int n = cx? ntap*2 : ntap+1;
    for (int i=0; i<n; i++) filt[i]=0;

    // convert freqs to bins of interest
    bin1 = ((int)(0.5*ntap*f1)+1)*2;
    if ((type==BAND) || (type==STOP)) {
      if (f2==0) f2=1.0;
      bin2 = ((int)(0.5*ntap*f2)+1)*2;
    }
    else {
      bin2 = ntap+1;
    }

    // make ones in pass bands
    if (type==LOW)  for (int i=0; i<bin1; i+=2) { filt[i]=1; if (cx) filt[n-i]=1; }
    if (type==HIGH) for (int i=bin1; i<bin2; i+=2) { filt[i]=1; if (cx) filt[n-i]=1; }
    if (type==BAND) for (int i=bin1; i<bin2; i+=2) { filt[i]=1; }
    if (type==STOP) for (int i=0; i<bin1; i+=2) { filt[i]=1; }
    if (type==STOP) for (int i=bin2; i<n; i+=2) { filt[i]=1; }

    // shift alternate points by 180 degrees to make inverse FFT non-causal
    for (int i=2; i<n; i+=4) filt[i] = -filt[i];

    // inverse FFT
    Fft.process(filt,ntap,Fft.INVERSE|(cx?Fft.COMPLEX:Fft.REAL|Fft.UNPACKED));

    // multiply by window
    if (cx) for (int i=0; i<ntap; i++) { filt[i+i+0] *= wind[i]; filt[i+i+1] *= wind[i]; }
    else    for (int i=0; i<ntap; i++) filt[i] *= wind[i];

  }

}
