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

import com.artenum.cassandra.action.menu.RenameVtkObject;
import com.artenum.cassandra.pipeline.CascadeRemoveManager;
import com.artenum.cassandra.pipeline.PipeLineManager;
import com.artenum.cassandra.pipeline.CassandraObject;
import com.artenum.cassandra.util.VtkObjectInformationPane;

import vtk.vtkActor;
import vtk.vtkActor2D;

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

import java.util.Hashtable;

import javax.swing.Box;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JColorChooser;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButton;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 * <pre>
 * &lt;b&gt;Project ref           :&lt;/b&gt; CASSANDRA project
 * &lt;b&gt;Copyright and license :&lt;/b&gt; See relevant sections
 * &lt;b&gt;Status                :&lt;/b&gt; under development
 * &lt;b&gt;Creation              :&lt;/b&gt; 04/03/2005
 * &lt;b&gt;Modification          :&lt;/b&gt;
 * &lt;b&gt;Description  :&lt;/b&gt; Actor popup menu.
 * 
 * </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
 * @version 0.1
 */
public class ActorPopupMenu extends JPopupMenu implements ActionListener, ChangeListener, VtkObjectPopupMenu {
	// Actions
	public final static String ACTOR_SHOW = "actor.show";
	public final static String ACTOR_COLOR = "actor.color";
	public final static String ACTOR_REMOVE = "actor.remove";
	public final static String CHANG_REP = "actor.change.representation";
	public final static String SHOW_HIDE_EDGES = "actor.edge.status";
	public final static String EDGES_COLOR = "edges.color";

	public final static String ACTOR_REP_POINT = "Points";
	public final static String ACTOR_REP_WIREFRAME = "Wireframe";
	public final static String ACTOR_REP_SURFACE = "Surface";
	public final static String ACTOR_GET_INFO = "actor.get.info";

	private PipeLineManager pipeLineManager;
	private CascadeRemoveManager cascadeRemoveManager;
	private CassandraObject currentVtkObject;

	// UI components
	private JCheckBoxMenuItem viewActor;
	private JSlider actorOpacity;
	private JMenuItem actorColor;
	private RenameVtkObject actorRename;
	private JMenuItem actorGetInfo;
	private JMenuItem actorRemove;
	private JCheckBox edgesCheckBox;
	private ButtonGroup actorRepresentation;
	private JRadioButton pointButton;
	private JRadioButton surfaceButton;
	private JRadioButton wireframeButton;
	private JCheckBox backFaceCullingCheckBox;
	private JButton edgeColorButton;

	private double rEdge = 0.5;
	private double gEdge = 0.5;
	private double bEdge = 0.5;

