
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);
            // TODO check if toString is sufficient
            String target = event.getTarget().toString();
            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().toString(), 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();
        }
    }

}
