package battery.graph;

import java.util.*;

import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;

import vtk.vtkFloatArray;

import clustering.kmeans.DataPoint;
import endu.*;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseListener;
import java.io.File;
import java.util.Arrays;
import battery.utility.*;

public class GraphPanel extends WizardPanel implements ExactConstants {
	private ExactModel model;
	private WhatIfPlot graph;
	private JComboBox index;
	private boolean forcedUpdate = false;
	private LinesTable table;
	private JScrollPane tableScrollPane;
	final static Dimension DIM_SPINNER = new Dimension(60, 25);
	private String currentIndex = "none";
	private int[] classes;
	private int[] stations;
	private int[] stations2;
	JComboBox stationsCombo2 = new JComboBox();
	JComboBox uStationsCombo2 = new JComboBox();
	public static int loop = 0;
	public static int times = 0;
	private static final String AGGREGATE = "<html><b><i>Aggregate</i></b></html>";
	public static JSpinner Xmin, Xmax, Ymin, Ymax;
/**Pham declaration*******************************************	 */
	private JPanel clTop;
	private JPanel clLeft;
	private JPanel clRight;
	private JTextField clKValue = new JTextField("3", 20);
	private JTextField clLoops = new JTextField("10", 20);
	private JLabel clKValuelbl = new JLabel("Number of Clusters:");
	private JLabel clLoopslbl = new JLabel("Maximum iterations:");
	private JComboBox clCmbloopIndex;
	private JPanel clPnlLoopIndex;
	private JLabel clLblLoopIndex = new JLabel("Choose a time: ");
	static clustering.kmeans.JCA jca;

/** VTK  Declaration ********************************************************************************************/
	private JPanel mainPanel;
	private JPanel left;
	public static JPanel right = new JPanel(new BorderLayout(1, 1));
	private JButton clBtnPrev = new JButton("Zoom out       (-)");
	private JButton clBtnNext = new JButton("Zoom in         (+)");
	private JButton scaleXYDown = new JButton("Scale XY       (-)");
	private JButton scaleXYUp = new JButton("Scale XY       (+)");
	private JButton scaleDepthDown = new JButton("Scale Depth (-)");
	private JButton scaleDepthUp = new JButton("Scale Depth (+)");
	public static JSpinner Zoom, XY, Depth, cameraX, cameraY, cameraZ, focalX, focalY, focalZ, DataRadius, DataReduction, MissingValue;
	public static JSpinner X1, X2, X3; 
	
	
	
	public static JSpinner simSpeed;
	private JButton view = new JButton("View mission  ");
	public static JButton surfaceButton = new JButton("Hide   surface   ");
	public static boolean surfaceState = true;
	public static JButton cutButton = new JButton("Show   slice   ");
	public static boolean cutState = false;
	
	public static JButton openButton;
	public static JFileChooser fc;
	public static JTextField TextF = new JTextField("", 30);
	
	
/**************************************************************************************	 */

	public GraphPanel() {
		this.model = new ExactModel();
		initGraphics();
	}

