package imseProc.proc.fft;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
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 imseProc.core.IMSEProc;
import imseProc.core.ImagePipeController;
import imseProc.core.ImagePipeControllerROISettable;
import imseProc.core.ImgPipe;
import imseProc.gui.swt.SWTControllerInfoDraw;

public class FFTSWTController implements ImagePipeController, SWTControllerInfoDraw, ImagePipeControllerROISettable {
	
	private Group swtGroup;
	private FFTProcessor proc;
	private Button autoUpdateCheckbox;
	private Button updateButton;
	private Button singleImageCheckbox;
	private Spinner cropSpinner;
	private Button setWindowing;
	private Label statusLabel;
	
	public FFTSWTController(Composite parent, int style, FFTProcessor proc) {
		this.proc = proc;
		swtGroup = new Group(parent, style);
		swtGroup.setText("FFT Control (" + proc.toShortString() + ")");		
		swtGroup.setLayout(new GridLayout(3, 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, 2, 1));
		
		Label lC = new Label(swtGroup, SWT.NONE); lC.setText("Crop:");		
		cropSpinner = new Spinner(swtGroup, SWT.NONE);
		cropSpinner.setValues(128, 0, Integer.MAX_VALUE, 0, 16, 128);
		cropSpinner.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 2, 1));
		cropSpinner.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { cropSpinnerEvent(event); } });

		singleImageCheckbox = new Button(swtGroup, SWT.CHECK);
		singleImageCheckbox.setText("Single Image");
		singleImageCheckbox.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { singleImageEvent(event); } });
		singleImageCheckbox.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 3, 1));
		
		setWindowing = new Button(swtGroup, SWT.CHECK);
		setWindowing.setText("Set windowing");
		setWindowing.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { autoUpdateEvent(event); } });
		setWindowing.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 3, 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, 2, 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); } });
		
				
		swtGroup.pack();
		update();
	}
	
	private void cropSpinnerEvent(Event e){
		proc.setCrop(cropSpinner.getSelection());
	}
	
	private void autoUpdateEvent(Event e){
		proc.setAutoCalc(autoUpdateCheckbox.getSelection());
	}
	
	private void singleImageEvent(Event e){
		proc.setCalcSelectedImageOnly(singleImageCheckbox.getSelection());
		proc.calc();
	}

	private void forceUpdateEvent(Event e){
		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(){
		autoUpdateCheckbox.setSelection(proc.getAutoCalc());
		singleImageCheckbox.setSelection(proc.isCalcSelectedImageOnly());
		cropSpinner.setSelection(proc.getCrop());
		int stat = proc.getCalcProgress();
		statusLabel.setText((stat < 0) ? "Idle" : (stat + " / " + proc.getConnectedSource().getNumImages()));
	}

	@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) {
		if(setWindowing.getSelection())
			proc.setGaussWindow(x0, y0, width, height);
	}

	@Override
	public void drawOnImage(GC gc, double scale, int imageWidth, int imageHeight, boolean asSource) {
		double gx0 = proc.getGaussWindowX0();
		double gy0 = proc.getGaussWindowY0();
		double gwx = proc.getGaussWindowFWHMX();
		double gwy = proc.getGaussWindowFWHMY();
		
		gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE));
		gc.drawOval(
				(int)((gx0 - gwx/2) * scale), 
				(int)((gy0 - gwy/2) * scale), 
				(int)(gwx * scale), 
				(int)(gwy * scale));
		
		gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_DARK_RED));
		gc.drawOval(
				(int)((gx0 - gwx) * scale), 
				(int)((gy0 - gwy) * scale), 
				(int)(gwx*2 * scale), 
				(int)(gwy*2 * scale));
	}

	@Override
	public void destroy() {
		swtGroup.dispose();
		proc.controllerDestroyed(this);
		//proc.destroy(); //and actively kill it, for good measure
	}

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

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