/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on 2005/11/18, 17:29
!  AUTHOR(S): KOGA, Junichiro
!  File : PlotDataAttributes.java
!  
!  Contact address :  Phase System Consortium
!                     E-mail: phase_system@nims.go.jp URL https://azuma.nims.go.jp
!
!
!   Since 2002, this program set had been intensively developed as a part of the following 
!  national projects supported by the Ministry of Education, Culture, Sports, Science and
!  Technology (MEXT) of Japan; "Frontier Simulation Software for Industrial Science
!  (FSIS)" from 2002 to 2005, "Revolutionary Simulation Software (RSS21)" from 2006 to
!  2008. "Research and Development of Innovative Simulation Software (RISS)" from 2008
!  to 2013. These projects is lead by the Center for Research on Innovative Simulation 
!  Software (CISS), the Institute of Industrial Science (IIS), the University of Tokyo.
!   Since 2013, this program set has been further developed centering on PHASE System
!  Consortium. 
!   The activity of development of this program set has been supervised by Takahisa Ohno.
!
!=======================================================================
 */

package ciss.phase_viewer.plugins.graph.plotattributes;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.border.TitledBorder;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.apache.log4j.Logger;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.StrokeSample;

import ciss.phase_viewer.graph.plotattributes.PlotAttributesEditor;
import ciss.phase_viewer.graph.plotattributes.PlotAttributesSubEditor;
import ciss.phase_viewer.graph.plotattributes.PlotShapesAndLines;
import ciss.phase_viewer.graph.plotattributes.SeriesInfo;
import ciss.phase_viewer.graph.plotattributes.ShapeSample;

/**
 * 「プロット方法」を編集.
 * 
 * @author
 */
public class PlotDataAttributes extends PlotAttributesSubEditor {
    private Logger logger = Logger
            .getLogger(PlotDataAttributes.class.getName());
    private XYPlot xyplot;
    private SeriesInfo[] series;
    private JPanel thispanel;

    /** Creates a new instance of PlotDataAttributes */
    public PlotDataAttributes(PlotAttributesEditor parent) {
        super(parent);
    }

    public boolean updateChart() {
        if (series == null || series.length == 0) {
            return false;
        }

        seriesChanged();

        for (int i = 0; i < series.length; i++) {
            if (!series[i].update(xyplot, dsetIndex[i], i))
                return false;
        }

        return true;
    }

    public void init() {
        thispanel = this;
        if (parent == null) {
            logger.debug("'parent' is null.");
            return;
        }
        Plot plot = parent.getSelectedPlot();
        if (plot == null) {
            logger.debug("'plot' is null.");
            return;
        }

        if (plot instanceof XYPlot) {
            xyplot = (XYPlot) plot;
        } else {
            return;
        }
    }

    private String[] range;
    private JList list;
    private JButton btnplotlinecolor;
    private JComboBox comboplottype;
    private JComboBox comboplotlinetype;
    private JTextField tfplotlinewidth;
    private JComboBox comboplotshapetype;
    private JTextField tfplotshapesize;
    private JCheckBox cbapplytoall;
    private boolean apply_to_all = false;
    private int dsetCount;
    private int[] dsetIndex;