	public ActorPopupMenu(PipeLineManager pipeLineManager, CascadeRemoveManager cascadeRemoveManager) {
		this.pipeLineManager = pipeLineManager;
		this.cascadeRemoveManager = cascadeRemoveManager;

		// Init popup with its ui components
		viewActor = new JCheckBoxMenuItem("Visible");
		viewActor.setActionCommand(ACTOR_SHOW);
		viewActor.addActionListener(this);

		actorColor = new JMenuItem("Actor color");
		actorColor.setActionCommand(ACTOR_COLOR);
		actorColor.addActionListener(this);

		actorOpacity = new JSlider(0, 50, 50);
		actorOpacity.addChangeListener(this);
		Hashtable label = new Hashtable();
		label.put(new Integer(0), new JLabel("0%"));
		label.put(new Integer(50), new JLabel("100%"));
		label.put(new Integer(25), new JLabel("50%"));
		actorOpacity.setMinorTickSpacing(1);
		actorOpacity.setMajorTickSpacing(5);
		actorOpacity.setLabelTable(label);
		actorOpacity.setPaintLabels(true);
		actorOpacity.setPaintLabels(true);

		actorRename = new RenameVtkObject("Rename", "Rename actor", null);

		// menuItem to get information about the selected actor
		actorGetInfo = new JMenuItem("Get information");
		actorGetInfo.setActionCommand(ACTOR_GET_INFO);
		actorGetInfo.addActionListener(this);

		actorRemove = new JMenuItem("Remove");
		actorRemove.setActionCommand(ACTOR_REMOVE);
		actorRemove.addActionListener(this);

		// set if the edges of mesh elements are represented or not
		Box edgesBox = Box.createHorizontalBox();

		edgesCheckBox = new JCheckBox("show edges");
		edgesCheckBox.addChangeListener(this);
		edgesCheckBox.setActionCommand(SHOW_HIDE_EDGES);
		edgesBox.add(edgesCheckBox);

		edgeColorButton = new JButton("Edges color");
		edgeColorButton.addActionListener(this);
		edgeColorButton.setActionCommand(EDGES_COLOR);
		edgesBox.add(edgeColorButton);

		// management of the actor representation
		actorRepresentation = new ButtonGroup();
		pointButton = new JRadioButton(ACTOR_REP_POINT);
		actorRepresentation.add(pointButton);
		pointButton.addChangeListener(this);
		surfaceButton = new JRadioButton(ACTOR_REP_SURFACE);
		actorRepresentation.add(surfaceButton);
		surfaceButton.addChangeListener(this);
		wireframeButton = new JRadioButton(ACTOR_REP_WIREFRAME);
		actorRepresentation.add(wireframeButton);
		wireframeButton.addChangeListener(this);
		Box representationMenu = Box.createVerticalBox();
		representationMenu.add(new JLabel("Represent as:"));
		representationMenu.add(pointButton);
		representationMenu.add(surfaceButton);
		representationMenu.add(wireframeButton);

		// management of the back face culling
		backFaceCullingCheckBox = new JCheckBox("set back face culling");
		backFaceCullingCheckBox.addChangeListener(this);

		//
		add(viewActor);
		add(actorOpacity);
		addSeparator();
		// add(edgesCheckBox);
		add(edgesBox);
		addSeparator();
		add(representationMenu);
		add(backFaceCullingCheckBox);
		addSeparator();
		add(actorColor);
		addSeparator();
		add(actorRename);
		add(actorGetInfo);
		addSeparator();
		add(actorRemove);
	}

	/**
	 * Set the current VtkObject
	 */
	public void setCurrentVtkOject(CassandraObject currentVtkObject) {
		this.currentVtkObject = currentVtkObject;
		actorRename.setVtkObject(currentVtkObject);
		// init popup with current vtkObject
		actorColor.setEnabled(currentVtkObject.getVtkObject() instanceof vtkActor);
		if (currentVtkObject.getVtkObject() instanceof vtkActor) {
			actorOpacity.setValue((int) (((vtkActor) currentVtkObject.getVtkObject()).GetProperty().GetOpacity() * 50));
		}

		if (currentVtkObject.getVtkObject() instanceof vtkActor2D) {
			actorOpacity.setValue((int) (((vtkActor2D) currentVtkObject.getVtkObject()).GetProperty().GetOpacity() * 50));
		}

		if (currentVtkObject.getMetaData().get(CassandraObject.ACTOR_VISIBLE) == null) {
			viewActor.setSelected(false);
		} else {
			viewActor.setSelected(((String) currentVtkObject.getMetaData().get(CassandraObject.ACTOR_VISIBLE)).equals("true"));
		}
	}

