package org.spview.filehandler;
/*
 * Class for data files (spectrum or stick/peakas/tdsas/hitras).
 */

import java.awt.geom.Point2D;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;

import javax.swing.JOptionPane;

import org.spview.point.StickPoint;

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

/**
 * This class defines spectrum or stick data.
 */
public class DataFile {

	private final String name; // file name
	private String ntfile; // type
	private double[] x; // X data
	private double[] y; // Y data

	private int nbxy; // nb of points

	private BufferedReader br;
	private final String lnsep; // line separator

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

	/**
	 * Construct a new DataFile.
	 *
	 * @param cname file name
	 */
	public DataFile(String cname) {

		name = cname; // file name

		nbxy = 0; // nb of points
		lnsep = System.getProperty("line.separator");

	}

	/**
	 * Get name selection string.
	 */
	public String getname() {

		return name;
	}

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

	/**
	 * Read file. <br>
	 * validity is tested following : <br>
	 * FORMAT 1000 of spech.f (HITRAN format prediction) <br>
	 * FORMAT 1022 of spect.f (TDS format prediction) <br>
	 * FORMAT 1024 of spects.f (D2hStark format prediction)
	 */
	public boolean read() {
		ArrayList<Double> alx = new ArrayList<>(); // frequency
		ArrayList<Double> aly = new ArrayList<>(); // intensity
		// binary files
		OpusFile opusFile = new OpusFile(name);
		try {
			if (opusFile.read()) {
				if (opusFile.getCancelled()) {
					/* User cancelled the operation */
					return false;
				}
				alx = opusFile.get_XArray();
				aly = opusFile.get_YArray();
			} else {
				// flat files
				try {
					double cx; // to keep X
					double cy; // to keep Y
					Point2D data;
					// to keep points, unknown nb of points

					br = new BufferedReader(new FileReader(name)); // open
					// to read file
					String str;
					while ((str = br.readLine()) != null) { // line read
						switch (ntfile) {
							case "peakas":
								// peak or assignment file as stick
								if (str.length() < 31) { // line too short
									continue; // skip it
								}
								try {
									// read data
									cx = Double.parseDouble(str.substring(6, 18)); // Double for X
									cy = Double.parseDouble(str.substring(20, 31)); // Double for Y
									data = new Point2D.Double(cx, cy);
								} catch (NumberFormatException e) { // format error
									continue; // skip the line
								}
								break;
							case "hitras":
								data = HITRANFile.extractXY(str);
								break;
							case "tdsas":
								data = TDSFile.extractXY(str);
								break;
							case "pickettas":
								data = PickettFile.extractXY(str);
								break;
							default:
								// spectrum or stick file
								str = str.replace(',', ' '); // comma as separator (-> space)

								StringTokenizer st = new StringTokenizer(str); // separate X and Y

								if (st.countTokens() < 2) { // not enough tokens
									continue; // skip the line
								}
								try {
									cx = Double.parseDouble(st.nextToken()); // Double for X
									cy = Double.parseDouble(st.nextToken()); // Double for Y
									data = new Point2D.Double(cx, cy);
								} catch (NumberFormatException e) { // format error
									continue; // skip the line
								}
								break;
						}
						if (data != null) {
							alx.add(data.getX()); // keep data
							aly.add(data.getY());
						}
					}
				} catch (IOException ioe) { // IO error
					JOptionPane.showMessageDialog(null, "IO error while reading file" + lnsep + name + lnsep + ioe);
					return false;
				} finally {
					// close
					if (br != null) {
						try {
							br.close();
						} catch (IOException ignored) {
						}
					}
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

		// save data
		int cnbxy = alx.size(); // current nb of points
		if (cnbxy == 0) {
			// no point
			JOptionPane.showMessageDialog(null, "No valid data found in file" + lnsep + name);
			return false; // invalid read
		}
		nbxy = cnbxy;
		x = new double[nbxy]; // create arrays
		y = new double[nbxy];
		// sort
		StickPoint[] stickpoint = new StickPoint[nbxy]; // compare X
		for (int i = 0; i < nbxy; i++) {
			stickpoint[i] = new StickPoint(alx.get(i), aly.get(i)); // X, Y
		}
		Arrays.sort(stickpoint); // sort
		for (int i = 0; i < nbxy; i++) {
			// save data
			x[i] = stickpoint[i].getX();
			y[i] = stickpoint[i].getY();
		}

		// happy end
		return true;
	}

	/**
	 * Set file type.
	 *
	 * @param cntfile file type (spectrum/stick/peakas/tdsas/hitras)
	 */
	public void setType(String cntfile) {

		ntfile = cntfile;
	}

	/**
	 * Get file type.
	 */
	public String getType() {

		return ntfile;
	}

	/**
	 * Get number of data points.
	 */
	public int getNbxy() {

		return nbxy;
	}

	/**
	 * Get X array.
	 */
	public double[] getX() {

		return x;
	}

	/**
	 * Get X value.
	 */
	public double getX(int id) {

		return x[id];
	}

	/**
	 * Get Y array.
	 */
	public double[] getY() {

		return y;
	}

	/**
	 * Get Y value.
	 */
	public double getY(int id) {

		return y[id];
	}

}