	private void initGraphics() {
		setLayout(new BorderLayout(10, 10));
		setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
		mainPanel = new JPanel(new BorderLayout(5, 5));
		mainPanel.setBorder(BorderFactory.createEtchedBorder());		
/** Pham Code ****************************************************************/
		clTop = new JPanel(new BorderLayout(1, 1));
		clTop.setLayout(new FlowLayout());
		this.clLeft = new JPanel(new BorderLayout(1, 2));
		this.clRight = new JPanel(new BorderLayout(1, 2));

		this.clLeft.add(this.clKValuelbl, BorderLayout.WEST);
		this.clLeft.add(this.clKValue, BorderLayout.CENTER);

		this.clRight.add(this.clLoopslbl, BorderLayout.WEST);
		this.clRight.add(this.clLoops, BorderLayout.CENTER);

		this.clCmbloopIndex = new JComboBox();
		this.clPnlLoopIndex = new JPanel();
		this.clPnlLoopIndex.add(this.clLblLoopIndex, BorderLayout.WEST);
		this.clPnlLoopIndex.add(this.clCmbloopIndex, BorderLayout.CENTER);

		this.clTop.add(this.clLeft, BorderLayout.WEST);
		this.clTop.add(this.clRight, BorderLayout.CENTER);
		this.clTop.add(this.clPnlLoopIndex, BorderLayout.EAST);
	//	this.clPnlLoopIndex.add(this.clBtnView, BorderLayout.WEST);
	//	this.clPnlLoopIndex.add(this.clBtnPrev, BorderLayout.CENTER);
	//	this.clPnlLoopIndex.add(this.clBtnNext, BorderLayout.EAST);

/**  Add action listener ****************************************************************/		
		NextPrev objNextPrev = new NextPrev();
		this.scaleXYDown.addActionListener(objNextPrev);
		this.scaleXYUp.addActionListener(objNextPrev);
		this.scaleDepthDown.addActionListener(objNextPrev);
		this.scaleDepthUp.addActionListener(objNextPrev);
		this.clBtnNext.addActionListener(objNextPrev);
		this.clBtnPrev.addActionListener(objNextPrev);
		
		
		
		left = new JPanel(new BorderLayout(4, 4));		
		index = new JComboBox(ExactModel.INDICES_TYPES);
		//indexPanel.add(index);
			
//CONTROL PANEL ***********************************************************
		JPanel boundsPanel = new JPanel(new GridLayout(6, 1));
		controlListener control = new controlListener();
		planeListener planeLis = new planeListener();
		viewListener viewLis = new viewListener();
		
		JPanel flowPanel0 = new JPanel();
		flowPanel0.setLayout(new FlowLayout());
		JPanel flowPanel1 = new JPanel();
		flowPanel1.setLayout(new FlowLayout());
		JPanel flowPanel2 = new JPanel();
		flowPanel2.setLayout(new FlowLayout());
		JPanel flowPanel3 = new JPanel();
		flowPanel3.setLayout(new FlowLayout());
		JPanel flowPanel4 = new JPanel();
		flowPanel4.setLayout(new FlowLayout());
		
		JPanel flowP = new JPanel();
		flowP.setLayout(new FlowLayout());
		JPanel flowCut = new JPanel();
		flowCut.setLayout(new FlowLayout());
		
		fc = new JFileChooser();
		openButton = new JButton("Open a File...");
		openButton.addActionListener(viewLis);
		flowPanel0.add(this.TextF);
		flowPanel0.add(openButton);
		
		flowPanel1.add(new JLabel(" Data Radius:", JLabel.RIGHT));  //12
		DataRadius = new JSpinner(new SpinnerNumberModel(EnduModel.radius, 0.0, 1.0, 0.005));
		DataRadius.setPreferredSize(DIM_SPINNER);
		flowPanel1.add(DataRadius);
		this.DataRadius.addChangeListener(control);
		
		flowPanel1.add(new JLabel(" Data Reduction:", JLabel.RIGHT)); //15
		DataReduction = new JSpinner(new SpinnerNumberModel(EnduModel.dataReduction2, 1, 100, 4));
		DataReduction.setPreferredSize(DIM_SPINNER);
		flowPanel1.add(DataReduction);
		this.DataReduction.addChangeListener(control);
		
		flowPanel1.add(new JLabel(" Missing Value:", JLabel.RIGHT)); //14
		JLabel j;
		MissingValue = new JSpinner(new SpinnerNumberModel(EnduModel.missingValue, -10000, 10000, 1));
		MissingValue.setPreferredSize(DIM_SPINNER);
		flowPanel1.add(MissingValue);
		this.MissingValue.addChangeListener(control);
		
		
		double[] vector = EnduModel.camera.GetPosition();// new

		flowPanel2.add(new JLabel("    Camera X:", JLabel.RIGHT));
		cameraY = new JSpinner(new SpinnerNumberModel(vector[1], -1000, 1000, 0.1));
		cameraY.setPreferredSize(DIM_SPINNER);
		flowPanel2.add(cameraY);
		
		flowPanel2.add(new JLabel("            Camera Y:", JLabel.RIGHT));
		cameraX = new JSpinner(new SpinnerNumberModel(vector[0], -1000, 1000, 0.1));
		cameraX.setPreferredSize(DIM_SPINNER);
		flowPanel2.add(cameraX);
		
		flowPanel2.add(new JLabel("        Camera Z:", JLabel.RIGHT));
		cameraZ = new JSpinner(new SpinnerNumberModel(vector[2], -1000, 1000, 0.1));
		cameraZ.setPreferredSize(DIM_SPINNER);
		flowPanel2.add(cameraZ);
			
		this.cameraX.addChangeListener(control);
		this.cameraY.addChangeListener(control);
		this.cameraZ.addChangeListener(control);
	    
	    double[] focal = EnduModel.camera.GetFocalPoint();// new

	    flowPanel3.add(new JLabel("        Focal X:", JLabel.RIGHT));
		focalX = new JSpinner(new SpinnerNumberModel(focal[0], -1000, 1000, 0.1));
		focalX.setPreferredSize(DIM_SPINNER);
		flowPanel3.add(focalX);
		
		flowPanel3.add(new JLabel("                 Focal Y:", JLabel.RIGHT));
		focalY = new JSpinner(new SpinnerNumberModel(focal[1], -1000, 1000, 0.1));
		focalY.setPreferredSize(DIM_SPINNER);
		flowPanel3.add(focalY);
		
		flowPanel3.add(new JLabel("            Focal Z:", JLabel.RIGHT));
		focalZ = new JSpinner(new SpinnerNumberModel(focal[2], -1000, 1000, 0.1));
		focalZ.setPreferredSize(DIM_SPINNER);
		flowPanel3.add(focalZ);
	
		this.focalX.addChangeListener(control);
		this.focalY.addChangeListener(control);
		this.focalZ.addChangeListener(control);
		
		double step= 0.2;
		flowP.add(new JLabel("Depth Point 1:", JLabel.RIGHT));
		X1 = new JSpinner(new SpinnerNumberModel(0, -1000, 1000,  step));
		X1.setPreferredSize(DIM_SPINNER);
		flowP.add(X1);
		X1.addChangeListener(planeLis);
		
		flowP.add(new JLabel("  Depth Point 2:", JLabel.RIGHT));
		X2 = new JSpinner(new SpinnerNumberModel(0, -1000, 1000,  step));
		X2.setPreferredSize(DIM_SPINNER);
		Color c2= new Color(255,50,0);
		X2.setBackground(c2);
		flowP.add(X2);
		X2.addChangeListener(planeLis);
		
		flowP.add(new JLabel("  Depth Point 3:", JLabel.RIGHT));
		X3 = new JSpinner(new SpinnerNumberModel(0, -1000, 1000,  step));
		X3.setPreferredSize(DIM_SPINNER);
		flowP.add(X3);
		X3.addChangeListener(planeLis);
			
		flowPanel4.add(cutButton);
		cutButton.setText("Show   slice   ");
		Color c1 = new Color(0,255,0);
		cutButton.setBackground(c1);
		flowCut.add(cutButton);
		cutButton.addActionListener(viewLis);
		
		boundsPanel .add(flowPanel0);
		boundsPanel .add(flowPanel1);
		boundsPanel .add(flowPanel2);
		boundsPanel .add(flowPanel3);
		boundsPanel .add(flowP);	
		boundsPanel.add(flowCut);
		left.add(boundsPanel, BorderLayout.CENTER);
	    
//CONTROL PANEL 2 ***********************************************************
	    
	    
	    JPanel controlPanel = new JPanel();
		controlPanel.setLayout(new GridLayout(4,1));
		
		JPanel panel0 = new JPanel();
		panel0.setLayout(new FlowLayout());
		Zoom = new JSpinner(new SpinnerNumberModel(EnduModel.zoomStep, 0, 2, 0.2));
		Zoom.setPreferredSize(DIM_SPINNER);
		panel0.add(new JLabel("Factor:", JLabel.RIGHT));
		panel0.add(Zoom);
		panel0.add(clBtnPrev);
		panel0.add(clBtnNext);
		controlPanel.add(panel0);
		
		JPanel panel1 = new JPanel();
		panel1.setLayout(new FlowLayout());
		XY = new JSpinner(new SpinnerNumberModel(1.2, 1.0, 100, 0.2));
		XY.setPreferredSize(DIM_SPINNER);
		panel1.add(new JLabel("Factor:", JLabel.RIGHT));
		panel1.add(XY);
		panel1.add(scaleXYDown);
		panel1.add(scaleXYUp);
		controlPanel.add(panel1);
		
		JPanel panel2 = new JPanel();
		panel2.setLayout(new FlowLayout());
		Depth = new JSpinner(new SpinnerNumberModel(1.2, 1.0, 100, 0.1));
		Depth.setPreferredSize(DIM_SPINNER);
		panel2.add(new JLabel("Factor:", JLabel.RIGHT));
		panel2.add(Depth);
		panel2.add(scaleDepthDown);
		panel2.add(scaleDepthUp);
		controlPanel.add(panel2);
	
		flowPanel4.add(new JLabel("Speed:", JLabel.RIGHT));
		simSpeed = new JSpinner(new SpinnerNumberModel(4, 1, 100, 1));
		simSpeed.setPreferredSize(DIM_SPINNER);
		flowPanel4.add(simSpeed);
		
		flowPanel4.add(view);
		flowPanel4.add(surfaceButton);
		surfaceButton.setText("Hide   surface   ");
		Color cc = new Color(255,50,0);
		surfaceButton.setBackground(cc);
		
		this.view.addActionListener(viewLis);	
		this.surfaceButton.addActionListener(viewLis);	
		controlPanel.add(flowPanel4);
		
		
	
		
		left.add(controlPanel, BorderLayout.SOUTH);
		

// *****************************XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
		graph = new WhatIfPlot(Battery.datetime2[0]);
		classes = new int[graph.getColors().length];
		if (model.isMultiClass()) // If model is single-class, select first
			// class by default
			Arrays.fill(classes, -10);
		stations = new int[graph.getColors().length];
		stations2 = new int[graph.getColors().length];
		Arrays.fill(stations, -10);
		Arrays.fill(stations2, -10);
		table = new LinesTable();
		tableScrollPane = new JScrollPane(table);
		tableScrollPane.setPreferredSize(new Dimension(160, 280));
// *****************************XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

		right.add(Main.panel, BorderLayout.CENTER);
		MouseMotionExample m =new MouseMotionExample();
		EnduModel.renWin.addMouseMotionListener(m);

		MouseEvent2 m2 =new MouseEvent2();
		EnduModel.renWin.addMouseListener(m2);
		add(mainPanel, BorderLayout.CENTER);
//		/mainPanel.add(clTop, BorderLayout.NORTH);
		mainPanel.add(left, BorderLayout.WEST);
		mainPanel.add(right, BorderLayout.CENTER);
		addActions();
		updateIndex();
	}