    protected void initGUI() {
        removeAll();
        setLayout(new BorderLayout());

        JPanel p = new JPanel();
        p.setLayout(new GridBagLayout());
        GridBagConstraints constraints = new GridBagConstraints();
        constraints.gridx = 0;
        constraints.gridy = 0;
        constraints.fill = GridBagConstraints.HORIZONTAL;
        constraints.weightx = 1;
        constraints.weighty = 0;

        JPanel prangetype = new JPanel();
        prangetype.setLayout(new BoxLayout(prangetype, BoxLayout.X_AXIS));

        dsetCount = xyplot.getDatasetCount();
        Vector rangeVector = new Vector();
        for (int i = 0; i < dsetCount; i++) {
            XYSeriesCollection collection = (XYSeriesCollection) xyplot
                    .getDataset(i);
            int scount = collection.getSeriesCount();
            for (int j = 0; j < scount; j++) {
                rangeVector.addElement(collection.getSeries(j).getKey()
                        .toString());
            }
        }

        if (rangeVector.size() != 0) {
            range = new String[rangeVector.size()];
            rangeVector.copyInto(range);
            dsetIndex = new int[rangeVector.size()];
            int count = 0;
            for (int i = 0; i < dsetCount; i++) {
                XYSeriesCollection collection = (XYSeriesCollection) xyplot
                        .getDataset(i);
                int scount = collection.getSeriesCount();
                for (int j = 0; j < scount; j++) {
                    dsetIndex[count] = i;
                    count++;
                }
            }
        } else {
            logger.error("could not obtain series!");
        }

        series = new SeriesInfo[range.length];
        for (int i = 0; i < range.length; i++) {
            series[i] = new SeriesInfo(xyplot, i);
        }

        list = new JList(range);
        list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        JScrollPane scrPane = new JScrollPane(list);
        scrPane.setBorder(new TitledBorder("series"));
        scrPane.setPreferredSize(new Dimension(200, 150));

        cbapplytoall = new JCheckBox("apply changes to all series");

        prangetype.add(scrPane);
        prangetype.add(cbapplytoall);
        p.add(prangetype, constraints);

        String[] strplottype = { "lines", "shapes", "lines and shapes" };
        String[] plotnumber = { "1", "2", "3", "4", "5", "6", "7", "8", "9",
                "10" };
        JPanel pplottype = new JPanel();
        pplottype.setLayout(new BoxLayout(pplottype, BoxLayout.X_AXIS));
        comboplottype = new JComboBox(strplottype);
        JPanel pcomboplottype = new JPanel();
        pcomboplottype.setBorder(new TitledBorder("plot type"));
        pcomboplottype.add(comboplottype);

        btnplotlinecolor = new JButton("select");
        JPanel pbtnline = new JPanel();
        pbtnline.setBorder(new TitledBorder("color"));
        pbtnline.add(btnplotlinecolor);

        pplottype.add(pcomboplottype);
        pplottype.add(pbtnline);
        constraints.gridy = 1;
        p.add(pplottype, constraints);
        PlotShapesAndLines psal = new PlotShapesAndLines();
        StrokeSample[] sample = new StrokeSample[psal.getNumLines()];
        for (int i = 0; i < psal.getNumLines(); i++) {
            sample[i] = new StrokeSample(psal.getLine(i, 1.0f));
        }

        JPanel plineproperties = new JPanel();
        // comboplotlinetype = new JComboBox(plotnumber);
        comboplotlinetype = new JComboBox(sample);
        comboplotlinetype.setRenderer(new StrokeSample(new BasicStroke(1)));

        JPanel pcomboplotlinetype = new JPanel();
        pcomboplotlinetype.setBorder(new TitledBorder("line type"));
        pcomboplotlinetype.add(comboplotlinetype);
        tfplotlinewidth = new JTextField(10);
        JPanel ptfline = new JPanel();
        ptfline.setBorder(new TitledBorder("line width"));
        ptfline.add(tfplotlinewidth);

        plineproperties.setLayout(new GridLayout(1, 3));
        plineproperties.setBorder(new TitledBorder("line properties"));
        plineproperties.add(pcomboplotlinetype);
        plineproperties.add(ptfline);

        constraints.gridy = 2;
        p.add(plineproperties, constraints);

        JPanel pshapeproperties = new JPanel();
        ShapeSample[] shapesample = new ShapeSample[psal.getNumShapes()];
        for (int i = 0; i < shapesample.length; i++) {
            shapesample[i] = new ShapeSample(psal.getShape(i, 49, 9, 10.d));
        }
        // comboplotshapetype = new JComboBox(plotnumber);
        comboplotshapetype = new JComboBox(shapesample);
        comboplotshapetype.setRenderer(new ShapeSample(psal.getShape(0, 49, 9,
                10.d)));
        JPanel pcomboplotshapetype = new JPanel();
        pcomboplotshapetype.setBorder(new TitledBorder("shape type"));
        pcomboplotshapetype.add(comboplotshapetype);
        tfplotshapesize = new JTextField(10);
        JPanel ptf = new JPanel();
        ptf.setBorder(new TitledBorder("shape size"));
        ptf.add(tfplotshapesize);

        pshapeproperties.setLayout(new GridLayout(1, 3));
        pshapeproperties.setBorder(new TitledBorder("shape properties"));
        pshapeproperties.add(pcomboplotshapetype);
        pshapeproperties.add(ptf);

        constraints.gridy = 3;
        p.add(pshapeproperties, constraints);

        add(p, BorderLayout.NORTH);
        list.addListSelectionListener(new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                seriesChanged();
            }
        });

        cbapplytoall.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                apply_to_all = cbapplytoall.isSelected();
                seriesChanged();
            }
        });

        comboplottype.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                int index = list.getSelectedIndex();
                series[index].setPlotType(comboplottype.getSelectedIndex());
            }
        });

        btnplotlinecolor.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                int index = list.getSelectedIndex();
                Color color = JColorChooser.showDialog(thispanel, "Choose",
                        btnplotlinecolor.getBackground());
                if (color != null) {
                    btnplotlinecolor.setBackground(color);
                    btnplotlinecolor.revalidate();
                    series[index].setColor(color);
                }
            }
        });

        comboplotlinetype.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                int index = list.getSelectedIndex();
                series[index].setLineType(comboplotlinetype.getSelectedIndex());
            }
        });

        tfplotlinewidth.addCaretListener(new CaretListener() {
            public void caretUpdate(CaretEvent ce) {
                float linewidth = 0.f;
                try {
                    linewidth = Float.parseFloat(tfplotlinewidth.getText());
                } catch (NumberFormatException nfe) {
                    return;
                }
                series[list.getSelectedIndex()].setLineWidth(linewidth);
            }
        });

        comboplotshapetype.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                series[list.getSelectedIndex()].setShapeType(comboplotshapetype
                        .getSelectedIndex());
            }
        });

        tfplotshapesize.addCaretListener(new CaretListener() {
            public void caretUpdate(CaretEvent ce) {
                double shapesize = 0.d;
                try {
                    shapesize = Double.parseDouble(tfplotshapesize.getText());
                } catch (NumberFormatException nfe) {
                    return;
                }
                series[list.getSelectedIndex()].setShapeSize(shapesize);
            }
        });

        list.setSelectedIndex(0);
        tfplotlinewidth.setText(String.valueOf(series[0].getLineWidth()));
        tfplotshapesize.setText(String.valueOf(series[0].getShapeSize()));
    }

    public void plotChanged(Plot plot) {
        updateChart();
        init();
        initGUI();
        revalidate();
    }

    private void seriesChanged() {
        int index = list.getSelectedIndex();
        SeriesInfo info = series[index];
        btnplotlinecolor.setBackground(info.getColor());
        comboplottype.setSelectedIndex(info.getPlotType());
        comboplotlinetype.setSelectedIndex(info.getLineType());
        comboplotshapetype.setSelectedIndex(info.getShapeType());
        tfplotlinewidth.setText(String.valueOf(info.getLineWidth()));
        tfplotshapesize.setText(String.valueOf(info.getShapeSize()));
        doApplytoAll();
    }

    private void doApplytoAll() {
        if (apply_to_all) {
            for (int i = 0; i < series.length; i++) {
                series[i].copy(series[list.getSelectedIndex()]);
            }
        } else {
            int[] indeces = list.getSelectedIndices();
            int ind = list.getSelectedIndex();
            if (indeces == null || indeces.length == 0) {
                return;
            }
            for (int i = 0; i < indeces.length; i++) {
                if (ind == indeces[i]) {
                    continue;
                }
                series[indeces[i]].copy(series[ind]);
            }
        }
    }
}