	/**
	 * Action method of the listener related to the actor popup menu.
	 */
	public void actionPerformed(ActionEvent e) {
		String command = e.getActionCommand();
		if (command.equals(ACTOR_SHOW)) {
			pipeLineManager.setActorVisible(currentVtkObject, viewActor.isSelected());
		} else if (command.equals(ACTOR_COLOR)) {
			Color c = JColorChooser.showDialog(this, "Actor color", Color.BLACK);
			if (c != null) {
				double r = ((float) c.getRed()) / 255;
				double g = ((float) c.getGreen()) / 255;
				double b = ((float) c.getBlue()) / 255;

				if (currentVtkObject.getVtkObject() instanceof vtkActor) {
					((vtkActor) currentVtkObject.getVtkObject()).GetProperty().SetColor(r, g, b);
				}

				((vtkActor) currentVtkObject.getVtkObject()).ApplyProperties();
			}

		} else if (command.equals(ACTOR_GET_INFO)) {
			VtkObjectInformationPane infoPane = new VtkObjectInformationPane(currentVtkObject);
			infoPane.showMessageDialog();

		} else if (command.equals(ACTOR_REMOVE)) {
			cascadeRemoveManager.removeActor(currentVtkObject);

		} else if (command.equals(EDGES_COLOR)) {
			// JColorChooser chooser = new JColorChooser();
			// chooser.setFocusable(true);
			// Color c = chooser.showDialog(this, "Actor color", Color.BLACK);
			Color c = JColorChooser.showDialog(this, "Actor color", Color.BLACK);

			if (c != null) {

				rEdge = ((float) c.getRed()) / 255;
				gEdge = ((float) c.getGreen()) / 255;
				bEdge = ((float) c.getBlue()) / 255;

				if (currentVtkObject.getVtkObject() instanceof vtkActor) {
					((vtkActor) currentVtkObject.getVtkObject()).GetProperty().SetEdgeColor(rEdge, gEdge, bEdge);
				}
			}

		}

		// ((vtkActor)
		// currentVtkObject.getVtkObject()).GetProperty().SetInterpolationToFlat();
		// ((vtkActor)
		// currentVtkObject.getVtkObject()).GetProperty().SetInterpolationToGouraud();
		// ((vtkActor)
		// currentVtkObject.getVtkObject()).GetProperty().SetInterpolationToPhong();

		// ((vtkActor)
		// currentVtkObject.getVtkObject()).GetProperty().SetPointSize(id0);

		// ((vtkActor) currentVtkObject.getVtkObject()).ApplyProperties();

		pipeLineManager.validateViewAndGo();
	}

	public void stateChanged(ChangeEvent e) {
		if (currentVtkObject.getVtkObject() instanceof vtkActor) {
			((vtkActor) currentVtkObject.getVtkObject()).GetProperty().SetOpacity(((double) actorOpacity.getValue()) / 50);

			if (edgesCheckBox.isSelected()) {
				((vtkActor) currentVtkObject.getVtkObject()).GetProperty().SetEdgeColor(rEdge, gEdge, bEdge);
				((vtkActor) currentVtkObject.getVtkObject()).GetProperty().SetEdgeVisibility(1);
			} else {
				((vtkActor) currentVtkObject.getVtkObject()).GetProperty().SetEdgeVisibility(0);
			}

			if (backFaceCullingCheckBox.isSelected()) {
				((vtkActor) currentVtkObject.getVtkObject()).GetProperty().SetBackfaceCulling(1);
			} else {
				((vtkActor) currentVtkObject.getVtkObject()).GetProperty().SetBackfaceCulling(0);
			}

			if (pointButton.isSelected()) {
				((vtkActor) currentVtkObject.getVtkObject()).GetProperty().SetRepresentationToPoints();
			} else if (wireframeButton.isSelected()) {
				((vtkActor) currentVtkObject.getVtkObject()).GetProperty().SetRepresentationToWireframe();
			} else if (surfaceButton.isSelected()) {
				((vtkActor) currentVtkObject.getVtkObject()).GetProperty().SetRepresentationToSurface();
			}

			((vtkActor) currentVtkObject.getVtkObject()).ApplyProperties();

		} else if (currentVtkObject.getVtkObject() instanceof vtkActor2D) {
			((vtkActor2D) currentVtkObject.getVtkObject()).GetProperty().SetOpacity(((double) actorOpacity.getValue()) / 50);
		}

		pipeLineManager.validateViewAndGo();
	}

	public JMenuItem getActorColorMenuItem() {
		return actorColor;
	}

	public JSlider getActorOpacityMenuItem() {
		return actorOpacity;
	}

	public JMenuItem getActorRemoveMenuItem() {
		return actorRemove;
	}

	public JMenuItem getActorRenameMenuItem() {
		return actorRename;
	}

	public JCheckBoxMenuItem getActorVisibleMenuItem() {
		return viewActor;
	}
}
