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

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.vtkDataSet;
import vtk.vtkDataSetMapper;
import vtk.vtkLookupTable;
import vtk.vtkScalarBarActor;
import vtk.vtkThreshold;

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

import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;

/**
 * <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
 * @author        Benoit Thiebault, ARTENUM SARL
 * @author        Jeremie Turbet, ARTENUM SARL
 * 
 * @version       1.2
 */
public class ThresholdPlugin implements CassandraPlugin, RemoveListener {
    public final static int THRESHOLD_BETWEEN = 1;
    public final static int THRESHOLD_LOWER = 2;
    public final static int THRESHOLD_UPPER = 3;

    //
    private String name;
    private PipeLineManager pipelineManager;
    private PluginManager pluginManager;
    private JPopupMenu contextualMenu;
    private ThresholdControlUI controlUI;
    private int nbUpdate = 0;

    // Vtk data
    private vtkDataSet lastDataSet;
    private vtkLookupTable lookupTable;
    private vtkScalarBarActor scalarBar;
    private vtkThreshold threshold;
    private vtkDataSetMapper thresholdVtkMapper;
    private vtkActor thresholdVtkActor;

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

    public ThresholdPlugin() {
        this.name = "Threshold";
        filterImpl = new FilterImpl();
    }

    public ThresholdPlugin(PipeLineManager pipelineManager, PluginManager pluginManager, Frame owner) {
        this();
        this.pipelineManager = pipelineManager;
        this.pluginManager = pluginManager;

        // Init control UI
        controlUI = new ThresholdControlUI(pipelineManager, this, owner);

        // Init contextual menu
        contextualMenu = new JPopupMenu("Threshold 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);

        // Init pipeline
        // Here write your processing pipeline
        threshold = new vtkThreshold();
        thresholdVtkMapper = new vtkDataSetMapper();
        thresholdVtkMapper.SetInput(threshold.GetOutput());

        //thresholdVtkMapper.SetLookupTable((vtkLookupTable) pipelineManager.getDefaultLookupTable().getVtkObject());
        thresholdVtkActor = new vtkActor();
        thresholdVtkActor.SetMapper(thresholdVtkMapper);

        // Build lookupTable
        lookupTable = new vtkLookupTable();
        lookupTable.SetHueRange(0.66667, 0);

        lookupTable.Build();
        thresholdVtkMapper.SetLookupTable(lookupTable);

        // Scalar bar
        vtkScalarBarActor scalBar = new vtkScalarBarActor();
        scalBar.SetLookupTable(lookupTable);

        //
        filterImpl.getOutputDataSet().add(threshold.GetOutput());
        filterImpl.addRemoveListener(this);

        //
        actor = pipelineManager.addActor(thresholdVtkActor, "Threshold");
        mapper = pipelineManager.addMapper(thresholdVtkMapper, "Threshold");
        dataset = pipelineManager.addDataSet(threshold.GetOutput(), "Threshold");
        filter = pipelineManager.addFilter(filterImpl, "Threshold");
        pipelineManager.addLookupTable(lookupTable, "Threshold");
        pipelineManager.addScalarBar(scalBar, "Threshold");
        //pipelineManager.setActorVisible(pipelineManager.addScalarBar(scalBar, "Threshold"), true);

        //
        filter.getMetaData().put(CassandraObject.POPUP_MENU, getContextualMenu());

        //
        actor.setValide(false);
        
        controlUI.setVisible(true);
    }

    public void updateThreshold(vtkDataSet inputDataSet, int thresholdType, double lowerLevel, double upperLevel) {
        if (inputDataSet != null) {
            threshold.SetInput(inputDataSet);
            switch (thresholdType) {
            case THRESHOLD_BETWEEN:
                threshold.ThresholdBetween(lowerLevel, upperLevel);
                break;
            case THRESHOLD_LOWER:
                threshold.ThresholdByLower(upperLevel);
                break;
            case THRESHOLD_UPPER:
                threshold.ThresholdByUpper(lowerLevel);
                break;
            }

            filterImpl.getInputDataSet().clear();
            filterImpl.getInputDataSet().add(inputDataSet);

            // Set the default actor visible by default
            //if ((nbUpdate++ == 0) && pipelineManager.getActorList().getData().contains(actor)) {
            if (pipelineManager.getActorList().getData().contains(actor)) {
                actor.setValide(true);
                pipelineManager.setActorVisible(actor, true);
            } else {
                pipelineManager.setActorVisible(actor, false);
            }
            // and we hide the actor corresponding to the source
            pipelineManager.hideInputActor(actor, inputDataSet);

            // Update mapper
            if (((lastDataSet == null) || !lastDataSet.equals(inputDataSet)) && thresholdVtkMapper.GetLookupTable().equals(lookupTable)) {
                thresholdVtkMapper.SetScalarRange(inputDataSet.GetScalarRange());
                lookupTable.SetTableRange(inputDataSet.GetScalarRange());
                lastDataSet = inputDataSet;
            }

            threshold.Update();
            threshold.GetOutput().UpdateData();
            pipelineManager.notifyConnectivityChange(filter);
        }
    }

    public String getName() {
        return name;
    }

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

    public JPopupMenu getContextualMenu() {
        return contextualMenu;
    }

    public String toString() {
        return getName();
    }

    public CassandraObject getOutputDataSet() {
        return dataset;
    }
    
    public Filter getInternalFilter() {
        return filterImpl;
    }

    @Override
    public PlugInControlUI getControlUI() {
        return controlUI;
    }

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

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