package org.eclipse.stem.ui.grapheditor;

import java.util.List;

import org.eclipse.emf.common.util.EList;
import org.eclipse.stem.definitions.labels.AreaLabel;
import org.eclipse.stem.definitions.labels.PopulationLabel;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.zest.core.widgets.Graph;
import org.eclipse.zest.core.widgets.GraphItem;
import org.eclipse.zest.core.widgets.GraphNode;


//for modifications (when typed in with keyboard)
public class ComboListenerValue implements KeyListener
{ 
	
	
	NodeData nodeData;
	Graph zestGraph;
	Combo connectedCombo;
	int selectedValue = -1;
	
	ComboListenerValue(Graph zestGraph, Combo connectedCombo)
	{		
		this.zestGraph = zestGraph;
		this.connectedCombo = connectedCombo;		
	}
	
	
	public void widgetDefaultSelected(final SelectionEvent e) {}
	

	public void keyReleased(final KeyEvent e) {
		
		if (e.character==SWT.CR || e.character==SWT.LF)
		{	
		  connectedCombo.setFocus();
		}
		
		Combo valueCombo = (Combo) e.widget;
		
		//System.err.println("new: " + valueCombo.getText());
		
		int selectedType = connectedCombo.getSelectionIndex(); 
//		if (e.character==SWT.CR || e.character==SWT.LF)
		{
			
			 
			List<GraphItem> selectedItems = zestGraph.getSelection();
			if (selectedItems.size() == 1)
			{
				if (selectedItems.get(0) instanceof GraphNode)
				{
					GraphNode selectedNode = (GraphNode) selectedItems.get(0);
					NodeData nodeData = (NodeData) selectedNode.getData();
					this.nodeData = nodeData;
					
				}			
			}
			
			if  (this.nodeData == null)
				return;
			
			
			
			if (selectedValue >= 0)
			{
				String oldValueString = valueCombo.getItem(selectedValue);			
				String newValueString = valueCombo.getText() ;
				
				EList<org.eclipse.stem.core.graph.NodeLabel> nodeLabels = nodeData.getNodeLabels();
				org.eclipse.stem.core.graph.NodeLabel nodeLabel = nodeLabels.get(selectedType);
				List<Integer> labelTypes = nodeData.getNodeLabelTypes();
				
				switch(labelTypes.get(selectedType))
				{
					case GraphDefs.AREA_LABEL:  
							AreaLabel areaLabel = (AreaLabel) nodeLabel;							
							double newArea;
							try {
								newArea = Double.parseDouble(newValueString);
								valueCombo.setItem(selectedValue, newValueString);
							} catch (NumberFormatException ex){
								newArea = areaLabel.getCurrentAreaValue().getArea();
								valueCombo.setItem(selectedValue, oldValueString);
								valueCombo.setText(oldValueString);
							}
							
							areaLabel.getCurrentAreaValue().setArea(newArea);						
							break;
					
					case GraphDefs.POPULATION_LABEL: 	
						PopulationLabel populationLabel = (PopulationLabel) nodeLabel;
											
						//order defined in other listener
						if (this.selectedValue == 0) // population name
						{
							populationLabel.setName(newValueString);
							populationLabel.setPopulationIdentifier(newValueString);
							valueCombo.setItem(selectedValue, newValueString);
						}
						if (this.selectedValue == 1) // pop size
						{
							double newCount;
							try {
								newCount = Double.parseDouble(newValueString);
								valueCombo.setItem(selectedValue, newValueString);
							} catch (NumberFormatException ex){
								newCount = populationLabel.getCurrentPopulationValue().getCount();
								valueCombo.setItem(selectedValue, oldValueString);
								valueCombo.setText(oldValueString);
							}
							populationLabel.getCurrentPopulationValue().setCount(newCount);
						}
						if (this.selectedValue == 2) //population area
						{	double newPopulatedArea;
							try {
								newPopulatedArea = Double.parseDouble(newValueString);
								valueCombo.setItem(selectedValue, newValueString);
							} catch (NumberFormatException ex){
								newPopulatedArea = populationLabel.getPopulatedArea();
								valueCombo.setItem(selectedValue, oldValueString);
								valueCombo.setText(oldValueString);
							}						
							populationLabel.setPopulatedArea(newPopulatedArea);
						}						
						break;
				} //end switch

			} // selected value index in combo >= 0
		} // if key==ENTER					
	}
	
	
	
	public void keyPressed(final KeyEvent e) {		
		Combo valueCombo = (Combo) e.widget;	
		
		//no idea but seems to be necessary in some cases
		if (valueCombo.getSelectionIndex() != -1)
		{ 
			this.selectedValue = valueCombo.getSelectionIndex(); 
		}
		
		
	} // keyPressed for data input
} //end combo listener for Node Label Values