/*
 * (c) Copyright: Artenum SARL, 101-103 Boulevard Mac Donald,
 *                75019, Paris, France 2005.
 *                http://www.artenum.com
 *
 * License:
 *
 *  This program is free software; you can redistribute it
 *  and/or modify it under the terms of the Q Public License;
 *  either version 1 of the License.
 *
 *  This program is distributed in the hope that it will be
 *  useful, but WITHOUT ANY WARRANTY; without even the implied
 *  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 *  PURPOSE. See the Q Public License for more details.
 *
 *  You should have received a copy of the Q Public License
 *  License along with this program;
 *  if not, write to:
 *    Artenum SARL, 101-103 Boulevard Mac Donald,
 *    75019, PARIS, FRANCE, e-mail: contact@artenum.com
 */
package com.artenum.cassandra.plugin.isolevel;

import com.artenum.cassandra.pipeline.PipeLineManager;
import com.artenum.cassandra.pipeline.CassandraObject;
import com.artenum.cassandra.plugin.PlugInControlUI;
import com.artenum.cassandra.util.VtkObjectComboBoxModel;

import vtk.vtkDataSet;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;

import java.text.NumberFormat;

import java.util.Hashtable;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 * <pre>
 * <b>Project ref           :</b> CASSANDRA project
 * <b>Copyright and license :</b> See relevant sections
 * <b>Status                :</b> under development
 * <b>Creation              :</b> 04/03/2005
 * <b>Modification          :</b>
 *
 * <b>Description  :</b> Control panel for the plugin.
 *
 * </pre>
 * <table cellpadding="3" cellspacing="0" border="1" width="100%">
 * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"><td><b>Version number</b></td><td><b>Author (name, e-mail)</b></td><td><b>Corrections/Modifications</b></td></tr>
 * <tr><td>0.1</td><td>Sebastien Jourdain, jourdain@artenum.com</td><td>Creation</td></tr>
 * </table>
 *
 * @author        Sebastien Jourdain, ARTENUM SARL 
 * @author        Julien Forest, ARTENM SARL 
 * 
 * @version       1.2
 */
public class IsoLevelControlUI extends PlugInControlUI {
    // plugin data
    private PipeLineManager pipeLineManager;
    private IsoLevelPlugin plugin;
    private VtkObjectComboBoxModel datasetModel;

    // plugin ui
    private JComboBox inputDataset;
    private JFormattedTextField minRange;
    private JFormattedTextField maxRange;
    private JCheckBox computeNormal;
    private JTabbedPane levelType;

    // -> simple-level 
    private JSlider levelSlider;
    private JFormattedTextField levelValue;

    // -> multi-level 
    private JFormattedTextField nbLevel;