	/**
	 * Updates values in spinners used to select ranges to be shown in graph
	 */
	private void updateSpinners() {
		// Check for special value used if graph is empty
	}

	/**
	 * This function must be called each time selected performance index changes
	 */
	private void updateIndex() {
		String current = (String) index.getSelectedItem();
		if (!current.equals(currentIndex)) {
			currentIndex = current;

			if (currentIndex.equals(AGGREGATE_TYPES[0])
					|| currentIndex.equals(AGGREGATE_TYPES[1])) {
				updateRecursive();
			} else {
				updateGreedy();
			}

			if (currentIndex.equals(AGGREGATE_TYPES[0])) {
				tableScrollPane.setVisible(true);
				// Removes incorrect utilization measures
				if (table.getCellEditor() != null)
					table.getCellEditor().stopCellEditing();

				table.repaint();
				table.repaint();
				paintAllIndices();

			}

			else if (currentIndex.equals(AGGREGATE_TYPES[2])) {
				tableScrollPane.setVisible(true);
				// Removes incorrect utilization measures
				if (table.getCellEditor() != null)
					table.getCellEditor().stopCellEditing();

				table.repaint();
				table.repaint();
				paintAllIndices();
				/*
				 * for (loop = 0; loop < GraphPanel.jca.getLoopsNumber();
				 * loop++) { try { Thread.sleep(1000); paintAllIndices();
				 * graph.repaint(); } catch (InterruptedException e) {
				 * System.err.println("InterruptedException Thread.Sleep"); } }
				 * loop = 0;
				 */}

			else {
				tableScrollPane.setVisible(true);
				// Removes incorrect utilization measures
				if (table.getCellEditor() != null)
					table.getCellEditor().stopCellEditing();
				/*
				 * if (currentIndex.equals(ExactModel.INDICES_TYPES[0])) { for
				 * (int i=0; i<stations.length; i++) if (stations[i] == -1)
				 * stations[i] = -2; }
				 */
				table.repaint();
				table.repaint();
				paintAllIndices();
			}

				}
	}

