package imseProc.gmds;

import java.util.ArrayList;

import org.eclipse.swt.SWT;


import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Device;
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;
import org.eclipse.swt.widgets.Text;

import imseProc.core.IMSEProc;
import imseProc.core.ImagePipeController;
import imseProc.core.ImgPipe;
import imseProc.core.ImgSink;
import imseProc.core.ImgSource;
import imseProc.noiseGen.NoiseGenSWTControl;

public class GMDSPipeSWTControl implements ImagePipeController {
	private GMDSPipe pipe;
	
	private Group swtGroup;
	private Text swtExperimentText;
	private Combo swtPathCombo;
	private Spinner swtPulseSpinner;
	private Button swtLoadSaveButton;
	private Button swtEnableMemCacheCheckbox;
	private Label swtInfoLabel;

	private Button saveOnAbortCheckbox;
	
	private Text notesTextBox;
	
	private Button swtAutoCheckbox;
	
	private boolean dataChangeInhibit = false;
	
	public GMDSPipeSWTControl(Composite parent, Integer style, GMDSPipe pipe) {
		swtGroup = new Group(parent, style);
		this.pipe = pipe;
		
		swtGroup.setLayout(new GridLayout(5, false));
		swtGroup.setText("MDS+ CIS " + ((pipe instanceof ImgSource) ? "(Source)" : "(Sink)"));
				
		Label lS = new Label(swtGroup, 0); lS.setText("Status:");
		swtInfoLabel = new Label(swtGroup, SWT.NONE);
		swtInfoLabel.setText("Initialising");
		swtInfoLabel.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 4, 1));
		
		Label lE = new Label(swtGroup, 0); lE.setText("Experiment:");
		swtExperimentText = new Text(swtGroup, 0);
		swtExperimentText.addListener(SWT.Modify, new Listener() { @Override public void handleEvent(Event event) { dataChangingEvent(); } });
		swtExperimentText.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 4, 1));
		
		Label lP = new Label(swtGroup, 0); lP.setText("Path:");
		swtPathCombo = new Combo(swtGroup, SWT.None);
		swtPathCombo.addListener(SWT.Modify, new Listener() { @Override public void handleEvent(Event event) { dataChangingEvent(); } });
		swtPathCombo.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 4, 1));
		
		Label lPN = new Label(swtGroup, 0); lPN.setText("Pulse:");
		swtPulseSpinner = new Spinner(swtGroup, 0);
		swtPulseSpinner.setMinimum(0);
		swtPulseSpinner.setMaximum(Integer.MAX_VALUE);
		swtPulseSpinner.setSelection(-1);
		swtPulseSpinner.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 4, 1));
		swtPulseSpinner.addListener(SWT.Modify, new Listener() { @Override public void handleEvent(Event event) { dataChangingEvent(); } });
		

		swtLoadSaveButton = new Button(swtGroup, SWT.PUSH);
		swtAutoCheckbox = new Button(swtGroup, SWT.CHECK);

		saveOnAbortCheckbox = new Button(swtGroup, SWT.CHECK);
		saveOnAbortCheckbox.setText("Save and advance on abort");		
		saveOnAbortCheckbox.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { autoCheckboxChangeEvent(); } });
		
		
		swtEnableMemCacheCheckbox = new Button(swtGroup, SWT.CHECK);
		swtEnableMemCacheCheckbox.setText("Enable Mem Cache");		
		swtEnableMemCacheCheckbox.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { enableCacheButtonEvent(event); } });
		
		
		if(pipe instanceof ImgSource){
			swtLoadSaveButton.setText("Load");
			swtLoadSaveButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { loadButtonEvent(event); } });
			
			swtAutoCheckbox.setText("Auto Load");
			swtAutoCheckbox.setToolTipText("Load images immediately when pulse number is changed");
		
		}else{
			swtLoadSaveButton.setText("Set/Save");
			swtLoadSaveButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { saveButtonEvent(event); } });
			
			swtAutoCheckbox.setText("Auto Save");
			swtAutoCheckbox.setToolTipText("Save images to current pulse when image set or image content changes");
		
			//Label lAS = new Label(swtGroup, 0); lAS.setText("Autosave on:");			
		}
		swtAutoCheckbox.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
		swtAutoCheckbox.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { autoCheckboxChangeEvent(); } });
		
		notesTextBox = new Text(swtGroup, SWT.MULTI | SWT.V_SCROLL | SWT.BORDER );
		GridData notesGD = new GridData(SWT.FILL, SWT.FILL, true, true, 4, 1);
		notesGD.heightHint = 50;
		notesTextBox.setLayoutData(notesGD);
		//notesTextBox.setText("\n\n\n\n");		
		notesTextBox.addListener(SWT.Modify, new Listener() { @Override public void handleEvent(Event event) { notesChangingEvent(); } });
		
		
		swtExperimentText.setText(pipe.getDefaultExperiment());
		swtPathCombo.setText(pipe.getDefaultPath());
		swtPulseSpinner.setSelection(pipe.getDefaultPulse());
		
		generalControllerUpdate();
	}
	
	public void notesChangingEvent(){
		String notesGUI = notesTextBox.getText();
		String notesMDS = pipe.getNotes(swtExperimentText.getText(), swtPulseSpinner.getSelection());
		if(!notesGUI.equals(notesMDS))
			pipe.setNotes(swtExperimentText.getText(), 
					swtPulseSpinner.getSelection(),
					notesGUI);
	}
		
	public void dataChangingEvent(){
		if(dataChangeInhibit)
			return;
		
		dataChangeInhibit = true;
		
		setTextColour();
		
		String notesGUI = notesTextBox.getText();
		String notesMDS = pipe.getNotes(swtExperimentText.getText(), swtPulseSpinner.getSelection());
		if(!notesGUI.equals(notesMDS))
			notesTextBox.setText(notesMDS);
		
		if((pipe instanceof GMDSSource) &&
				swtAutoCheckbox.getSelection() &&
				!(swtExperimentText.getText().equals(pipe.getExperiment()) && 
						swtPathCombo.getText().equals(pipe.getPath()) && 
						swtPulseSpinner.getSelection() == pipe.getPulse())
				){
			
				((GMDSSource)pipe).loadTarget(
						swtExperimentText.getText(), 
						swtPulseSpinner.getSelection(),
						swtPathCombo.getText());
		}
		
		if(!swtPathCombo.isFocusControl())
			repopulatePathCombo();
		
		dataChangeInhibit = false;
	}
	
	private void repopulatePathCombo() {		
		String current = swtPathCombo.getText(); //never change the current
		
		swtPathCombo.setItems(pipe.getAvailableImageSets(swtExperimentText.getText(), swtPulseSpinner.getSelection()));
		
		swtPathCombo.setText(current);
	}
	
	public void setTextColour(){
		Color textCol;
		if(swtExperimentText.getText().equals(pipe.getExperiment()) && 
				swtPathCombo.getText().equals(pipe.getPath()) && 
				swtPulseSpinner.getSelection() == pipe.getPulse()){
			
			if(pipe instanceof GMDSSource){
				textCol = swtGroup.getDisplay().getSystemColor(((GMDSSource)pipe).isLoading() ? SWT.COLOR_RED : SWT.COLOR_BLACK);
				//swtLoadSaveButton.setEnabled(false);
				
			}else{
				textCol = swtGroup.getDisplay().getSystemColor(SWT.COLOR_BLACK);
			}
			
		}else{
			textCol = swtGroup.getDisplay().getSystemColor(SWT.COLOR_BLUE);
			//swtLoadSaveButton.setEnabled(true);
		}
		
		swtExperimentText.setForeground(textCol);
		swtPathCombo.setForeground(textCol);
		swtPulseSpinner.setForeground(textCol);
		
	}
	
	public void autoCheckboxChangeEvent(){
		if(pipe instanceof GMDSSink){
			boolean autoSave = swtAutoCheckbox.getSelection();
			boolean saveOnAbort = saveOnAbortCheckbox.getSelection();
			((GMDSSink)pipe).setAutoSave(autoSave, autoSave, saveOnAbort, saveOnAbort);
			((GMDSSink)pipe).setData(
					swtExperimentText.getText(), 
					swtPulseSpinner.getSelection(),
					swtPathCombo.getText());
			
		}
	}
		
	public void loadButtonEvent(Event event){
		((GMDSSource)pipe).loadTarget(
				swtExperimentText.getText(), 
				swtPulseSpinner.getSelection(),
				swtPathCombo.getText());
		
		//colour change will be triggered by the controller update
	}

	public void enableCacheButtonEvent(Event event){
		pipe.setCacheEnable(swtEnableMemCacheCheckbox.getSelection());		
	}		

	public void saveButtonEvent(Event event){
		((GMDSSink)pipe).setData(
				swtExperimentText.getText(), 
				swtPulseSpinner.getSelection(),
				swtPathCombo.getText());
		
		((GMDSSink)pipe).save();
	}
	
	public GMDSPipe getSource() { return pipe; };

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

	@Override
	public void generalControllerUpdate() {
		IMSEProc.ensureFinalSWTUpdate(swtGroup.getDisplay(), this, new Runnable() { @Override public void run() { update(); } });
	}

	private void update(){
		
		int status[] = pipe.getLoadSaveStatus();
		String statStr = pipe.getExperiment() + "/" + pipe.getPulse() + ": " +
		                     ((status[0] >= 0) ? (status[0] + " / ") : "All ") 
		                     	+ status[1];
						
		swtInfoLabel.setText(statStr);
					
		if(pipe instanceof GMDSSink){
			boolean autoSave = ((GMDSSink)pipe).getAutoSaveOnImageChange() || ((GMDSSink)pipe).getAutoSaveOnSetChange();
			swtAutoCheckbox.setSelection(autoSave);
		}
		
		setTextColour();
	}
	
	@Override
	public void destroy() {
		swtGroup.dispose();		
		pipe.controllerDestroyed(this);
	}

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