/*
 * (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.dynamic.dataset;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Observable;
import java.util.Observer;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.filechooser.FileFilter;

import com.artenum.cassandra.pipeline.PipeLineManager;
import com.artenum.cassandra.plugin.PlugInControlUI;

/**
 * <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, ARTENUM SARL 
 * 
 * @version 1.2
 */
public class DynamicDatasetControlUI extends PlugInControlUI implements Observer {
    private PipeLineManager pipeLineManager;

    // Base file
    private JTextField firstFileName;
    private JButton browse;
    private JSpinner step;

    // Control
    private JCheckBox searchForNextFile;
    private JCheckBox loop;

    // movie part
    private JLabel currentFileName;
    private JSlider slider;
    private JSpinner timeBetweenFrame;
    private JCheckBox play;
    private JCheckBox saveFile;
    private Timer timer;
    private Timer timerSearch;

    //
    private DynamicDatasetPlugin plugin;
    private File currentDirectory;

    /**
     * Defines the graphical interface of the control panel for the cutting plane plugin.
     * This method just defines the components and attach the action listener.
     * @param pipeLineManager
     * @param plugin
     */
    public DynamicDatasetControlUI(PipeLineManager pipeLineManager, DynamicDatasetPlugin plugin, Frame owner) {
        super(owner, "Dynamic dataset configuration panel");
        //
        this.pipeLineManager = pipeLineManager;
        this.plugin = plugin;
        //
        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
        //
        JPanel block = new JPanel();
        block.setLayout(new BoxLayout(block, BoxLayout.Y_AXIS));
        block.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.BLACK), "Setup"));
        getContentPane().add(block);
        firstFileName = new JTextField(((File) plugin.getVtkFileList().get(0)).getAbsolutePath());
        browse = new JButton("Browse");
        browse.setActionCommand("BROWSE");
        browse.addActionListener(this);

        JPanel line = new JPanel();
        line.setLayout(new BoxLayout(line, BoxLayout.X_AXIS));
        line.add(new JLabel("First file: "));
        line.add(firstFileName);
        line.add(browse);
        block.add(line);

        step = new JSpinner(new SpinnerNumberModel(1, 1, 1000, 1));
        line = new JPanel();
        line.setLayout(new BoxLayout(line, BoxLayout.X_AXIS));
        line.add(new JLabel("Step number between files: "));
        line.add(step);
        block.add(line);

        searchForNextFile = new JCheckBox("Search next file");
        searchForNextFile.setActionCommand("SEARCH_NEXT");
        searchForNextFile.addActionListener(this);
        loop = new JCheckBox("Loop");
        saveFile = new JCheckBox("Save image");

        // -------------       
        block = new JPanel();
        block.setLayout(new BoxLayout(block, BoxLayout.Y_AXIS));
        block.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.BLACK), "Movie"));
        getContentPane().add(block);

        line = new JPanel();
        line.setLayout(new BoxLayout(line, BoxLayout.X_AXIS));
        currentFileName = new JLabel(((File) plugin.getVtkFileList().get(0)).getName());
        line.add(new JLabel("Current file: "));
        line.add(currentFileName);
        line.add(Box.createHorizontalGlue());
        block.add(line);

        line = new JPanel();
        line.setLayout(new BoxLayout(line, BoxLayout.X_AXIS));
        timeBetweenFrame = new JSpinner(new SpinnerNumberModel(1000, 1000, 5000, 250));
        line.add(new JLabel("Number of ms between frame: "));
        line.add(timeBetweenFrame);
        block.add(line);

        slider = new JSlider(0, plugin.getVtkFileList().size() - 1);
        slider.addChangeListener(this);
        block.add(slider);

        play = new JCheckBox("Play");
        play.setActionCommand("PLAY");
        play.addActionListener(this);
        line = new JPanel();
        line.setLayout(new BoxLayout(line, BoxLayout.X_AXIS));
        line.add(searchForNextFile);
        line.add(loop);
        line.add(play);
        line.add(saveFile);
        block.add(line);

        JButton cancel = new JButton("Cancel");
        cancel.setActionCommand("CANCEL");
        cancel.addActionListener(this);

        //
        line = new JPanel();
        line.setLayout(new BoxLayout(line, BoxLayout.LINE_AXIS));
        line.add(Box.createHorizontalGlue());
        line.add(cancel);
        getContentPane().add(line);
        pack();
        Dimension size = getSize();
        size.setSize(size.getWidth() + 100, size.getHeight());
        setSize(size);
        setLocationRelativeTo(null);

        //
        plugin.addObserver(this);
    }

    /**
     * Performe the actions requested by the components (buttons, etc...)
     * of the control GUI of the plugin.
     * The actions are filtered on the keywords previously defined.
     * If needed and depending on the action, this method the relevant update method of the
     * plugin.
     */
    public void actionPerformed(ActionEvent e) {
        String command = e.getActionCommand();
        if (command.equals("PLAY")) {
            if (play.isSelected()) {
                // Start playing
                timer = new Timer();
                timer.schedule(new TimerTask() {
                        public void run() {
                            if (loop.isSelected() || ((slider.getValue() + 1) <= slider.getMaximum())) {
                                slider.setValue((slider.getValue() + 1) % (slider.getMaximum() + 1));
                            }
                        }
                    }, 0, ((Number) timeBetweenFrame.getValue()).longValue());
            } else {
                timer.cancel();
                timer = null;
            }
        }

        if (command.equals("CANCEL")) {
            this.dispose();
        }

        if (command.equals("SEARCH_NEXT")) {
            System.out.println("SEARCH_NEXT");
            if (searchForNextFile.isSelected()) {
                // Start searching
                timerSearch = new Timer();
                timerSearch.schedule(new TimerTask() {
                        public void run() {
                            searchNextFile();
                        }
                    }, 10, 5000);
            } else {
                timerSearch.cancel();
                timerSearch = null;
            }
        }

        if (command.equals("BROWSE")) {
            JFileChooser chooser = new JFileChooser(currentDirectory);
            chooser.setMultiSelectionEnabled(false);
            chooser.setFileFilter(new FileFilter() {
                    public boolean accept(File f) {
                        if (f.isDirectory() || f.getName().toLowerCase().endsWith(".vtk")) {
                            return true;
                        }

                        return false;
                    }

                    public String getDescription() {
                        return "Vtk files";
                    }
                });
            if (chooser.showOpenDialog(this) != JFileChooser.APPROVE_OPTION) {
                return;
            }

            currentDirectory = chooser.getSelectedFile().getParentFile();
            firstFileName.setText(chooser.getSelectedFile().getAbsolutePath());
            plugin.setFirstFile(chooser.getSelectedFile());
        }
    }

    public void setCurrentDirectory(File currentDirectory) {
        this.currentDirectory = currentDirectory;
    }

    public void searchNextFile() {
        File f = (File) plugin.getVtkFileList().get(plugin.getVtkFileList().size() - 1);
        ArrayList fileDecomposition = FileToolBox.splitNumbers(f.getName());

        // Check position of numbers
        StringBuffer currentPart = null;
        int numberPos = 0;
        ArrayList listOfNumberPos = new ArrayList();
        for (Iterator filePart = fileDecomposition.iterator(); filePart.hasNext();) {
            currentPart = (StringBuffer) filePart.next();
            if ((currentPart.charAt(0) >= '0') && (currentPart.charAt(0) <= '9')) {
                // number 
                listOfNumberPos.add(new Integer(numberPos));
            } else {
                // String
            }

            numberPos++;
        }

        int[] realNumberPos = new int[listOfNumberPos.size()];
        for (int i = 0; i < realNumberPos.length; i++)
            realNumberPos[i] = ((Integer) listOfNumberPos.get(i)).intValue();

        // search if files exists
        File fileToCheck = null;
        for (int i = 1; i <= 10; i++) {
            for (int j = 0; j < realNumberPos.length; j++) {
                StringBuffer fileToSearchFor = new StringBuffer();
                for (int k = 0; k < fileDecomposition.size(); k++) {
                    if (k == realNumberPos[j]) {
                        int length = ((StringBuffer) fileDecomposition.get(k)).length();
                        String number = Integer.toString((Integer.parseInt(((StringBuffer) fileDecomposition.get(k)).toString())) +
                                (((Number) step.getValue()).intValue() * i));
                        if (number.length() < length) {
                            // Fill with 0
                            for (int nbZ = 0; nbZ < (length - number.length()); nbZ++) {
                                fileToSearchFor.append("0");
                            }
                        }

                        fileToSearchFor.append(number);
                    } else {
                        fileToSearchFor.append((StringBuffer) fileDecomposition.get(k));
                    }
                }

                // Check if file exist !
                fileToCheck = new File(f.getParentFile(), fileToSearchFor.toString());
                if (fileToCheck.exists()) {
                    plugin.addVtkFile(fileToCheck);
                }
            }
        }
    }

    /**
     * slide bar listener. The update of the pipeline is directly performed
     * when the sldie bar is changed.
     */
    public void stateChanged(ChangeEvent e) {
        SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    File f = (File) plugin.getVtkFileList().get(slider.getValue());
                    currentFileName.setText(f.getName());
                    plugin.updateInputFile(f, saveFile.isSelected());
                }
            });
    }

    public boolean isSaveFileSelected() {
        return saveFile.isSelected();
    }

    public void update(Observable o, Object arg) {
        if (slider.getValue() > (plugin.getVtkFileList().size() - 1)) {
            slider.setValue(plugin.getVtkFileList().size() - 1);
        }

        slider.setMaximum(plugin.getVtkFileList().size() - 1);
    }

    public void itemStateChanged(ItemEvent arg0) {
        // TODO Auto-generated method stub
        
    }
}
