package nxm.sys.test.junit.lib;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

import nxm.sys.lib.Data;
import nxm.sys.lib.DataFile;
import nxm.sys.lib.DataFileStreamSupport;
import nxm.sys.lib.Midas;
import nxm.sys.lib.Shell;
import nxm.sys.test.junit.NMTestCase;

/** Starter test for the DataFileStreamSupport class.
    @author  Jeanette McCall
    @since 4.1.4
 */
public class DataFileStreamSupportTest extends NMTestCase {

  /** public constructor to allow running this test case directly with JUnit. */
  public DataFileStreamSupportTest (String methodName) {
    this(methodName, null);
  }

  /** This constructor is required by NeXtMidas Unit Testing framework.
      @param methodName The name of the method being called.
      @param midas      The midas context to use when running the tests.
   */
  public DataFileStreamSupportTest (String methodName, Midas midas) {
    super(methodName, midas);
  }

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

  public void testPackBlueFile () {
    packFileByCopy();
  }

  public void testPackDetachedHeader () {
    packDetachedByCopy();
  }

  private void packFileByCopy () {
    Midas M = getMidasContext();
    DataFile origFile = new DataFile(M,"nxm.sys.test.fft_wavechirp_tc.prm");
    origFile.open();
    LinkedHashMap<String, Object> extKWMap = createExtKeywordsMap(origFile);
    byte[] fileData = setData(origFile);

    DataFileStreamSupport pfbc = new DataFileStreamSupport();
    setFieldsToMatch(pfbc, origFile);
    origFile.close();

    pfbc.setExtendedHeaderKeywords(extKWMap);
    byte[] byteCopy = pfbc.packBlueFile(fileData);
    try {
      String writePath = Shell.getAuxPath("WRITE");
      Path outPath = Paths.get(writePath + "copyoffile.tmp");
      Files.write(outPath, byteCopy);
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

  private void packDetachedByCopy () {
    Midas M = getMidasContext();
    DataFile origFile = new DataFile(M,"nxm.sys.test.fft_wavechirp_tc.prm");
    origFile.open();
    LinkedHashMap<String, Object> extKWMap = createExtKeywordsMap(origFile);

    DataFileStreamSupport pfbc = new DataFileStreamSupport();
    setFieldsToMatch(pfbc, origFile);
    origFile.close();

    pfbc.setExtendedHeaderKeywords(extKWMap);
    byte[] byteCopy = pfbc.packDetachedHeader();
    try {
      String writePath = Shell.getAuxPath("WRITE");
      Path outPath = Paths.get(writePath + "copyoffiledetached.tmp");
      Files.write(outPath, byteCopy);
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

  private void setFieldsToMatch (DataFileStreamSupport dfss, DataFile df) {
    int nelem = (int)df.getSize();
    int bpe = Data.getBPA(df.getFormat());
    dfss.setDataSize(nelem*bpe*df.getSubsize());
    dfss.setFormat(df.getFormat());
    dfss.setType(df.getType());
    dfss.setXStart(df.getXStart());
    dfss.setXDelta(df.getXDelta());
    dfss.setXUnits(df.getXUnits());
    dfss.setSubsize(df.getSubsize());
    dfss.setYStart(df.getYStart());
    dfss.setYDelta(df.getYDelta());
    dfss.setYUnits(df.getYUnits());
  }

  private LinkedHashMap<String,Object> createExtKeywordsMap (DataFile df) {
    Collection<Map.Entry<String,Object>> extHeaderKW = df.getKeywordsObject().getAll("EXTENDED",true);
    LinkedHashMap<String,Object> extKWMap = new LinkedHashMap<>();
    for (Map.Entry<String,Object> e : extHeaderKW) {
      extKWMap.put(e.getKey(), e.getValue());
    }
    return extKWMap;
  }

  private byte[] setData (DataFile df) {
    int nelem = (int)df.getSize();
    int bpe   = (int)df.getBPE();
    byte[] dataAsBytes;
    if (df.getType() == 2000) {
      dataAsBytes = new byte[nelem*bpe];
      for (int i=0; i < nelem; i++) {
        Data fileData = df.getDataBuffer(1);
        df.read(fileData);
        byte[] thisElem = fileData.getBuf();
        System.arraycopy(thisElem, 0, dataAsBytes, bpe*i, bpe);
      }
    }
    else {
      Data fileData = df.getDataBuffer(nelem);
      df.read(fileData);
      dataAsBytes = fileData.getBuf();
    }
    return dataAsBytes;
  }
}
