package de.ugoe.cs.eventbench.swt;

import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;

import de.ugoe.cs.util.console.CommandExecuter;

public class TrainModelDialog extends Dialog {

	protected Object result;
	protected Shell shlTrainUsageModel;
	
	private Button btnFirstorderMarkovModel;
	private Button btnHighorderMarkovModel;
	private Button btnPredictionByPartial;
	private Button btnDeterministicFiniteAutomaton;
	
	private Spinner minOrderSpinner;
	private Spinner maxOrderSpinner;
	private Text modelnameText;
	
	private String[] sequenceNames;
	private Text probEscapeText;
	private Label lblEscapeProbability;

	/**
	 * Create the dialog.
	 * @param parent
	 * @param style
	 */
	public TrainModelDialog(Shell parent, int style) {
		super(parent, style);
		setText("SWT Dialog");
	}

	/**
	 * Open the dialog.
	 * @return the result
	 */
	public Object open() {
		createContents();
		shlTrainUsageModel.open();
		shlTrainUsageModel.layout();
		Display display = getParent().getDisplay();
		while (!shlTrainUsageModel.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
		return result;
	}

	/**
	 * Create contents of the dialog.
	 */
	private void createContents() {
		shlTrainUsageModel = new Shell(getParent(), SWT.DIALOG_TRIM | SWT.MIN | SWT.APPLICATION_MODAL);
		shlTrainUsageModel.setSize(219, 330);
		shlTrainUsageModel.setText("Train Usage Model");
		shlTrainUsageModel.setLayout(new GridLayout(2, false));
		
		Group grpGeneralInformation = new Group(shlTrainUsageModel, SWT.NONE);
		grpGeneralInformation.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1));
		grpGeneralInformation.setText("Name");
		grpGeneralInformation.setLayout(new GridLayout(1, false));
		
		modelnameText = new Text(grpGeneralInformation, SWT.BORDER);
		modelnameText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
		
		Group grpType = new Group(shlTrainUsageModel, SWT.NONE);
		grpType.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1));
		grpType.setText("Type");
		grpType.setLayout(new GridLayout(2, false));
		
		btnFirstorderMarkovModel = new Button(grpType, SWT.RADIO);
		btnFirstorderMarkovModel.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				minOrderSpinner.setEnabled(false);
				maxOrderSpinner.setEnabled(false);
				probEscapeText.setEnabled(false);
			}
		});
		btnFirstorderMarkovModel.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, false, 2, 1));
		btnFirstorderMarkovModel.setText("First-Order Markov Model");
		btnFirstorderMarkovModel.setSelection(true);
		
		btnHighorderMarkovModel = new Button(grpType, SWT.RADIO);
		btnHighorderMarkovModel.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				minOrderSpinner.setEnabled(false);
				maxOrderSpinner.setEnabled(true);
				probEscapeText.setEnabled(false);
			}
		});
		btnHighorderMarkovModel.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, false, 2, 1));
		btnHighorderMarkovModel.setText("High-Order Markov Model");
		
		btnPredictionByPartial = new Button(grpType, SWT.RADIO);
		btnPredictionByPartial.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				minOrderSpinner.setEnabled(true);
				maxOrderSpinner.setEnabled(true);
				probEscapeText.setEnabled(true);
			}
		});
		btnPredictionByPartial.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, true, false, 2, 1));
		btnPredictionByPartial.setText("Prediction by Partial Match");
		
		lblEscapeProbability = new Label(grpType, SWT.NONE);
		lblEscapeProbability.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false, 1, 1));
		lblEscapeProbability.setText("Escape Probability:");
		
		probEscapeText = new Text(grpType, SWT.BORDER);
		probEscapeText.setText("0.1");
		probEscapeText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		probEscapeText.setEnabled(false);
		
		btnDeterministicFiniteAutomaton = new Button(grpType, SWT.RADIO);
		btnDeterministicFiniteAutomaton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				minOrderSpinner.setEnabled(false);
				maxOrderSpinner.setEnabled(false);
				probEscapeText.setEnabled(false);
			}
		});
		btnDeterministicFiniteAutomaton.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, false, 2, 1));
		btnDeterministicFiniteAutomaton.setText("Deterministic Finite Automaton");
		
		Group grpModelProperties = new Group(shlTrainUsageModel, SWT.NONE);
		grpModelProperties.setLayout(new GridLayout(4, false));
		grpModelProperties.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true, 2, 1));
		grpModelProperties.setText("Order");
		
		Label lblMin = new Label(grpModelProperties, SWT.NONE);
		lblMin.setText("Min.");
		
		minOrderSpinner = new Spinner(grpModelProperties, SWT.BORDER);
		minOrderSpinner.setEnabled(false);
		
		Label lblMax = new Label(grpModelProperties, SWT.NONE);
		lblMax.setText("Max.");
		
		maxOrderSpinner = new Spinner(grpModelProperties, SWT.BORDER);
		maxOrderSpinner.setEnabled(false);
		maxOrderSpinner.setMinimum(2);
		
		Button btnTrain = new Button(shlTrainUsageModel, SWT.NONE);
		btnTrain.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				String command = "";
				String modelname = modelnameText.getText();
				if( modelname.equals("")) {
					MessageBox messageBox = new MessageBox(shlTrainUsageModel, SWT.ERROR);
					messageBox.setText("Error");
					messageBox.setMessage("No modelname defined!");
					messageBox.open();
					return;
				}
				if( btnFirstorderMarkovModel.getSelection() ) {
					command = "trainMarkovModel " + modelname + " " + sequenceNames[0];
					
				}
				else if( btnHighorderMarkovModel.getSelection() ) {
					int modelOrder = maxOrderSpinner.getSelection();
					command = "trainMarkovModel " + modelname + " " + sequenceNames[0] + " " + modelOrder;
				}
				else if( btnPredictionByPartial.getSelection() ) {
					int minOrder = minOrderSpinner.getSelection();
					int maxOrder = maxOrderSpinner.getSelection();
					if( minOrder>maxOrder ) {
						MessageBox messageBox = new MessageBox(shlTrainUsageModel, SWT.ERROR);
						messageBox.setText("Error");
						messageBox.setMessage("Min. Order must be smaller than or equal to max. order!");
						messageBox.open();
						return;
					}
					double probEscape = Double.parseDouble(probEscapeText.getText());
					if( probEscape<0.0 || probEscape>1.0) {
						MessageBox messageBox = new MessageBox(shlTrainUsageModel, SWT.ERROR);
						messageBox.setText("Error");
						messageBox.setMessage("Escape probability must be in [0,1]!");
						messageBox.open();
						return;
					}
					command = "trainPPM " + modelname + " " + sequenceNames[0] + " " + probEscape + " " + maxOrder + " " + minOrder;
				}
				else if( btnDeterministicFiniteAutomaton.getSelection() ) {
					command = "trainDFA " + modelname + " " + sequenceNames[0];
				}
				CommandExecuter.getInstance().exec(command);
				for( int i=1; i<sequenceNames.length; i++ ) {
					command = "updateModel " + sequenceNames[i];
					CommandExecuter.getInstance().exec(command);
				}
				shlTrainUsageModel.dispose();
			}
		});
		btnTrain.setText("Train!");
		
		Button btnAbort = new Button(shlTrainUsageModel, SWT.NONE);
		btnAbort.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				shlTrainUsageModel.dispose();
			}
		});
		btnAbort.setText("Abort");

	}
	
	public void setSequenceNames(String[] sequenceNames) {
		this.sequenceNames = sequenceNames;
	}
}
