package imseProc.arduinoComm.swt;

import imseProc.arduinoComm.ArduinoCommHanger;
import imseProc.arduinoComm.SequenceConfig;
import imseProc.core.IMSEProc;

import org.eclipse.swt.SWT;
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.Spinner;

public class SequenceSWTGroup {
	private ArduinoCommHanger proc;
	
	private Group swtGroup;

	private Label statusLabel;
	private Label timingLabel;
	private Spinner numFramesSpinner;
	private Spinner stepsPerFrameSpinner;
	private Combo flcStateCombo;
	private Spinner startDelaySpinner;
	private Spinner clockPeriodSpinner;
	private Spinner exposureTimeSpinner;
	private Spinner postExpTimeSpinner;
	private Button startTriggerCheckbox;
	private Button lineTriggerCheckbox;
	private Button softTriggeringCheckbox;	
	private Spinner restartTimeSpinner;
	private Button startButton;	
	private Button abortButton;	
	private Button downloadButton;	
	private Button advanceButton;
	
	public SequenceSWTGroup(Composite parent, ArduinoCommHanger proc) {
		this.proc = proc;
		
		swtGroup = new Group(parent, SWT.BORDER);
		swtGroup.setText("Sequence");
		swtGroup.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 1, 1));
		swtGroup.setLayout(new GridLayout(4, false));
		
		Label lSL = new Label(swtGroup, SWT.NONE); lSL.setText("Status:");
		statusLabel = new Label(swtGroup, SWT.NONE);
		statusLabel.setText("init");
		statusLabel.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 3, 1));

		Label lTL = new Label(swtGroup, SWT.NONE); lTL.setText("Timing:");
		timingLabel = new Label(swtGroup, SWT.NONE);
		timingLabel.setText("init");
		timingLabel.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 3, 1));

		Label lNF = new Label(swtGroup, SWT.NONE); lNF.setText("Num Frames:");
		numFramesSpinner = new Spinner(swtGroup, SWT.NONE);
		numFramesSpinner.setValues(480, 0, Integer.MAX_VALUE, 0, 100, 1000);
		numFramesSpinner.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 1, 1));
		numFramesSpinner.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { sequenceTimingEvent(event); } });
		
		Label lNS = new Label(swtGroup, SWT.NONE); lNS.setText("Num Steps/Frame:");
		stepsPerFrameSpinner = new Spinner(swtGroup, SWT.NONE);
		stepsPerFrameSpinner.setValues(4, 0, Integer.MAX_VALUE, 0, 1, 10);
		stepsPerFrameSpinner.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 1, 1));
		stepsPerFrameSpinner.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { sequenceTimingEvent(event); } });
		
		Label lFS = new Label(swtGroup, SWT.NONE); lFS.setText("FLC:");
		flcStateCombo = new Combo(swtGroup, SWT.MULTI | SWT.DROP_DOWN | SWT.READ_ONLY);
		flcStateCombo.setItems(new String[]{ "Off", "On", "Interlaced" });
		flcStateCombo.select(0);
		flcStateCombo.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 1, 1));
		flcStateCombo.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { sequenceTimingEvent(event); } });
		
		lineTriggerCheckbox = new Button(swtGroup, SWT.CHECK);
		lineTriggerCheckbox.setText("Fast Advance");
		lineTriggerCheckbox.setSelection(true);
		lineTriggerCheckbox.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 1, 1));
		lineTriggerCheckbox.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { sequenceTimingEvent(event); } });
		
		startTriggerCheckbox = new Button(swtGroup, SWT.CHECK);
		startTriggerCheckbox.setText("Start Trig");
		startTriggerCheckbox.setSelection(true);
		startTriggerCheckbox.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 1, 1));
		startTriggerCheckbox.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { sequenceTimingEvent(event); } });

		Label lSD = new Label(swtGroup, SWT.NONE); lSD.setText("Start Delay / ms:");
		startDelaySpinner = new Spinner(swtGroup, SWT.NONE);
		startDelaySpinner.setValues(0, 0, Integer.MAX_VALUE, 0, 1, 100);
		startDelaySpinner.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 1, 1));
		startDelaySpinner.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { sequenceTimingEvent(event); } });

		Label lCP = new Label(swtGroup, SWT.NONE); lCP.setText("Clock period / ns:");
		clockPeriodSpinner = new Spinner(swtGroup, SWT.NONE);
		clockPeriodSpinner.setValues(20000, 0, Integer.MAX_VALUE, 0, 100, 1000);
		clockPeriodSpinner.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 1, 1));
		clockPeriodSpinner.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { sequenceTimingEvent(event); } });

		Label lET = new Label(swtGroup, SWT.NONE); lET.setText("Exposure Time / µs:");
		exposureTimeSpinner = new Spinner(swtGroup, SWT.NONE);
		exposureTimeSpinner.setValues(3000, 0, Integer.MAX_VALUE, 0, 1000, 10000);
		exposureTimeSpinner.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 1, 1));
		exposureTimeSpinner.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { sequenceTimingEvent(event); } });

		Label lPT = new Label(swtGroup, SWT.NONE); lPT.setText("Post Exp Time / µs:");
		postExpTimeSpinner = new Spinner(swtGroup, SWT.NONE);
		postExpTimeSpinner.setValues(16000, 0, Integer.MAX_VALUE, 0, 1000, 10000);
		postExpTimeSpinner.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 1, 1));
		postExpTimeSpinner.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { sequenceTimingEvent(event); } });
			
		startButton = new Button(swtGroup, SWT.PUSH);
		startButton.setText("Start");
		startButton.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 1, 1));
		startButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { startButtonEvent(event); } });
		
		advanceButton = new Button(swtGroup, SWT.PUSH);
		advanceButton.setText("Manual Advance");
		advanceButton.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 1, 1));
		advanceButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { advanceButtonEvent(event); } });

		downloadButton = new Button(swtGroup, SWT.PUSH);
		downloadButton.setText("Download Record");
		downloadButton.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 1, 1));
		downloadButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { downloadButtonEvent(event); } });
		
		abortButton = new Button(swtGroup, SWT.PUSH);
		abortButton.setText("Abort");
		abortButton.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 1, 1));
		abortButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { abortButtonEvent(event); } });

		softTriggeringCheckbox = new Button(swtGroup, SWT.CHECK);
		softTriggeringCheckbox.setText("S/W Start and S/W abort at end");
		softTriggeringCheckbox.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 2, 1));
		softTriggeringCheckbox.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { softTriggeringEvent(event); } });
				
		Label lRT = new Label(swtGroup, SWT.NONE); lRT.setText("Restart time / ms:");
		restartTimeSpinner = new Spinner(swtGroup, SWT.NONE);
		restartTimeSpinner.setValues(0, 0, Integer.MAX_VALUE, 0, 1000, 10000);
		restartTimeSpinner.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 1, 1));
		
	}

	public void startButtonEvent(Event event){		
		proc.seqCtrl().initSequence(guiToConfig());
	}
	
	public void softTriggeringEvent(Event event){
		//if turning soft triggering on, set the config 		
		if(softTriggeringCheckbox.getSelection())
			proc.seqCtrl().armSoftTrigger(true, guiToConfig());
		else
			proc.seqCtrl().armSoftTrigger(false, null);
	}
	
	private SequenceConfig guiToConfig() {
		SequenceConfig config = new SequenceConfig();
		
		config.nFrames = numFramesSpinner.getSelection();
		config.flcMode = flcStateCombo.getSelectionIndex();
		config.nStepsPerFrame = stepsPerFrameSpinner.getSelection();
		config.lineTrigger = lineTriggerCheckbox.getSelection();
		config.clockPeriodNS = clockPeriodSpinner.getSelection();
		config.startTriggerPFI = startTriggerCheckbox.getSelection() ? 1 : -1;
		config.exposureTimeUS = exposureTimeSpinner.getSelection();
		config.postExposureTimeUS = postExpTimeSpinner.getSelection();
		
		//take step config from motor section 
		config.stepPeriodUS = proc.getSWTController().getMotorSWTControl().getStepPeriodUS(); 
		config.startDelayUS = startDelaySpinner.getSelection()*1000;
		
		config.abortTrigAtEnd = softTriggeringCheckbox.getSelection();		
		config.restartPeriodMS = restartTimeSpinner.getSelection();
		
		proc.seqCtrl().calcSequence(config);
		
		return config;
	}

	public void abortButtonEvent(Event event){
		proc.seqCtrl().fastAbortSequence();
	}

	public void downloadButtonEvent(Event event){
		proc.seqCtrl().requestSequenceRecord();
	}

	public void advanceButtonEvent(Event event){
		proc.seqCtrl().fastAdvanceSequence();
	}
	
	public void sequenceTimingEvent(Event event){
		SequenceConfig config = guiToConfig();
		
		timingLabel.setText("Step " + config.startPos + " - " + config.endPos + 
				", tFrame = " + (config.frameTimeUS/1000.0) + "ms, " +  
				"tAll = " + (config.totalTimeUS/1.0e6) + "s.");
	}
	
	public void doUpdate() {
		statusLabel.setText(proc.seqCtrl().getStatusString());
	}
}
