package org.spview.residuals;

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JOptionPane;

import org.spview.point.ResidualPoint;
import org.spview.filehandler.ExpFile;
import org.spview.filehandler.PredFile;
import org.spview.point.ExpJsynPoint;
import org.spview.gui.JFCreatePeakFile;
import org.spview.gui.JobPlay;
import org.spview.gui.PlotData;

public class ObsCalc {
	private final ExpFile expFile;
	private final PredFile predFile;
	private PlotData mainPanel;

	public ObsCalc(ExpFile expFile, PredFile predFile) throws Exception {
		if (expFile == null || expFile.getNbxy() == 0 || predFile == null || predFile.getNbxy() == 0) {
			throw new Exception("Invalid data");
		}
		this.expFile = expFile;
		this.predFile = predFile;
	}

	public ArrayList<ResidualPoint> getFreqResiduals() {
		int n = this.expFile.getNbxy();

		if (n < 1)
			return null;
		ArrayList<ResidualPoint> XResiduals = new ArrayList<>();
		ArrayList<ExpJsynPoint>[] expPoint = expFile.getEjsynpt();
		for (int i = 0; i < n; i++) {
			for (ExpJsynPoint uniqPoint : expPoint[i]) {
				int index = uniqPoint.getIpred();

				if (index != -1 && uniqPoint.getFaso().equals("+")) {
					double diff = (this.expFile.getX(i) - this.predFile.getX(index)) * 1E3;
					XResiduals.add(new ResidualPoint(this.expFile.getX(i), diff, uniqPoint.getJsyn()));
				}
			}
		}
		return XResiduals.isEmpty() ? null : XResiduals;
	}

	public ArrayList<ResidualPoint> getIntResiduals() {
		int n = this.expFile.getNbxy();

		if (n < 1)
			return null;
		ArrayList<ResidualPoint> YResiduals = new ArrayList<>();
		ArrayList<ExpJsynPoint>[] expPoint = expFile.getEjsynpt();
		for (int i = 0; i < n; i++) {
			for (ExpJsynPoint uniqPoint : expPoint[i]) {
				int index = uniqPoint.getIpred();

				if (index != -1 && uniqPoint.getSaso().equals("+")) {
					// 100*(obs-calc)/obs
					double diff = 100 * (this.expFile.getY(i) - this.predFile.getY(index)) / this.expFile.getY(i);
					YResiduals.add(new ResidualPoint(this.expFile.getX(i), diff, uniqPoint.getJsyn()));
				}
			}
		}
		return YResiduals.isEmpty() ? null : YResiduals;
	}

	public void show(JobPlay jobplay, String type) {
		List<ResidualPoint> data = type.equals("X") ? getFreqResiduals() : getIntResiduals();
		if (data == null) {
			JOptionPane.showMessageDialog(null, "There is no data to display!", "No data", JOptionPane.WARNING_MESSAGE);
			return;
		}
		mainPanel = new PlotData(jobplay, data);
		mainPanel.setPreferredSize(new Dimension(800, 600));

		JFrame frame;
		if (type.equals("X")) {
			frame = new JFrame("Frequency Obs-Cal Display");
		} else {
			frame = new JFrame("Intensity Obs-Cal Display");
		}
		frame.setIconImage(Toolkit.getDefaultToolkit().getImage(JFCreatePeakFile.class.getResource("/pixmaps/spview.png")));
		frame.getContentPane().add(mainPanel);
		frame.pack();
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);

		frame.addWindowListener(new WindowAdapter() { // clean end
			public void windowClosing(WindowEvent e) {
				if (mainPanel.getJFT() != null) {
					mainPanel.getJFT().dispose();
				}
			}
		});

	}
}
