package imseProc.proc.pitch;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map.Entry;
import java.util.Set;

import oneLiners.OneLiners;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.graphics.GC;
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.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.Spinner;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;

import imseProc.core.IMSEProc;
import imseProc.core.ImagePipeController;
import imseProc.core.ImagePipeControllerROISettable;
import imseProc.core.Img;
import imseProc.core.ImgPipe;
import imseProc.gui.swt.SWTControllerInfoDraw;

/** SWT controller for the pitch/current calculation
 *  
 * @author oliford
 */
public class PitchSWTController implements ImagePipeController, SWTControllerInfoDraw, ImagePipeControllerROISettable {

	private Group swtGroup;
	private PitchProcessor proc;
	
	private Button autoUpdateCheckbox;
	private Button currentCheckbox;
	private Button updateButton;
	private Label statusLabel;
	private Spinner gridNumXSpinner;
	private Spinner gridNumYSpinner;
	
	private Spinner beamSelectionSpinner;

	private boolean isSinkController;
		
	public PitchSWTController(Composite parent, int style, PitchProcessor proc, boolean isSinkController) {
		this.isSinkController = isSinkController;
		this.proc = proc;
		swtGroup = new Group(parent, style);
		swtGroup.setText("Pol-->Pitch Control (" + proc.toShortString() + ")");		
		swtGroup.setLayout(new GridLayout(6, false));
		swtGroup.addListener(SWT.Dispose, new Listener() { @Override public void handleEvent(Event event) { destroy(); }});
		
		Label lStat = new Label(swtGroup, SWT.NONE); lStat.setText("Status:");
		statusLabel = new Label(swtGroup, SWT.NONE);
		statusLabel.setText("init");
		statusLabel.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 6, 1));

		Label lBS = new Label(swtGroup, SWT.NONE); lBS.setText("Force beam:");
		beamSelectionSpinner = new Spinner(swtGroup, SWT.NONE);
		beamSelectionSpinner.setValues(-1, -1, 8, 0, 1, 4); //-1 indicates that we want lat,long as output
		beamSelectionSpinner.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 1, 1));
		beamSelectionSpinner.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { settingsChangedEvent(event); } });
		
		Label lNX = new Label(swtGroup, SWT.NONE); lNX.setText("nCalcGrid X:");
		gridNumXSpinner = new Spinner(swtGroup, SWT.NONE);
		gridNumXSpinner.setValues(30, 2, 100, 0, 1, 4);
		gridNumXSpinner.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 1, 1));
		gridNumXSpinner.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { settingsChangedEvent(event); } });
		
		Label lNY = new Label(swtGroup, SWT.NONE); lNY.setText("Y:");
		gridNumYSpinner = new Spinner(swtGroup, SWT.NONE);
		gridNumYSpinner.setValues(30, 2, 100, 0, 1, 4);
		gridNumYSpinner.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 1, 1));
		gridNumYSpinner.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { settingsChangedEvent(event); } });

		currentCheckbox = new Button(swtGroup, SWT.CHECK);
		currentCheckbox.setText("d/dR (~ current in kA)");
		currentCheckbox.setSelection(false);
		currentCheckbox.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { settingsChangedEvent(event); } });
		currentCheckbox.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 2, 1));
		
		autoUpdateCheckbox = new Button(swtGroup, SWT.CHECK);
		autoUpdateCheckbox.setText("Auto");
		autoUpdateCheckbox.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { autoUpdateEvent(event); } });
		autoUpdateCheckbox.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 1, 1));
		
		updateButton = new Button(swtGroup, SWT.PUSH);
		updateButton.setText("Update Now");
		updateButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { forceUpdateEvent(event); } });
		updateButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false, 1, 1));
		
		swtGroup.pack();
		update();
	}
	
	private void settingsChangedEvent(Event e){
		proc.setBeamSelection(beamSelectionSpinner.getSelection());

		proc.setCalcCurrent(currentCheckbox.getSelection());
		proc.setCalcGrid(gridNumXSpinner.getSelection(), gridNumYSpinner.getSelection());
		
	}
	
	private void autoUpdateEvent(Event e){
		proc.setAutoCalc(autoUpdateCheckbox.getSelection());
	}

	private void forceUpdateEvent(Event e){
		proc.invalidate();
		proc.calc();
	}

	@Override
	public void generalControllerUpdate() {
		if(swtGroup.isDisposed())
			return;
		IMSEProc.ensureFinalSWTUpdate(swtGroup.getDisplay(), this, new Runnable() {
			@Override
			public void run() { update(); }
		});
	}
	
	private void update(){
		boolean autoUpdate = proc.getAutoCalc();
		if(autoUpdateCheckbox.getSelection() != autoUpdate)
			autoUpdateCheckbox.setSelection(autoUpdate);
	
		int stat = proc.getCalcProgress();
		statusLabel.setText((stat < 0) ? "Idle" : (stat + " / " + proc.getConnectedSource().getNumImages()));
		
		int nX = proc.getCalcNX(), nY = proc.getCalcNY();		
		if(gridNumXSpinner.getSelection() != nX)
			gridNumXSpinner.setSelection(nX);
		
		if(gridNumYSpinner.getSelection() != nY)
			gridNumYSpinner.setSelection(nY);
		
		boolean calcCurrent = proc.getCalcCurrent();
		if(currentCheckbox.getSelection() != calcCurrent)
			currentCheckbox.setSelection(calcCurrent);
	
	}

	@Override
	public void movingPos(int x, int y) {	}

	@Override
	public void fixedPos(int x, int y) {	}

	@Override
	public void setRect(int x0, int y0, int width, int height) {
		
	}
	
	@Override
	public void drawOnImage(GC gc, double scale, int imageWidth, int imageHeight, boolean asSource) { }
	
	@Override
	public void destroy() {
		swtGroup.dispose();
		proc.controllerDestroyed(this);
	}

	@Override
	public Object getInterfacingObject() { return swtGroup;	}

	@Override
	public ImgPipe getPipe() { return proc;	}
}