    public IsoLevelControlUI(PipeLineManager pipeLineManager, IsoLevelPlugin plugin, Frame owner) {
        super(owner, "Iso level configuration panel");
        this.pipeLineManager = pipeLineManager;
        this.plugin = plugin;
        datasetModel = new VtkObjectComboBoxModel(pipeLineManager.getDataSetList(), plugin.getOutputDataSet());

        // Dialog box
        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.PAGE_AXIS));

        // Input dataset
        JPanel line = new JPanel(new BorderLayout());
        line.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.BLACK, 1), "Input dataset"));
        inputDataset = new JComboBox(datasetModel);
        inputDataset.addActionListener(this);
        line.add(inputDataset, BorderLayout.CENTER);
        line.setMaximumSize(new Dimension(10000, inputDataset.getHeight()));
        getContentPane().add(line);

        // Vertical glue
        line = new JPanel(new BorderLayout());
        line.add(Box.createRigidArea(new Dimension(10, 10)), BorderLayout.NORTH);
        getContentPane().add(line);

        // Range
        line = new JPanel(new GridLayout(2, 2));
        line.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.BLACK, 1), "Range"));
        minRange = new JFormattedTextField("0");
        minRange.setValue(new Double(-1));
        maxRange = new JFormattedTextField("0");
        maxRange.setValue(new Double(1));
        line.add(new JLabel("Min"));
        line.add(new JLabel("Max"));
        line.add(minRange);
        line.add(maxRange);
        getContentPane().add(line);

        // Simple isolevel
        JPanel simpleIsoLevel = new JPanel(new BorderLayout());
        levelValue = new JFormattedTextField("0");
        levelValue.setValue(new Double(0));
        Hashtable label = new Hashtable();
        label.put(new Integer(0), new JLabel("0%"));
        label.put(new Integer(50), new JLabel("50%"));
        label.put(new Integer(100), new JLabel("100%"));
        levelSlider = new JSlider(0, 100, 50);
        levelSlider.setMinorTickSpacing(1);
        levelSlider.setMajorTickSpacing(10);
        levelSlider.setLabelTable(label);
        levelSlider.setPaintLabels(true);
        levelSlider.setPaintLabels(true);
        levelSlider.addChangeListener(this);
        levelSlider.setToolTipText("Move inside the range");
        simpleIsoLevel.add(levelValue, BorderLayout.NORTH);
        simpleIsoLevel.add(levelSlider, BorderLayout.CENTER);

        // Multi isolevel
        JPanel multiIsoLevel = new JPanel();
        multiIsoLevel.setLayout(new BoxLayout(multiIsoLevel, BoxLayout.Y_AXIS));
        line = new JPanel();
        line.setLayout(new BoxLayout(line, BoxLayout.X_AXIS));
        nbLevel = new JFormattedTextField(NumberFormat.getIntegerInstance());
        nbLevel.setValue(new Integer(10));
        line.add(new JLabel("Nb levels : "));
        line.add(nbLevel);
        line.add(Box.createVerticalGlue());
        multiIsoLevel.add(line);

        // Vertical glue
        line = new JPanel(new BorderLayout());
        line.add(Box.createRigidArea(new Dimension(10, 10)), BorderLayout.NORTH);
        getContentPane().add(line);

        // 2 type of isolevel
        levelType = new JTabbedPane();
        levelType.addTab("Simple iso-level", simpleIsoLevel);
        levelType.addTab("Multi iso-level", multiIsoLevel);
        getContentPane().add(levelType);

        // Vertical glue
        line = new JPanel(new BorderLayout());
        line.add(Box.createRigidArea(new Dimension(10, 10)), BorderLayout.NORTH);
        getContentPane().add(line);

        // cmd line
        line = new JPanel();
        computeNormal = new JCheckBox("Computes normals");
        JButton update = new JButton("Update");
        update.setActionCommand("UPDATE");
        update.addActionListener(this);
        JButton cancel = new JButton("Cancel");
        cancel.setActionCommand("CANCEL");
        cancel.addActionListener(this);
        line.setLayout(new BoxLayout(line, BoxLayout.LINE_AXIS));
        line.add(computeNormal);
        line.add(Box.createHorizontalGlue());
        line.add(update);
        line.add(cancel);
        getContentPane().add(line);

        pack();
        Dimension d = getSize();
        setSize(d.width, d.height);
        setLocationRelativeTo(null);
    }

    public void actionPerformed(ActionEvent e) {
        String command = e.getActionCommand();
        int levelFlag = 0;
        if (command.equals("UPDATE")) {
            if (inputDataset.getSelectedItem() != null) {
                levelFlag = levelType.getSelectedIndex();
                plugin.setControls(computeNormal.isSelected(), false);

                int nbLevelValue = ((Number) nbLevel.getValue()).intValue();
                double minValue = ((Number) minRange.getValue()).doubleValue();
                double maxValue = ((Number) maxRange.getValue()).doubleValue();

                //Upate the plug-in itself.
                plugin.updateIsoLevel((vtkDataSet) ((CassandraObject) datasetModel.getSelectedItem()).getVtkObject(), updateLevelValue(), nbLevelValue, levelFlag,
                    minValue, maxValue);
                pipeLineManager.validateViewAndGo();
            } else {
            	JOptionPane.showMessageDialog(new JFrame(),
            		    "Please select a valid input dataset.",
            		    "Input Filter Selection Error",
            		    JOptionPane.ERROR_MESSAGE);
            	return;
            }
        } else if (command.equals("CANCEL")) {
            this.dispose();
        } else if (datasetModel.getSelectedItem() != null) {
            // New input selection
            double[] range = ((vtkDataSet) ((CassandraObject) datasetModel.getSelectedItem()).getVtkObject()).GetScalarRange();
            if (range != null) {
                minRange.setValue(new Double(range[0]));
                maxRange.setValue(new Double(range[1]));
            }
        }
    }

    public void stateChanged(ChangeEvent e) {
        double level = updateLevelValue();
        if (inputDataset.getSelectedItem() != null) {
            int nbLevelValue = ((Number) nbLevel.getValue()).intValue();
            double minValue = ((Number) minRange.getValue()).doubleValue();
            double maxValue = ((Number) maxRange.getValue()).doubleValue();

            plugin.updateIsoLevel((vtkDataSet) ((CassandraObject) inputDataset.getSelectedItem()).getVtkObject(), level, 1, 0, minValue, maxValue);
            pipeLineManager.validateViewAndGo();
        }
    }

    /**
     * Select the index of the type of isolevel (i.e one or multi-isolevels) 
     * @param levelType, should 0 (simple) or 1 (multi).
     */
    public void setLevelType(int levelType){
        if (levelType >=0 && levelType < this.levelType.getTabCount()){
            this.levelType.setSelectedIndex(levelType);
        } else{
            System.out.println("Error, index not found. Set to one unique leve by default");
            this.levelType.setSelectedIndex(0);
        }
    }
    
    
    private double updateLevelValue() {
        double value = ((double) levelSlider.getValue());
        double minValue = ((Number) minRange.getValue()).doubleValue();
        double maxValue = ((Number) maxRange.getValue()).doubleValue();
        double step = (maxValue - minValue) / 100;
        double result = (value * step) + minValue;
        levelValue.setValue(new Double(result));
        return result;
    }

    public void itemStateChanged(ItemEvent arg0) {
        // TODO Auto-generated method stub
        
    }
    
    /**
     * set the selected input data set. 
     * @param selectedInput
     */
    public void setSelectedInput(CassandraObject selectedInput){
        if (selectedInput != null){
            inputDataset.getModel().setSelectedItem(selectedInput);
        } else {
            System.out.println("Selection is null");
        }
    }
}