	/**
	 * Adds action listeners to GUI components
	 */
	private void addActions() {
		// Listener used for bounds spinners
		ChangeListener boundsListener = new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				if (!forcedUpdate) {
					updateSpinners();
				}
			}
		};
		XY.addChangeListener(boundsListener);
		Depth.addChangeListener(boundsListener);
		Zoom.addChangeListener(boundsListener);
		// Listener for index selection comboBox
		index.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				updateIndex();
			}
		});

		// Adds a listener to the graph to detect zoom events
		graph.addRescaleListener(new WhatIfPlot.RescaleListener() {
			public void Rescaled() {
				forcedUpdate = true;
				updateSpinners();
				forcedUpdate = false;
			}
		});
	}

	/**
	 * Paints performance index at specified row
	 * 
	 * @param rowNum
	 *            row number of index to be painted
	 */
	private void paintIndexAtRow(int rowNum) {
		int group = stations[rowNum]+1;
		left.add(tableScrollPane, BorderLayout.NORTH);
		mainPanel.updateUI();

		if (group == -1) {
			util.removeMeasure(rowNum);
			util.updateVTK();
		} else if (group>= 0) {
			util.addMeasure(group, rowNum);
			util.updateVTK();
		}
	}
		

	private void paintAllIndices() {
		// System.out.println("paintAllIndices() loop:" + loop);
		for (int i = 0; i < classes.length; i++)
			paintIndexAtRow(i);
	}

	
	/**
	 * @return the panel's name
	 */
	public String getName() {
		return "";
	}

	/**
	 * Table used to select performance indices to be drawn
	 */
	protected class LinesTable extends JTable {
		/** ComboBoxes used as cell editors */
		private ComboEditor classEditor, stationsEditor, uStationsEditor;

		/**
		 * Builds a new LinesTable
		 */
		public LinesTable() {
			super(new LinesTableModel());
			setDefaultRenderer(Color.class, new ColorCellEditor());
			setDefaultRenderer(String.class, ComboBoxCellEditor
					.getRendererInstance());
			// Sets column sizes
			getColumnModel().getColumn(0).setMaxWidth(100);
			getColumnModel().getColumn(1).setPreferredWidth(00);
			getColumnModel().getColumn(2).setPreferredWidth(150);
			setRowHeight(18);

			// Creates class editors (one is for utilizations)
			JComboBox classCombo = new JComboBox();
			// Null elements
			classCombo.addItem("");
			// Aggregate measures
			classCombo.addItem(AGGREGATE);
			for (int i = 0; i < model.getClasses(); i++) {
				classCombo.addItem(model.getClassNames()[i]);
			}

			// Creates station editor
			JComboBox stationsCombo = new JComboBox();
			JComboBox uStationsCombo = new JComboBox();
			stationsCombo.addItem("");
			uStationsCombo.addItem("");

			stationsCombo.addItem("Conductivity (S/m)");
			uStationsCombo.addItem("Conductivity (S/m)");
			stationsCombo.addItem("Temperature (C)");
			uStationsCombo.addItem("Temperature (C)");
			stationsCombo.addItem("CDOM (ru)");
			uStationsCombo.addItem("CDOM (ru)");
			stationsCombo.addItem("Chl-a (ru)");
			uStationsCombo.addItem("Chl-a (ru)");
			stationsCombo.addItem("REDOX (meV)");
			uStationsCombo.addItem("REDOX (meV)");
			stationsCombo.addItem("PAR (umol/m^2*s^1)");
			uStationsCombo.addItem("PAR (umol/m^2*s^1)");
			stationsCombo.addItem("pH");
			uStationsCombo.addItem("pH");
			stationsCombo.addItem("Turbidity (ru)");
			uStationsCombo.addItem("Turbidity (ru)");

			// Creates editors
			classEditor = new ComboEditor(classCombo);
			uStationsEditor = new ComboEditor(uStationsCombo);
			stationsEditor = new ComboEditor(stationsCombo);
		}
		

		public TableCellEditor getCellEditor(int row, int column) {
			if (column == 1)
				return classEditor;
			else if (currentIndex.equals(ExactModel.INDICES_TYPES[0]))
				return uStationsEditor;
			else
				return stationsEditor;
		}

		public TableCellRenderer getCellRenderer(int row, int column) {
			if (model.isMultiClass() || column != 1)
				return super.getCellRenderer(row, column);
			else
				return super.getDefaultRenderer(Object.class);
		}

		protected class ComboEditor extends DefaultCellEditor {
			protected JComboBox combo;

			public ComboEditor(JComboBox comboBox) {
				super(comboBox);
				combo = comboBox;
			}
			public Object getCellEditorValue() {
				int val = combo.getSelectedIndex();
				return new Integer(val - 2);
			}
		}
	}

	protected class LinesTableModel extends AbstractTableModel {
		public Class getColumnClass(int columnIndex) {
			switch (columnIndex) {
			case 0:
				return Color.class;
			case 1:
				return String.class;
			case 2:
				return String.class;
			default:
				return super.getColumnClass(columnIndex);
			}
		}
		public int getColumnCount() {
			return 3;
		}

		public Object getValueAt(int rowIndex, int columnIndex) {
			int stationNum = stations[rowIndex];
			int classNum = classes[rowIndex];
			switch (columnIndex) {
			case 0:
				return graph.getColors()[rowIndex];
			case 1:
				if (classNum >= 0)
					return model.getClassNames()[classNum];
				else if (classNum == -1)
					return AGGREGATE;
				else
					return null;
			case 2:
				if (stationNum == -1)
					return "Conductivity (S/m)";
				else if (stationNum ==0)
					return "Temperature (C)";
				else if (stationNum ==1)
					return "CDOM (ru)";
				if (stationNum == 2)
					return "Chl-a (ru)";
				else if (stationNum ==3)
					return "REDOX (meV)";
				else if (stationNum ==4)
					return "PAR (umol/m^2*s^1)";
				if (stationNum == 5)
					return "pH";
				else if (stationNum ==6)
					return "Turbidity (ru)";
				else
					return null;
			}
			return null;
		}


		public String getColumnName(int column) {
			switch (column) {
			case 0:
				return " ";
			case 1:
				return " ";
			case 2:
				return "Select option";
			}

			return super.getColumnName(column); // To change body of overridden
			// methods use File | Settings |
			// File Templates.
		}
		public int getRowCount() {
			return graph.getColors().length;
		}
				public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
			if (columnIndex == 2) {
				// if (currentIndex.equals(ExactModel.INDICES_TYPES[0]) &&
				// ((Integer)aValue).intValue() < 0)
				// stations[rowIndex] = -2;
				// else
				stations[rowIndex] = ((Integer) aValue).intValue();
			} else
				classes[rowIndex] = ((Integer) aValue).intValue();
			// Paints new index
			paintIndexAtRow(rowIndex);
		}
	public boolean isCellEditable(int rowIndex, int columnIndex) {
			return columnIndex == 2
					|| (columnIndex == 1 && model.isMultiClass());
		}
	}

	
	public void updateRecursive() {
		clCmbloopIndex.removeAllItems();
		for (int i = 1; i < Stock.row; i++) {
			clCmbloopIndex.addItem(i);
		}
	}

	public void updateGreedy() {
		clCmbloopIndex.removeAllItems();
		for (int i = 0; i < Points.row; i++) {
			clCmbloopIndex.addItem(i);
		}
	}

	public Vector<DataPoint> getDataPoints() {
		Vector<DataPoint> temp = new Vector();
		int sensors = Battery.row;
		for (int i = 0; i < sensors; i++) {
			temp.add(new DataPoint((int) Battery.sensorID[i],
					AverageBattery.level[i]));
		}
		return temp;
	}
	public class clActions implements ActionListener {
		public void actionPerformed(ActionEvent e) {
		}
		public Vector<DataPoint> getDataPoints() {
			Vector<DataPoint> temp = new Vector();
			int sensors = Battery.row;
			for (int i = 0; i < sensors; i++) {
				temp.add(new DataPoint((int) Battery.sensorID[i],
						AverageBattery.level[i]));
			}
			return temp;
		}
	}

