package imseProc.graph;

import imseProc.graph.ExtSignalsPlotter.ExtSignalPlotInfo;

import java.text.DecimalFormat;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.Map.Entry;

import oneLiners.OneLiners;

import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;

public class ExtSignalsSWTControl {
	private Group swtGroup;
	private GraphUtilProcessor proc;
	
	private Table sigsTable;
	private TableEditor paramsTableEditor;
	
	private List<ExtSignalPlotInfo> sigList;
	
	private Combo saveLoadListCombo;
	private Button saveButton;
		
	private static final String colNames[] = new String[]{ "Name", "Path", "Entry", "Scale", "Offset", "Enable",  };
	private static final int COL_NAME = 0;
	private static final int COL_PATH = 1;
	private static final int COL_SLICE = 2;
	private static final int COL_SCALE = 3;
	private static final int COL_OFFSET = 4;
	private static final int COL_ENABLE = 5;
	
	public static final DecimalFormat tableValueFormat = new DecimalFormat("#.###");
	
	private TableItem tableItemEditing = null;
	
	public ExtSignalsSWTControl(Composite parent, int style, GraphUtilProcessor proc) {
			this.proc = proc;
			
			swtGroup = new Group(parent, style);
			swtGroup.setText("Signals");
			swtGroup.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 4, 1));
			swtGroup.setLayout(new GridLayout(4, false));
			
			Label lS = new Label(swtGroup, SWT.NONE); lS.setText("Save/Load list:");
			
			saveLoadListCombo = new Combo(swtGroup, SWT.DROP_DOWN);
			saveLoadListCombo.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 2, 1));
			saveLoadListCombo.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { saveLoadComboEvent(event); }});
			saveLoadListCombo.setItems(proc.getSignalPlotter().loadList());
			
			saveButton = new Button(swtGroup, SWT.PUSH);
			saveButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false, 1, 1));
			saveButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { saveButtonEvent(event); }});
			
			sigsTable = new Table(swtGroup, SWT.NONE);
			sigsTable.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, true, 5, 0));
			sigsTable.setHeaderVisible(true);
			sigsTable.setLinesVisible(true);
			TableColumn cols[] = new TableColumn[colNames.length];
			for(int i=0; i < colNames.length; i++){
				cols[i] = new TableColumn(sigsTable, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
				cols[i].setText(colNames[i]); 
				cols[i].pack();
			}
			

			TableItem blankItem = new TableItem(sigsTable, SWT.NONE);
			blankItem.setText(0, "");		
			
			paramsTableEditor = new TableEditor (sigsTable);
			paramsTableEditor.horizontalAlignment = SWT.LEFT;
			paramsTableEditor.grabHorizontal = true;
			sigsTable.addListener(SWT.MouseDown, new Listener() { @Override public void handleEvent(Event event) { tableMouseDownEvent(event); } });
			
			  
	}

	private void saveLoadComboEvent(Event event) {
		proc.getSignalPlotter().load(saveLoadListCombo.getText());
	}
	
	private void saveButtonEvent(Event event) {
		proc.getSignalPlotter().save(saveLoadListCombo.getText());
	}

	/** Copied from 'Snippet123'  Copyright (c) 2000, 2004 IBM Corporation and others. 
	 * [ org/eclipse/swt/snippets/Snippet124.java ] */
	private void tableMouseDownEvent(Event event){
		 
		Rectangle clientArea = sigsTable.getClientArea ();
		Point pt = new Point (event.x, event.y);
		int index = sigsTable.getTopIndex ();
		while (index < sigsTable.getItemCount ()) {
			boolean visible = false;
			final TableItem item = sigsTable.getItem (index);
			for (int i=0; i<sigsTable.getColumnCount (); i++) {
				Rectangle rect = item.getBounds (i);
				if (rect.contains (pt)) {
					final int column = i;
					final Text text = new Text(sigsTable, SWT.NONE);
					tableItemEditing = item;
					Listener textListener = new Listener () {
						public void handleEvent (final Event e) {
							switch (e.type) {
							case SWT.FocusOut:
								setTableEntry(column, item, text.getText());
								text.dispose ();
								tableItemEditing = null;
								break;
							case SWT.Traverse:
								switch (e.detail) {
								case SWT.TRAVERSE_RETURN:
									setTableEntry(column, item, text.getText());
									//FALL THROUGH
								case SWT.TRAVERSE_ESCAPE:
									text.dispose ();
									tableItemEditing = null;
									e.doit = false;
								}
								break;
							}
						}
					};
					text.addListener (SWT.FocusOut, textListener);
					text.addListener (SWT.Traverse, textListener);
					paramsTableEditor.setEditor (text, item, i);
					text.setText (item.getText (i));
					text.selectAll ();
					text.setFocus ();
					return;
				}
				if (!visible && rect.intersects (clientArea)) {
					visible = true;
				}
			}
			if (!visible) return;
			index++;
		}
		
		
	}
	
	private void setTableEntry(int column, TableItem item, String str){
		
		try{
			item.setText(column, str);
			
			String oldName = item.getText(0);
			
			//see if the entry already exists
			ExtSignalPlotInfo sigInfo = null;
			for(ExtSignalPlotInfo sigInfoTest : sigList){
				if(sigInfoTest.name.equalsIgnoreCase(oldName)){
					sigInfo = sigInfoTest;
					break;
				}
			}
			
			//if not, create a new entry
			if(sigInfo == null){
				sigInfo = new ExtSignalPlotInfo();
				sigList.add(sigInfo);
			}
			
			sigInfo.x = null;
			sigInfo.data = null;
			
			switch(column){
				case COL_NAME: //signal			
					if(str.length() <= 0){
						item.dispose();
						sigList.remove(sigInfo);
					}else{
						sigInfo.name = str;
					}
					break;
					
				case COL_PATH:
					sigInfo.path = str;
					break;
					
				case COL_SLICE:
					String parts[] = str.split(",");
					sigInfo.slice = new int[parts.length];
					for(int i=0; i < parts.length; i++)
						sigInfo.slice[i] = OneLiners.mustParseInt(parts[i].trim());			
	
					break;
					
				case COL_SCALE:
					sigInfo.scale = OneLiners.mustParseDouble(str);
					break;
					
				case COL_OFFSET:
					sigInfo.offset = OneLiners.mustParseDouble(str);
					break;
					
				case COL_ENABLE:
					sigInfo.enable = (str.startsWith("Y") || str.startsWith("y"));
					break;
					
			}
						
		}catch(SWTException err){
			err.printStackTrace();
			/// wtF?
			
		}
		
		
		proc.getSignalPlotter().signalsListModified();
		proc.calc();
	}	
	
	public void update(){
		//clear and repopulate table
		if(tableItemEditing != null)
			return;
		
		sigsTable.removeAll();
		
		sigList = proc.getSignalPlotter().getSignalsList();
		if(sigList == null)
			return;
			
		Collections.sort(sigList);
				
		for(ExtSignalPlotInfo sigInfo : sigList){			
			
			if(sigInfo.name.length() <= 0)
				continue;
			
			if(sigInfo.slice == null)
				sigInfo.slice = new int[0];
			if(sigInfo.path == null)
				sigInfo.path = "";
			
			TableItem item = new TableItem(sigsTable, SWT.NONE);		
			item.setText(COL_NAME, sigInfo.name);		
			item.setText(COL_PATH, sigInfo.path);			
			String sliceStr = "";			
			for(int i=0; i < sigInfo.slice.length; i++){
				sliceStr += (i == 0 ? "" : ", ") + sigInfo.slice[i]; 
			}
			item.setText(COL_SLICE, sliceStr);			
			item.setText(COL_SCALE, Double.toString(sigInfo.scale));			
			item.setText(COL_OFFSET, Double.toString(sigInfo.offset));			
			item.setText(COL_ENABLE, sigInfo.enable ? "Y" : "N");		
			
		}
		
		//and finally a blank item for creating new point
		TableItem blankItem = new TableItem(sigsTable, SWT.NONE);
		blankItem.setText(0, "");
	}
		
	public Group getGroup(){ return swtGroup; }

}
