
/**
 * XYDataFileReader.java
 * This class reads in information from xydata files.
 *
 * Created:  June 19, 2005
 *
 * @author Nathan Stevens
 * @version 0.11 3/13/06
 */
import java.io.*;
import java.util.Vector;

public class XYDataFileReader extends Thread {
  private XYDataImporter xydataImporter= null;
  private File[] files = null;
  private String instrument = null;
  private String instrumentName = null;
  private String delimiter = null;
  private String regex = null;
  private String description = null;
  private String[] axis = null;
  private String[] notes = null;
  private boolean ascending= true;
  private TextInputFile inputFile = null;
  private Vector textlines = null;
  private Vector vdata = null;
  private String exptype = null; // the experiment type
  
  // The main constructor
  public XYDataFileReader(XYDataImporter xydataImporter, File[] files, String instrument,
  String instrumentName, String delimiter, String regex, String description, String[] axis,
  String[] notes, boolean ascending) {
    super("XYData File Reader");
    this.xydataImporter = xydataImporter;
    this.files = files;
    this.instrument = instrument;
    this.instrumentName = instrumentName;
    this.delimiter = delimiter;
    this.regex = regex;
    this.description = description;
    this.axis = axis;
    this.notes = notes;
    this.ascending = ascending;
  }
  
  // Method that takes an XYData instrument object
  public XYDataFileReader(XYDataImporter xydataImporter, File[] files, 
  XYDataInstrument xydataInstrument) {
    super("XYData File Reader");
    this.xydataImporter = xydataImporter;
    this.files = files;
    instrument = xydataInstrument.getInstrument();
    instrumentName = xydataInstrument.getInstrumentName();
    delimiter = xydataInstrument.getDelimiter();
    regex = xydataInstrument.getRegex();
    description = xydataInstrument.getDescription();
    axis = xydataInstrument.getAxis();
    notes = xydataInstrument.getNotes();
    ascending = xydataInstrument.isAscending();
  }
  
  // The run method to read in the file
  public void run() {
    vdata = new Vector();
    SpectraData sd;
    
    for(int i = 0; i < files.length; i++) {
      sd = importDataFile(files[i]);
      if(sd != null) {
        vdata.addElement(sd);
      }
      else {
        xydataImporter.print("Error reading data file " + files[i].getName() + ".\n");
        xydataImporter.print("It does not appear to be a XY data file...\n\n");
      }
    }
    
    SpectraData[] sda = SpectraDataUtil.getSpectraDataArray(vdata);
    
    // add generate spectra data xydata importer now
    if(sda != null) {
      xydataImporter.loadSpectraData(getExperimentType(), sda); // must actually fix this
    }
  }
  
  // Method to get the instrument type based
  private String getExperimentType() {
    String exptype;
    
    if(instrument.equals("Absorption")) {
      exptype = "absorption";
    }
    else if(instrument.equals("Emission")) {
      exptype = "emission";
    }
    else if(instrument.equals("Raman")) {
      exptype = "raman";
    }
    else if(instrument.equals("Decay Profile")) {
      exptype = "streak";
    }
    else {
      exptype = "xydata";
    }
    
    return exptype;
  }
  
