/*
 * (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 com.artenum.cassandra.pipeline.Filter;
import com.artenum.cassandra.pipeline.FilterImpl;
import com.artenum.cassandra.pipeline.PipeLineManager;
import com.artenum.cassandra.pipeline.RemoveListener;
import com.artenum.cassandra.pipeline.CassandraObject;
import com.artenum.cassandra.plugin.CassandraPlugInProperty;
import com.artenum.cassandra.plugin.CassandraPlugin;
import com.artenum.cassandra.plugin.PlugInControlUI;
import com.artenum.cassandra.plugin.PluginManager;

import vtk.vtkActor;
import vtk.vtkDataSetMapper;
import vtk.vtkDataSetReader;
import vtk.vtkLookupTable;
import vtk.vtkScalarBarActor;

import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import java.io.File;

import java.util.ArrayList;
import java.util.Observable;

import javax.swing.JFileChooser;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.filechooser.FileFilter;

/**
 * <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>
 *             This class defines the VTK processing pipeline itself
 *             and the initialisation of the contextuel GUI of 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 DynamicDatasetPlugin extends Observable implements CassandraPlugin, RemoveListener {
    // Cassandra elements
    private String name;
    private PipeLineManager pipelineManager;
    private PluginManager pluginManager;
    private JPopupMenu contextualMenu;

    // Contextual control GUI of the plugin
    private DynamicDatasetControlUI controlUI;

    // Vtk data
    private vtkDataSetReader dataSetVTK;
    private vtkDataSetMapper mapperVTK;
    private vtkActor actorVTK;
    private vtkLookupTable lookupTableVTK;
    private vtkScalarBarActor scalarBarVTK;
    private Filter filterImpl;

    // Pipeline VtkObjects
    private CassandraObject actor;
    private CassandraObject mapper;
    private CassandraObject dataset;
    private CassandraObject filter;

    // File manager
    private ArrayList<File> fileList;
    private File currentFile;

    /**
     * Main contructor and VTK pipeline definition.
     * @param pipelineManager is the central pipeline manager of Cassandra.
     * @param pluginManager is the central list of plugin instance, where a contextual menu access is given.
     */
    public DynamicDatasetPlugin(PipeLineManager pipelineManager, PluginManager pluginManager, Frame owner) {
        // Init default variable
        this.name = "Dynamic dataset";
        this.pipelineManager = pipelineManager;
        this.pluginManager = pluginManager;
        this.filterImpl = new FilterImpl();
        filterImpl.addRemoveListener(this);
        fileList = new ArrayList<File>();

        // Select list of files
        JFileChooser chooser = new JFileChooser();
        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(owner) != JFileChooser.APPROVE_OPTION) {
            return;
        }

        fileList.add(chooser.getSelectedFile());

        // Define and init the VTK pipeline
        dataSetVTK = new vtkDataSetReader();
        dataSetVTK.SetFileName(fileList.get(0).getAbsolutePath());
        dataSetVTK.Update();
        // Set pipeline
        mapperVTK = new vtkDataSetMapper();
        mapperVTK.SetInput(dataSetVTK.GetOutput());
        mapperVTK.Update();
        actorVTK = new vtkActor();
        actorVTK.SetMapper(mapperVTK);

        // Register vtkObject in pipeline
        pipelineManager.addDataSet(dataSetVTK.GetOutput(), "Dynamic");
        pipelineManager.addMapper(mapperVTK, "");

        // Show actors
        pipelineManager.setActorVisible(pipelineManager.addActor(actorVTK, "Dynamic"), true);

        // lookup table
        if (dataSetVTK.GetOutput().GetScalarRange() != null) {
            lookupTableVTK = new vtkLookupTable();
            lookupTableVTK.SetHueRange(0.66667, 0);
            lookupTableVTK.SetTableRange(dataSetVTK.GetOutput().GetScalarRange());
            lookupTableVTK.Build();
            mapperVTK.SetLookupTable(lookupTableVTK);
            mapperVTK.SetScalarRange(dataSetVTK.GetOutput().GetScalarRange());

            // Scalar bar
            scalarBarVTK = new vtkScalarBarActor();
            scalarBarVTK.SetLookupTable(lookupTableVTK);

            // register 
            pipelineManager.addLookupTable(lookupTableVTK, "Dynamic");
            pipelineManager.setActorVisible(pipelineManager.addScalarBar(scalarBarVTK, "Dynamic"), true);
        }

        // Load the result data in the Cassandra pipeline
        filter = pipelineManager.addFilter(filterImpl, "Dynamic dataset");
        filterImpl.getOutputDataSet().add(dataSetVTK.GetOutput());
        pipelineManager.notifyConnectivityChange(filter);

        // end of the VTK pipeline
        // Init all the control UI
        controlUI = new DynamicDatasetControlUI(pipelineManager, this, owner);
        controlUI.setCurrentDirectory(chooser.getSelectedFile().getParentFile());
        // Init contextual menu
        contextualMenu = new JPopupMenu("Movie menu");
        JMenuItem showControl = new JMenuItem("Show control");
        showControl.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    controlUI.setVisible(true);
                }
            });
        contextualMenu.add(showControl);
        contextualMenu.addSeparator();
        JMenuItem remove = new JMenuItem("Remove");
        remove.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    remove();
                }
            });
        contextualMenu.add(remove);
        filter.getMetaData().put(CassandraObject.POPUP_MENU, getContextualMenu());
    }

    public ArrayList getVtkFileList() {
        return fileList;
    }

    public void showNextFile() {
        File f = null;
        if (currentFile != null) {
            f = (File) getVtkFileList().get((fileList.indexOf(currentFile) + 1) % fileList.size());
        } else {
            f = (File) getVtkFileList().get(0);
        }

        updateInputFile(f, controlUI.isSaveFileSelected());
    }

    public void setFirstFile(File firstFile) {
        fileList.clear();
        fileList.add(firstFile);
        updateInputFile(firstFile, controlUI.isSaveFileSelected());
        setChanged();
        notifyObservers();
    }

    public void addVtkFile(File f) {
        fileList.add(f);
        setChanged();
        notifyObservers();
    }

    /**
     * Update the data in the defined pipeline
     */
    public void updateInputFile(final File vtkFile, final boolean saveFile) {
        if (!vtkFile.exists()) {
            System.out.println("File not exist: " + vtkFile);
            return;
        }

        currentFile = vtkFile;

        dataSetVTK.SetFileName(vtkFile.getAbsolutePath());
        dataSetVTK.Update();
        // Repaint view
        pipelineManager.validateViewAndGo();
        if (saveFile) {
            pipelineManager.getCassandraView().saveToJPG(vtkFile.getAbsolutePath() + ".jpg");
        }
    }

    /**
     * Default plugin interface
     */
    public String getName() {
        return name;
    }

    public JPopupMenu getContextualMenu() {
        return contextualMenu;
    }

    public void remove() {
        pluginManager.removePlugin(this);
        pipelineManager.removeVtkObject(actor);
        pipelineManager.removeVtkObject(mapper);
        pipelineManager.removeVtkObject(dataset);
        pipelineManager.removeVtkObject(filter);
    }

    /**
     * String printed in the plugin manager list
     */
    public String toString() {
        return getName();
    }
    
    public Filter getInternalFilter() {
        return filterImpl;
    }

    @Override
    public CassandraPlugInProperty getPlugInProperty() {
        // TODO Auto-generated method stub
        return null;
    }


    /**
     * return the control panel of the current plug-in. 
     */
    @Override
    public PlugInControlUI getControlUI() {
        return controlUI;
    }

    @Override
    public void initAndUpdate(CassandraPlugInProperty prop) {
        // TODO Auto-generated method stub
        
    }
}
