package de.ugoe.cs.quest.ui.swt;

import java.util.SortedSet;

import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;

import de.ugoe.cs.quest.eventcore.Event;

public class EditSequenceDialog extends Dialog {

	protected Shell shell;
	private Table table;
	private TableColumn tblclmnEventType;
	private TableColumn tblclmnEventTarget;

	private java.util.List<Event<?>> sequence;
	private SortedSet<String> targets;

	/**
	 * Create the dialog.
	 * 
	 * @param parent
	 * @param style
	 */
	public EditSequenceDialog(Shell parent, int style, SortedSet<String> targets) {
		super(parent, style);
		setText("SWT Dialog");
		this.targets = targets;
	}

	/**
	 * Open the dialog.
	 */
	public void open(java.util.List<Event<?>> sequence) {
		this.sequence = sequence;
		createContents();
		shell.open();
		shell.layout();
		Display display = getParent().getDisplay();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
	}

	/**
	 * Create contents of the dialog.
	 */
	private void createContents() {
		shell = new Shell(getParent(), SWT.SHELL_TRIM | SWT.BORDER
				| SWT.APPLICATION_MODAL);
		shell.setSize(450, 300);
		shell.setText(getText());
		shell.setLayout(new GridLayout(3, false));

		table = new Table(shell, SWT.BORDER | SWT.FULL_SELECTION);
		table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1));
		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		tblclmnEventType = new TableColumn(table, SWT.NONE);
		tblclmnEventType.setWidth(100);
		tblclmnEventType.setText("Event Type");

		tblclmnEventTarget = new TableColumn(table, SWT.NONE);
		tblclmnEventTarget.setWidth(100);
		tblclmnEventTarget.setText("Event Target");

		// this listener makes the table entries multiline
		Listener paintListener = new Listener() {
			public void handleEvent(org.eclipse.swt.widgets.Event event) {
				switch (event.type) {
				case SWT.MeasureItem: {
					TableItem item = (TableItem) event.item;
					String text = item.getText(event.index);
					Point size = event.gc.textExtent(text);
					event.width = size.x;
					event.height = Math.max(event.height, size.y);
					break;
				}
				case SWT.PaintItem: {
					TableItem item = (TableItem) event.item;
					String text = item.getText(event.index);
					Point size = event.gc.textExtent(text);
					int offset = event.index == 0 ? Math.max(0,
							(event.height - size.y) / 2) : 0;
					event.gc.drawText(text, event.x, event.y + offset, true);
					break;
				}
				case SWT.EraseItem:
					event.detail &= ~SWT.FOREGROUND;
					break;
				default:
					break;
				}
			}

		};
		table.addListener(SWT.MeasureItem, paintListener);
		table.addListener(SWT.PaintItem, paintListener);
		table.addListener(SWT.EraseItem, paintListener);

		updateTableContents();

		Button btnInsertBefore = new Button(shell, SWT.NONE);
		btnInsertBefore.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				int index = table.getSelectionIndex();
				if (index == -1) {
					MessageBox messageBox = new MessageBox(shell, SWT.ERROR);
					messageBox.setMessage("No event selected!");
					messageBox.setText("Error");
					messageBox.open();
				} else {
					openInsertDialog(index);
				}
			}
		});
		btnInsertBefore.setText("Insert Before");

		Button btnInsertAfter = new Button(shell, SWT.NONE);
		btnInsertAfter.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				int index = table.getSelectionIndex();
				if (index == -1) {
					MessageBox messageBox = new MessageBox(shell, SWT.ERROR);
					messageBox.setMessage("No event selected!");
					messageBox.setText("Error");
					messageBox.open();
				} else {
					openInsertDialog(index + 1);
				}
			}
		});
		btnInsertAfter.setText("Insert After");

		Button btnClose = new Button(shell, SWT.NONE);
		btnClose.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				shell.dispose();
			}
		});
		btnClose.setText("Close");

	}

	private void updateTableContents() {
		table.removeAll();
		for (Event<?> event : sequence) {
			TableItem tableItem = new TableItem(table, SWT.NONE);
			String target = event.getTarget();
			if (target != null) {
				// the target is split into multiple lines, as one line may
				// only  be 259 characters in tables with Windows
				target = target.replace("].", "].\n");
			}
			tableItem.setText(new String[] { event.getType(), target });
		}
		for (int i = 0; i < table.getColumnCount(); i++) {
			table.getColumn(i).pack();
		}
	}

	private void openInsertDialog(int position) {
		InsertAssertionDialog insertDialog = new InsertAssertionDialog(shell,
				SWT.NONE, targets);
		Event<?> event = insertDialog.open();
		if (event != null) {
			sequence.add(position, event);
			updateTableContents();
		}
	}

}