/** 
 * 
 * @author Dang Nhon Tuan
 *
 */

	public class controlListener implements ChangeListener {
		public void stateChanged(ChangeEvent e) {	
			
			if (DataRadius.equals(e.getSource())) {
				String s= DataRadius.getValue().toString();
				double value=Double.valueOf(s).doubleValue();			
				EnduModel.radius = value;
				util.repaintVTK();
				util.updateVTK();
			}
			if (DataReduction.equals(e.getSource())) {
				String s= DataReduction.getValue().toString();
				int value=Integer.parseInt(s);			
				System.out.println("+++++++++++++++++++DataReduction "+value);
				EnduModel.dataReduction2 = value;
				util.repaintVTK();
				util.updateVTK();	
				EnduModel.dataReduction1 = value;
				
			}
			if (MissingValue.equals(e.getSource())) {
				String s= MissingValue.getValue().toString();
				double value=Double.valueOf(s).doubleValue();			
				System.out.println("+++++++++++++++++++MissingValue "+value);
				EnduModel.missingValue = value;
				util.repaintVTK();
				util.updateVTK();
			}
			else if (cameraX.equals(e.getSource())) {
				String s= cameraX.getValue().toString();
				double x=Double.valueOf(s).doubleValue();			
				EnduModel.cameraX = x;
				EnduModel.camera.SetPosition(EnduModel.cameraX , EnduModel.cameraY  , EnduModel.cameraZ);
				util.updateVTK();
			} 
			else if (cameraY.equals(e.getSource())) {
				String s= cameraY.getValue().toString();		
				double y=Double.valueOf(s).doubleValue();		
				EnduModel.cameraY = y;
				EnduModel.camera.SetPosition(EnduModel.cameraX , EnduModel.cameraY  , EnduModel.cameraZ);
				util.updateVTK();
			}
			else if (cameraZ.equals(e.getSource())) {
				String s= cameraZ.getValue().toString();	
				double z=Double.valueOf(s).doubleValue();		
				EnduModel.cameraZ = z;
				EnduModel.camera.SetPosition(EnduModel.cameraX , EnduModel.cameraY  , EnduModel.cameraZ);
				util.updateVTK();
			}
			else if (focalX.equals(e.getSource())) {
				String s= focalX.getValue().toString();	
				double x=Double.valueOf(s).doubleValue();		
				EnduModel.focalX = x;
				EnduModel.camera.SetFocalPoint(EnduModel.focalX , EnduModel.focalY  , EnduModel.focalZ);
				util.updateVTK();
			}
			else if (focalY.equals(e.getSource())) {
				String s= focalY.getValue().toString();	
				double y=Double.valueOf(s).doubleValue();		
				EnduModel.focalY = y;
				EnduModel.camera.SetFocalPoint(EnduModel.focalX , EnduModel.focalY  , EnduModel.focalZ);
				util.updateVTK();
			}
			else if (focalZ.equals(e.getSource())) {
				String s= focalZ.getValue().toString();	
				double z=Double.valueOf(s).doubleValue();		
				EnduModel.focalZ = z;
				EnduModel.camera.SetFocalPoint(EnduModel.focalX , EnduModel.focalY  , EnduModel.focalZ);
				util.updateVTK();
			}
		}
	}
	public class planeListener implements ChangeListener {
		public void stateChanged(ChangeEvent e) {	
			if (X1.equals(e.getSource()) || X2.equals(e.getSource()) || X3.equals(e.getSource())) {
				String s1= X1.getValue().toString();
				double value1=Double.valueOf(s1).doubleValue();
				String s2= X2.getValue().toString();
				double value2=Double.valueOf(s2).doubleValue();
				String s3= X3.getValue().toString();
				double value3=Double.valueOf(s3).doubleValue();
				
				EnduModel.ren.RemoveActor(EnduModel.planeActor2);
				EnduModel.ren.RemoveActor(EnduModel.planeSphereActor1);
				EnduModel.ren.RemoveActor(EnduModel.planeSphereActor2);
				EnduModel.ren.RemoveActor(EnduModel.planeSphereActor3);
				EnduModel.createPlane(value1, value2, value3);
				util.updateVTK();
			}
		}
	}

	public class NextPrev implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			double[] X1 = EnduModel.camera.GetPosition();
			double[] vector = EnduModel.camera.GetDirectionOfProjection();// new

			String s= Zoom.getValue().toString();
			double zoomStep=Double.valueOf(s).doubleValue();
			String s1= XY.getValue().toString();
			double f1=Double.valueOf(s1).doubleValue();
			String s2= Depth.getValue().toString();
			double f2=Double.valueOf(s2).doubleValue();

			if (clBtnNext.equals(e.getSource())) {
				X1[0] += zoomStep * (vector[0]);
				X1[1] += zoomStep * (vector[1]);
				X1[2] += zoomStep * (vector[2]);
				EnduModel.zoomStep = zoomStep;
				EnduModel.camera.SetPosition(X1[0], X1[1], X1[2]);
				util.updateControllers();
				util.updateVTK();
			} else if (clBtnPrev.equals(e.getSource())) {
				X1[0] -= zoomStep * (vector[0]);
				X1[1] -= zoomStep * (vector[1]);
				X1[2] -= zoomStep * (vector[2]);
				EnduModel.zoomStep = zoomStep;
				EnduModel.camera.SetPosition(X1[0], X1[1], X1[2]);
				util.updateControllers();
				util.updateVTK();				
			} else if (scaleDepthDown.equals(e.getSource())) {
				EnduModel.scaleDepth= EnduModel.scaleDepth*f2;
				util.repaintVTK();
				util.rescaleDepth();
				util.updateVTK();
			}else if (scaleDepthUp.equals(e.getSource())) {
				EnduModel.scaleDepth= EnduModel.scaleDepth/f2;
				util.repaintVTK();
				util.rescaleDepth();
				util.updateVTK();
			}	
			else if (scaleXYDown.equals(e.getSource())) {
				EnduModel.scaleXY= EnduModel.scaleXY*f1;
				util.repaintVTK();
				util.rescaleXY();
				util.updateVTK();
			}else if (scaleXYUp.equals(e.getSource())) {
				EnduModel.scaleXY= EnduModel.scaleXY/f1;
				util.repaintVTK();
				util.rescaleXY();
				util.updateVTK();
			}	
		}
	}

	public class MouseMotionExample  implements MouseMotionListener { 
		public void mouseMoved(MouseEvent me)  { 
			
		} 
		public void mouseDragged(MouseEvent me){
			util.updateControllers();
			
		} 
	}
	public class MouseEvent2 implements MouseListener{
		public void mousePressed(MouseEvent e) {
				//System.out.println("Mouse pressed; # of clicks: "+EnduModel.renWin.getLocation().getY() + " Y " +e.getY());
		    }

		    public void mouseReleased(MouseEvent e) {
		    	//System.out.println("Mouse released; # of clicks: ");
		    }

		    public void mouseEntered(MouseEvent e) {
		    	//System.out.println("Mouse entered");
		    }

		    public void mouseExited(MouseEvent e) {
		    	//System.out.println("Mouse exited");
		    }

		    public void mouseClicked(MouseEvent e) {
		    	//System.out.println("Mouse clicked (# of clicks: ");
		    }
	}
	
	public class viewListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			 if (view.equals(e.getSource())) {
					simulation.startSim();
					
			 }
			 if (surfaceButton.equals(e.getSource())) {
					if (surfaceState){
						surfaceState=false;
						surfaceButton.setText("Show surface  ");
						Color c = new Color(0,255,0);
						surfaceButton.setBackground(c);
						EnduModel.ren.RemoveActor(EnduModel.planeActor);
						util.updateVTK();
					}
					else{
						surfaceState=true;
						surfaceButton.setText("Hide   surface   ");
						Color c = new Color(255,50,0);
						surfaceButton.setBackground(c);
						EnduModel.createImage();
						util.updateVTK();
					}
					
			 }
			 if (cutButton.equals(e.getSource())) {
					if (cutState){
						cutState=false;
						cutButton.setText("Show slice  ");
						Color c = new Color(0,255,0);
						cutButton.setBackground(c);
						EnduModel.ren.RemoveActor(EnduModel.planeActor2);
						EnduModel.ren.RemoveActor(EnduModel.planeSphereActor1);
						EnduModel.ren.RemoveActor(EnduModel.planeSphereActor2);
						EnduModel.ren.RemoveActor(EnduModel.planeSphereActor3);
						util.updateVTK();
					}
					else{
						cutState=true;
						cutButton.setText("Hide   slice   ");
						Color c = new Color(255,50,0);
						cutButton.setBackground(c);
						String s1= X1.getValue().toString();
						double value1=Double.valueOf(s1).doubleValue();
						String s2= X2.getValue().toString();
						double value2=Double.valueOf(s2).doubleValue();
						String s3= X3.getValue().toString();
						double value3=Double.valueOf(s3).doubleValue();
						EnduModel.createPlane(value1, value2, value3);
						util.updateVTK();
					}
					
			 }
			 
			 if (e.getSource() == openButton) {
					int returnVal = fc.showOpenDialog(openButton);

					if (returnVal == JFileChooser.APPROVE_OPTION) {
						File file = fc.getSelectedFile();
						ReadCSV.fileName=file.getPath();
						System.out.println("Opening: " + file.getPath());
						TextF.setText(file.getPath());
						ReadCSV.readEndurance();
						
					} else {
						ReadCSV.fileName="endurance.csv";
						System.out.println("Open command cancelled by user.");
					}
					
			 }
		}
		
	}
	
}
