package org.opensourcephysics.tools;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;

import org.opensourcephysics.analysis.FourierSinCosAnalysis;
import org.opensourcephysics.display.ColorIcon;
import org.opensourcephysics.display.Data;
import org.opensourcephysics.display.DataTable;
import org.opensourcephysics.display.Dataset;
import org.opensourcephysics.display.DatasetManager;
import org.opensourcephysics.display.PlottingPanel;
import org.opensourcephysics.display.TeXParser;

/**
 * A JPanel that displays a plot and table of the Fourier spectrum of an input Dataset.
 * 
 * @author Doug Brown
 */
public class FourierPanel extends JPanel {
  
	// instance fields
	protected Dataset sourceData;
  protected PlottingPanel plot;
  protected DataTable table;
  protected DatasetManager fourierManager; // local datasets: frequency vs power, cosine, sine
  protected JSplitPane splitPane;
  protected JCheckBox[] buttons;
  protected JPanel plotPanel;


  /**
   * Constructs a FourierPanel.
   */
  public FourierPanel() {
  	super(new BorderLayout());
    createGUI();
  }

  // _______________________ protected & private methods ______________________

  /**
   * Creates the GUI.
   */
  protected void createGUI() {
  	fourierManager = new DatasetManager();
  	fourierManager.setXPointsLinked(true);
    table = new DataTable();
    table.add(fourierManager);
    plot = new PlottingPanel("", "", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    plotPanel = new JPanel(new BorderLayout());
    plotPanel.add(plot, BorderLayout.CENTER);
    splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
    splitPane.setResizeWeight(1);
    JScrollPane scroller = new JScrollPane(table);
    splitPane.setRightComponent(scroller);
    splitPane.setLeftComponent(plotPanel);
    add(splitPane, BorderLayout.CENTER);
  }
  
  /**
   * Refreshes the fourier data based on a source dataset.
   *
   * @param data the source dataset
   * @param name a name that identifies the source
   */
  protected void refreshFourierData(Dataset data, String name) {
    JDialog dialog = (JDialog)this.getTopLevelAncestor();
    dialog.setTitle(ToolsRes.getString("DataToolTab.Dialog.Fourier.Title")); //$NON-NLS-1$
  	fourierManager.removeDatasets();
    Data fourierData = createFourierData(data);
    if (fourierData==null) return;
  	ArrayList<Dataset> datasets = fourierData.getDatasets();
    createButtons(datasets);
    for (Dataset next: datasets) {
    	fourierManager.addDataset(next);
    }
    table.refreshTable();
    name = TeXParser.removeSubscripting(name);
    String x = TeXParser.removeSubscripting(data.getXColumnName());
    String y = TeXParser.removeSubscripting(data.getYColumnName());
    plot.setTitle(name+" ["+x+", "+y+"]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    refreshPlot();
  }
  
  /**
   * Refreshes the plot to show currrently selected variables.
   */
  protected void refreshPlot() {
  	plot.removeDrawables(Dataset.class);
  	String s = ""; //$NON-NLS-1$
  	for (int i=0; i<buttons.length; i++) {
  		if (buttons[i].isSelected()) {
  	  	Dataset data = fourierManager.getDataset(i);
  			plot.addDrawable(data);
		    plot.setXLabel(data.getXColumnName());
		    if (s.length()>0) s += ", "; //$NON-NLS-1$
		    s += data.getYColumnName();
  		}
  	}
    plot.setYLabel(s);	
    plot.repaint();
  }
  
  /**
   * Creates the plot variable buttons.
   *
   * @param datasets the fourier datasets
   */
  protected void createButtons(ArrayList<Dataset> datasets) {
  	if (buttons==null) {
  		buttons = new JCheckBox[datasets.size()];
  		JPanel buttonPanel = new JPanel();
  		plotPanel.add(buttonPanel, BorderLayout.SOUTH);
      for (int i=0; i<buttons.length; i++) {
      	Dataset next = datasets.get(i);
      	buttons[i] = new PlotCheckBox(next.getYColumnName(), next.getFillColor());
      	buttonPanel.add(buttons[i]);
      }
      buttons[0].setSelected(true);
  	}
  	
  }
  
  // ____________________________ static methods ______________________________

  /**
   * Creates a Data object containing the Fourier spectrum of the input Dataset.
   *
   * @param dataset the input
   * @return the fourier spectrum Data
   */
  public static Data createFourierData(Dataset dataset) {
  	if (dataset==null)
  		return null;
    double[] x = dataset.getXPoints();
    double[] y = dataset.getYPoints();
    if (y.length<2) return null;
    if (y.length%2==1) { // odd number of points
      double[] xnew = new double[y.length-1];
      double[] ynew = new double[xnew.length];
      System.arraycopy(x, 0, xnew, 0, xnew.length);
      System.arraycopy(y, 0, ynew, 0, ynew.length);
      dataset.clear();
      dataset.append(xnew, ynew);
      x = xnew;
      y = ynew;
    }
    FourierSinCosAnalysis fft = new FourierSinCosAnalysis();
		fft.doAnalysis(x, y, 0);
    return fft;
  }

  //____________________________________ inner classes _________________________________
  
  class PlotCheckBox extends JCheckBox {
  	
  	ColorIcon icon;
  	Color outlineColor, fillColor=Color.WHITE;
  	
  	PlotCheckBox(String text, Color color) {
  		super(text);
  		outlineColor = color;
  		icon = new ColorIcon(fillColor, outlineColor, 13, 13);
  		setIcon(icon);
      addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
        	JCheckBox checkBox = (JCheckBox)e.getSource();
        	setSelected(checkBox.isSelected());
          refreshPlot();
        }
      });
  	}
  	
  	public void setSelected(boolean select) {
      icon.setColor(select? outlineColor: fillColor);
  		super.setSelected(select);
  	}
  	
  }
}