  // Method to read in a file and return an SpectraData object
  private SpectraData importDataFile(File file) {
    textlines = new Vector();
    inputFile = new TextInputFile(file);
    SpectraData sd = null;
    String line = null;
    float[][] xydata = null;
    
    // now read in the data
    while(!inputFile.eof()) {
      line = inputFile.readLine();
      if(line.matches(regex)) {
        textlines.addElement(line);
      }
    }
    inputFile.close();
    
    // Initialize the meta information now
    String dmeta[] = new String[8];
    dmeta[0] = InstruView.getProperty("organization");
    dmeta[1] = InstruView.getProperty("laboratory");
    dmeta[2] = InstruView.getProperty("owner");
    dmeta[3] = InstruView.getProperty("email");
    dmeta[4] = instrumentName;
    dmeta[5] = "mm-dd-yyyy";
    dmeta[6] = "00";
    
    // get the data array now
    if(ascending) {
      xydata  = getAscendingDataArray(textlines);
    }
    else {
      xydata  = getDescendingDataArray(textlines);
    }
    
    // now create a SpectraDataObject
    String name = getName(file);
    String min = "" + xydata[0][0];
    String max = "" + xydata[xydata.length-1][0];
    String dps = "" + xydata.length;
    
    String type = "";
    String[] header = null;
    
    if(instrument.equals("Absorption")) {
      type = "transmission";
      header = new String[]{min, max, dps, "Unknown", "10", "none"};
    }
    else if(instrument.equals("Emission")) {
      type = "Em";
      header = new String[]{min, max, dps, "RA", "0.3", "400", "Unknown", "None"};
    }
    else if(instrument.equals("Raman")) {
      if(description.equals("macro") || description.equals("micro") || description.equals("FT")) {
        type = description;
      }
      else {
        type = "macro";
      }
      
      // get the laser wavelength (nm)
      String[] sa = notes[0].split("\\s*=\\s*");
      String laser = sa[1];
      
      // get the integration time (seconds)
      sa = notes[1].split("\\s*=\\s*");
      String itime = sa[1];
      
      header = new String[]{min, max, dps, laser, itime, "Unknown", "None"};
    }
    else if(instrument.equals("Decay Profile")) {
      // add ROIV to the name
      name += "ROIV";
      
      // get the minimum and maximum wavelengths
      String[] sa = notes[0].split("\\s*=\\s*");
      String minwl = sa[1];
      
      sa = notes[1].split("\\s*=\\s*");
      String maxwl = sa[1];
      
      sa = notes[2].split("\\s*=\\s*");
      String slaser = sa[1];
      
      String mint = "" + xydata[0][0];
      String maxt = "" + xydata[xydata.length-1][0];
      String sexp = "N/A";
      String snexp = "N/A";
      String ctype = "Unkown";
      String notes = "None";
      
      header = new String[]{minwl, maxwl, mint, maxt, dps, slaser, sexp, snexp, 
                                         ctype, notes};
      
      type = "streak";
    }
    else { // assume its xy data
      // see if we need to reset the notes to "none"
      if(notes[0].indexOf("=none") != -1) {
        notes[0] = "none";
      }
      
      if(notes[1].indexOf("=none") != -1) {
        notes[1] = "none";
      }
      
      if(notes[2].indexOf("=none") != -1) {
        notes[2] = "none";
      }
      
      type = "xydata";
      header = new String[]{min, max, dps, axis[0], axis[1], axis[2], axis[3], description, notes[0], notes[1], notes[2]};
      
      /* can't really keep track of what these variables are so this might help
      min => minimum X vlaue [0]
      max => maximum X value [1]
      dps => data points [2]
      axis[0] => X units [3]
      axis[1] => Y units [4]
      axis[2] => X label [5]
      axis[3] => Y label [6]
      description => short description of data [7]
      notes[0] => note 1 value [8]
      notes[1] => note 2 value [9]
      notes[2] => note 3 (sample=xxx) value [10]
      */
    }
    
    sd = new SpectraData(name, type, header, dmeta, xydata, null);
    sd.setProfileDirection(InstruView.VERTICAL_PROFILE);
    
    // return the data object
    return sd;
  }
  
  // Method to read in a descending data array
  private float[][] getAscendingDataArray(Vector textlines) {
    Object[] lines = textlines.toArray();
    float[][] xydata = null;
    String[] sa = null;
    String line = null;
    
    if(textlines.size() != 0) {
      xydata = new float[textlines.size()][2];
      float xvalue = 0f;
      float yvalue = 0f;
      
      for(int i = 0; i < xydata.length; i++) {
        line = (String)lines[i];
        sa = line.split(delimiter);
        try {
          xvalue = Float.parseFloat(sa[0]);
          yvalue = Float.parseFloat(sa[1]);
        }
        catch (NumberFormatException nfe) {
           xvalue = 0f;
           yvalue = 0f;
        }
        
        xydata[i][0] = xvalue;
        xydata[i][1] = yvalue;
      }
    }
     else {
       xydata = new float[1][2];
       xydata[0][0] = 0.0f;
       xydata[0][1] = 0.0f;
    }
    
    return xydata;
  }
  
  // Method to return a float array containing the data
  private float[][] getDescendingDataArray(Vector textlines) {
    Object[] lines = textlines.toArray();
    float[][] xydata = null;
    String[] sa = null;
    String line = null;
    
    if(textlines.size() != 0) {
      xydata = new float[textlines.size()][2];
      float xvalue = 0f;
      float yvalue = 0f;
      
      int j = xydata.length- 1;
      for(int i = 0; i < xydata.length; i++) {
        line = (String)lines[j];
        sa = line.split(delimiter);
        try {
          xvalue = Float.parseFloat(sa[0]);
          yvalue = Float.parseFloat(sa[1]);
        }
        catch (NumberFormatException nfe) {
           xvalue = 0f;
           yvalue = 0f;
        }
        
        xydata[i][0] = xvalue;
        xydata[i][1] = yvalue;
        j--;
      }
    }
    else {
      xydata = new float[1][2];
      xydata[0][0] = 0.0f;
      xydata[0][1] = 0.0f;
    }
    
    return xydata;
  }
  
  // return the name of the data object
  private String getName(File file) {
    String fn = file.getName();
    int end = fn.indexOf('.');
    String name = fn.substring(0, end);
    
    return name;
  }
} // -- end class XYDataFileReader
