package org.spview.filehandler;
/*
 * Class of prediction file
 */

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 javax.swing.JOptionPane;

import org.spview.point.PredXPoint;

/**
 * This class defines prediction data.
 */
public class PredFile {

    private final String name; // file name
    private final String type; // type (TDS/HITRAN/PICKETT)
    private double[] x; // X
    private double[] y; // Y
    private String[] jsyn; // assignment string
    private int[] jinf; // jinf extracted from jsyn

    private int nbxy; // nb of points

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

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

    /**
     * Construct a new PredFile. <br>
     * (TDS, HITRAN or PICKETT type)
     *
     * @param cname name of the file
     * @param ctype type of the file
     */
    public PredFile(String cname, String ctype) {

        name = cname; // file name
        type = ctype; // type (TDS/HITRAN/PICKETT)

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

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

    /**
     * Read file. <br>
     * validity is tested following FORMAT : 1022 of spect.f, 1000 of spech.f
     */
    public boolean read() {

        // to keep points, unknown nb of points
        ArrayList<Double> alx = new ArrayList<>(); // frequency
        ArrayList<Double> aly = new ArrayList<>(); // intensity
        ArrayList<String> aljsyn = new ArrayList<>(); // assignment
        ArrayList<String> alxjsyn = new ArrayList<>(); // extended assignment
        String cjsyn = ""; // current assignment
        String cxjsyn = ""; // current extended assignment
        try {
            Point2D data;
            br = new BufferedReader(new FileReader(name)); // open
            // to read file
            String str;
            while ((str = br.readLine()) != null) { // line read
                if (type.equals("HITRAN")) {
                    data = HITRANFile.extractXY(str);
                    if (data != null) {
                        cjsyn = HITRANFile.extractAssignment(str);
                        cxjsyn = HITRANFile.extractExtendedAssignment(str);
                    }
                } else if (type.equals("PICKETT")) {
                    data = PickettFile.extractXY(str);
                    if (data != null) {
                        cjsyn = PickettFile.extractAssignment(str);
                    }
                } else {
                    data = TDSFile.extractXY(str);
                    if (data != null) {
                        cjsyn = TDSFile.extractAssignment(str);
                    }
                }
                if (data != null) {
                    alx.add(data.getX()); // keep data
                    aly.add(data.getY());

                    // test if jsyn is not empty
                    if (cjsyn.length() == 0) {
                        JOptionPane.showMessageDialog(null, str + lnsep + "Empty jsyn in file" + lnsep + name);
                        return false;
                    }

                    // test if xjsyn (HITRAN) or jsyn (TDS) is uniq
                    if (type.equals("HITRAN")) {
                        // HITRAN
                        if (alxjsyn.contains(cxjsyn)) {
                            JOptionPane.showMessageDialog(null, cxjsyn + lnsep + "Duplicated in file" + lnsep + name);
                            return false;
                        }
                        alxjsyn.add(cxjsyn); // keep data
                    } else {
                        // TDS
                        if (aljsyn.contains(cjsyn)) {
                            JOptionPane.showMessageDialog(null, cjsyn + lnsep + "Duplicated in file" + lnsep + name);
                            return false;
                        }
                    }
                    aljsyn.add(cjsyn); // keep data
                }
            }
        } 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) {
                }
            }
        }
        // save data
        nbxy = alx.size(); // nb of points
        if (nbxy == 0) {
            // no point
            JOptionPane.showMessageDialog(null, "No valid data found in file" + lnsep + name);
            return false;
        }
        x = new double[nbxy];
        y = new double[nbxy];
        jsyn = new String[nbxy];
        jinf = new int[nbxy];
        // sort
        PredXPoint[] pxpt = new PredXPoint[nbxy]; // compare X
        for (int i = 0; i < nbxy; i++) {
            pxpt[i] = new PredXPoint(alx.get(i), aly.get(i), aljsyn.get(i));
        }
        Arrays.sort(pxpt); // sort
        // save data
        for (int i = 0; i < nbxy; i++) {
            x[i] = pxpt[i].getX();
            y[i] = pxpt[i].getY();
            jsyn[i] = pxpt[i].getJsyn();
            try {
                // extract jinf from jsyn
                // TDS, HITRAN
                jinf[i] = Integer.parseInt(jsyn[i].substring(0, 3).trim());
            } catch (NumberFormatException e) {
                // format error
                jinf[i] = -1;
            }
        }

        return true;
    }

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

        return nbxy;
    }

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

        return x;
    }

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

        return y;
    }

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

        return x[id];
    }

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

        return y[id];
    }

    /**
     * Get Jinf array.
     */
    public int[] getJinf() {

        return jinf;
    }

    /**
     * Get Jsyn assignment array.
     */
    public String[] getJsyn() {

        return jsyn;
    }

}
