/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.chemistry.opencmis.workbench;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.AbstractCellEditor;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.SwingWorker;
import javax.swing.ToolTipManager;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.border.EmptyBorder;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellEditor;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreeNode;

import org.apache.chemistry.opencmis.client.api.ObjectType;
import org.apache.chemistry.opencmis.commons.SessionParameter;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.tck.CmisTest;
import org.apache.chemistry.opencmis.tck.CmisTestGroup;
import org.apache.chemistry.opencmis.tck.CmisTestProgressMonitor;
import org.apache.chemistry.opencmis.tck.CmisTestResult;
import org.apache.chemistry.opencmis.tck.CmisTestResultStatus;
import org.apache.chemistry.opencmis.tck.impl.TestParameters;
import org.apache.chemistry.opencmis.tck.runner.AbstractRunner;
import org.apache.chemistry.opencmis.workbench.checks.SwingReport;
import org.apache.chemistry.opencmis.workbench.icons.TckIcon;
import org.apache.chemistry.opencmis.workbench.model.ClientModel;

/**
 * TCK dialog and runner.
 */
public class TckDialog {

    private final Frame owner;
    private final ClientModel model;
    private final TckDialogRunner runner;

    private Map<CmisTestResultStatus, Integer> status;

    private JProgressBar groupsProgressBar;
    private JProgressBar testsProgressBar;
    private JLabel statusLabel;

    public TckDialog(Frame owner, ClientModel model) {
        this.owner = owner;
        this.model = model;
        this.runner = new TckDialogRunner(model, this);

        status = new HashMap<CmisTestResultStatus, Integer>();
        status.put(CmisTestResultStatus.INFO, 0);
        status.put(CmisTestResultStatus.SKIPPED, 0);
        status.put(CmisTestResultStatus.OK, 0);
        status.put(CmisTestResultStatus.WARNING, 0);
        status.put(CmisTestResultStatus.FAILURE, 0);
        status.put(CmisTestResultStatus.UNEXPECTED_EXCEPTION, 0);

        try {
            runner.loadDefaultTckGroups();
        } catch (Exception e) {
            JOptionPane.showMessageDialog(owner, "Error: " + e.getMessage(), "TCK Error", JOptionPane.ERROR_MESSAGE);
            return;
        }

        new TckSelectDialog();
    }

    private class TckSelectDialog extends JDialog {
        private static final long serialVersionUID = 1L;

        public TckSelectDialog() {
            super(owner, "TCK", true);

            createGUI();
        }

        private void createGUI() {
            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
            setPreferredSize(new Dimension((int) (screenSize.getWidth() / 3), (int) (screenSize.getHeight() / 1.5)));
            setMinimumSize(new Dimension(600, 500));

            setLayout(new BorderLayout());

            // tree
            final DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Groups");
            final JTree groupTree = new JTree(rootNode);

            for (CmisTestGroup group : runner.getGroups()) {
                final TestTreeNode groupNode = new TestTreeNode(groupTree, group);
                rootNode.add(groupNode);
                for (CmisTest test : group.getTests()) {
                    final TestTreeNode testNode = new TestTreeNode(groupTree, test);
                    groupNode.add(testNode);
                }
            }

            ((DefaultTreeModel) groupTree.getModel()).reload();

            groupTree.setRootVisible(false);
            groupTree.setCellRenderer(new TestTreeNodeRender());
            groupTree.setCellEditor(new TestTreeNodeEditor());
            groupTree.setEditable(true);
            ToolTipManager.sharedInstance().registerComponent(groupTree);

            for (int i = 0; i < groupTree.getRowCount(); i++) {
                groupTree.expandRow(i);
            }

            final JPopupMenu treePopup = new JPopupMenu();

            final JMenuItem selectItem = new JMenuItem("Select all");
            selectItem.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    selectAll(groupTree, true);
                }
            });
            treePopup.add(selectItem);

            final JMenuItem deselectItem = new JMenuItem("Deselect all");
            deselectItem.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    selectAll(groupTree, false);
                }
            });
            treePopup.add(deselectItem);

            groupTree.addMouseListener(new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent e) {
                    maybeShowPopup(e);
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                    maybeShowPopup(e);
                }

                private void maybeShowPopup(MouseEvent e) {
                    if (e.isPopupTrigger()) {
                        treePopup.show(e.getComponent(), e.getX(), e.getY());
                    }
                }
            });

            // config panel
            final JPanel configPanel = new JPanel();
            configPanel.setLayout(new BoxLayout(configPanel, BoxLayout.PAGE_AXIS));
            configPanel.setPreferredSize(new Dimension(getWidth() / 2, 500));
            configPanel.setBorder(WorkbenchScale.scaleBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)));

            final JComboBox<String> folderComboBox = addComboBox(configPanel, "Test folder type:",
                    BaseTypeId.CMIS_FOLDER.value(), TestParameters.DEFAULT_FOLDER_TYPE_VALUE, true);
            configPanel.add(Box.createRigidArea(WorkbenchScale.scaleDimension(new Dimension(1, 10))));

            final JComboBox<String> documentComboBox = addComboBox(configPanel, "Test document type:",
                    BaseTypeId.CMIS_DOCUMENT.value(), TestParameters.DEFAULT_DOCUMENT_TYPE_VALUE, true);
            configPanel.add(Box.createRigidArea(WorkbenchScale.scaleDimension(new Dimension(1, 10))));

            final JComboBox<String> relationshipComboBox = addComboBox(configPanel, "Test relationship type:",
                    BaseTypeId.CMIS_RELATIONSHIP.value(), TestParameters.DEFAULT_RELATIONSHIP_TYPE_VALUE, true);
            configPanel.add(Box.createRigidArea(WorkbenchScale.scaleDimension(new Dimension(1, 10))));

            final JComboBox<String> policyComboBox = addComboBox(configPanel, "Test policy type:",
                    BaseTypeId.CMIS_POLICY.value(), TestParameters.DEFAULT_POLICY_TYPE_VALUE, true);
            configPanel.add(Box.createRigidArea(WorkbenchScale.scaleDimension(new Dimension(1, 10))));

            final JComboBox<String> itemComboBox = addComboBox(configPanel, "Test item type:",
                    BaseTypeId.CMIS_ITEM.value(), TestParameters.DEFAULT_ITEM_TYPE_VALUE, true);
            configPanel.add(Box.createRigidArea(WorkbenchScale.scaleDimension(new Dimension(1, 10))));

            final JComboBox<String> secondaryComboBox = addComboBox(configPanel, "Test secondary type:",
                    BaseTypeId.CMIS_SECONDARY.value(), TestParameters.DEFAULT_SECONDARY_TYPE_VALUE, false);
            configPanel.add(Box.createRigidArea(WorkbenchScale.scaleDimension(new Dimension(1, 10))));

            configPanel.add(new JLabel("Test folder path:"));
            final JTextField testParentFolderField = new JTextField(TestParameters.DEFAULT_TEST_FOLDER_PARENT_VALUE);
            testParentFolderField.setMaximumSize(new Dimension(Short.MAX_VALUE, WorkbenchScale.scaleInt(10)));
            testParentFolderField.setAlignmentX(Component.LEFT_ALIGNMENT);
            configPanel.add(testParentFolderField);

            configPanel.add(Box.createVerticalGlue());

            add(configPanel);

            final JPanel mainPanel = new JPanel(new BorderLayout());
            mainPanel.setBorder(WorkbenchScale.scaleBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)));
            mainPanel.add(new JScrollPane(groupTree), BorderLayout.CENTER);
            mainPanel.add(configPanel, BorderLayout.LINE_END);
            add(mainPanel, BorderLayout.CENTER);

            final JButton runButton = new JButton("Run TCK", new TckIcon(ClientHelper.BUTTON_ICON_SIZE,
                    ClientHelper.BUTTON_ICON_SIZE));
            runButton.setDefaultCapable(true);
            runButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent event) {
                    int answer = JOptionPane
                            .showConfirmDialog(
                                    owner,
                                    "Running the TCK may take a long time and may add, remove and alter data in the repository!\n"
                                            + "It also puts at a strain on the repository, performing several thousand calls!\n"
                                            + "\nAre you sure you want to proceed?", "TCK", JOptionPane.YES_NO_OPTION,
                                    JOptionPane.WARNING_MESSAGE);

                    if (answer == JOptionPane.YES_OPTION) {
                        Map<String, String> parameters = runner.getParameters();
                        parameters.put(TestParameters.DEFAULT_FOLDER_TYPE, (String) folderComboBox.getSelectedItem());
                        parameters.put(TestParameters.DEFAULT_DOCUMENT_TYPE,
                                (String) documentComboBox.getSelectedItem());
                        if (relationshipComboBox.isEnabled()) {
                            parameters.put(TestParameters.DEFAULT_RELATIONSHIP_TYPE,
                                    (String) relationshipComboBox.getSelectedItem());
                        }
                        if (policyComboBox.isEnabled()) {
                            parameters.put(TestParameters.DEFAULT_POLICY_TYPE,
                                    (String) policyComboBox.getSelectedItem());
                        }
                        if (itemComboBox.isEnabled()) {
                            parameters.put(TestParameters.DEFAULT_ITEM_TYPE, (String) itemComboBox.getSelectedItem());
                        }
                        if (secondaryComboBox.isEnabled()) {
                            parameters.put(TestParameters.DEFAULT_SECONDARY_TYPE,
                                    (String) secondaryComboBox.getSelectedItem());
                        }
                        parameters.put(TestParameters.DEFAULT_TEST_FOLDER_PARENT, testParentFolderField.getText());

                        runner.setParameters(parameters);

                        dispose();
                        new TckRunDialog();
                    }
                }
            });

            int height = 30;
            height = Math.max(height, getFontMetrics(runButton.getFont()).getHeight() + runButton.getInsets().top
                    + runButton.getInsets().bottom);

            final JPanel runButtonPanel = new JPanel();
            runButtonPanel.setLayout(new BoxLayout(runButtonPanel, BoxLayout.PAGE_AXIS));
            runButtonPanel.setBorder(WorkbenchScale.scaleBorder(BorderFactory.createEmptyBorder(0, 3, 3, 3)));
            runButton.setMaximumSize(new Dimension(Short.MAX_VALUE, height));
            runButtonPanel.add(runButton);

            add(runButtonPanel, BorderLayout.PAGE_END);

            getRootPane().setDefaultButton(runButton);

            ClientHelper.installEscapeBinding(this, getRootPane(), true);

            setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
            pack();
            setLocationRelativeTo(null);
            setVisible(true);
        }

        private void selectAll(final JTree tree, boolean select) {
            for (CmisTestGroup group : runner.getGroups()) {
                group.setEnabled(select);
                for (CmisTest test : group.getTests()) {
                    test.setEnabled(select);
                }
            }

            DefaultTreeModel treeModel = ((DefaultTreeModel) tree.getModel());
            treeModel.nodeChanged((TreeNode) treeModel.getRoot());
        }

        private JComboBox<String> addComboBox(JPanel panel, String title, String rootTypeId, String defaultTypeId,
                boolean creatableOnly) {
            final JLabel label = new JLabel(title);
            label.setAlignmentX(Component.LEFT_ALIGNMENT);
            panel.add(label);

            List<ObjectType> types = model.getTypesAsList(rootTypeId, creatableOnly);
            String[] typeIds = new String[types.size()];

            int i = 0;
            for (ObjectType type : types) {
                typeIds[i++] = type.getId();
            }

            final JComboBox<String> comboBox = new JComboBox<String>(typeIds);
            comboBox.setSelectedItem(defaultTypeId);
            comboBox.setAlignmentX(Component.LEFT_ALIGNMENT);
            comboBox.setMaximumSize(new Dimension(Short.MAX_VALUE, 10));
            comboBox.setEnabled(typeIds.length > 0);
            panel.add(comboBox);

            return comboBox;
        }
    }

    private static class TestTreeNode extends DefaultMutableTreeNode {
        private static final long serialVersionUID = 1L;

        private final JTree tree;
        private final CmisTestGroup group;
        private final CmisTest test;

        public TestTreeNode(JTree tree, CmisTestGroup group) {
            this.tree = tree;
            this.group = group;
            this.test = null;
        }

        public TestTreeNode(JTree tree, CmisTest test) {
            this.tree = tree;
            this.test = test;
            this.group = null;
        }

        public CmisTestGroup getGroup() {
            return group;
        }

        public String getName() {
            if (group != null) {
                return group.getName();
            }

            return test.getName();
        }

        public String getDescription() {
            if (group != null) {
                return group.getDescription();
            }

            return test.getDescription();
        }

        public boolean isEnabled() {
            if (group != null) {
                return group.isEnabled();
            }

            return test.isEnabled();
        }

        public void setEnabled(boolean enabled) {
            DefaultTreeModel treeModel = ((DefaultTreeModel) tree.getModel());

            if (group != null) {
                group.setEnabled(enabled);

                for (int i = 0; i < getChildCount(); i++) {
                    TestTreeNode node = (TestTreeNode) getChildAt(i);
                    node.setEnabled(enabled);
                    treeModel.nodeChanged(node);
                }

                return;
            }

            test.setEnabled(enabled);

            if (enabled) {
                TestTreeNode node = (TestTreeNode) getParent();
                node.getGroup().setEnabled(true);
                treeModel.nodeChanged(node);
            }
        }
    }

    private static class TestTreeNodeRender extends JCheckBox implements TreeCellRenderer {
        private static final long serialVersionUID = 1L;

        private final Color textSelectionColor;
        private final Color textNonSelectionColor;
        private final Color backgroundSelectionColor;
        private final Color backgroundNonSelectionColor;

        public TestTreeNodeRender() {
            textSelectionColor = UIManager.getDefaults().getColor("Tree.selectionForeground");
            textNonSelectionColor = UIManager.getDefaults().getColor("Tree.textForeground");
            backgroundSelectionColor = UIManager.getDefaults().getColor("Tree.selectionBackground");
            backgroundNonSelectionColor = UIManager.getDefaults().getColor("Tree.textBackground");

            Insets margins = UIManager.getDefaults().getInsets("Tree.rendererMargins");
            if (margins != null) {
                setBorder(new EmptyBorder(margins.top, margins.left, margins.bottom, margins.right));
            }
        }

        @Override
        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded,
                boolean leaf, int row, boolean hasFocus) {

            if (sel) {
                setForeground(textSelectionColor);
                setBackground(backgroundSelectionColor);
            } else {
                setForeground(textNonSelectionColor);
                setBackground(backgroundNonSelectionColor);
            }

            if (value instanceof TestTreeNode) {
                TestTreeNode node = (TestTreeNode) value;
                setText(node.getName());
                setSelected(node.isEnabled());
                setToolTipText(node.getDescription());
            } else {
                setText(value == null ? "" : value.toString());
                setToolTipText(null);
            }

            return this;
        }

        @Override
        public void validate() {
        }

        @Override
        public void invalidate() {
        }

        @Override
        public void revalidate() {
        }

        @Override
        public void repaint(long tm, int x, int y, int width, int height) {
        }

        @Override
        public void repaint(Rectangle r) {
        }

        @Override
        public void repaint() {
        }
    }

    private static class TestTreeNodeEditor extends AbstractCellEditor implements TreeCellEditor {
        private static final long serialVersionUID = 1L;

        private TestTreeNodeRender lastObject;

        @Override
        public Object getCellEditorValue() {
            return lastObject;
        }

        @Override
        public Component getTreeCellEditorComponent(JTree tree, final Object value, boolean isSelected,
                boolean expanded, boolean leaf, int row) {

            lastObject = new TestTreeNodeRender();
            lastObject.getTreeCellRendererComponent(tree, value, true, expanded, leaf, row, false);
            lastObject.addItemListener(new ItemListener() {
                @Override
                public void itemStateChanged(ItemEvent itemEvent) {
                    ((TestTreeNode) value).setEnabled(((JCheckBox) itemEvent.getItem()).isSelected());
                    fireEditingStopped();
                }
            });

            return lastObject;
        }
    }

    private class TckRunDialog extends JDialog {
        private static final long serialVersionUID = 1L;

        private final TckTask task;

        public TckRunDialog() {
            super(owner, "TCK");

            createGUI();

            task = new TckTask(this, runner);
            task.execute();
        }

        private void createGUI() {
            setPreferredSize(new Dimension(500, 200));
            setMinimumSize(new Dimension(500, 200));

            setLayout(new BorderLayout());

            JPanel progressPanel = new JPanel();
            progressPanel.setLayout(new BoxLayout(progressPanel, BoxLayout.Y_AXIS));
            progressPanel.setBorder(WorkbenchScale.scaleBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)));

            progressPanel.add(Box.createRigidArea(new Dimension(0, 10)));

            JLabel groupsLabel = new JLabel("Groups:");
            groupsLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
            progressPanel.add(groupsLabel);

            groupsProgressBar = new JProgressBar();
            groupsProgressBar.setMinimumSize(new Dimension(500, 30));
            groupsProgressBar.setPreferredSize(new Dimension(500, 30));
            groupsProgressBar.setMaximumSize(new Dimension(Short.MAX_VALUE, 30));
            groupsProgressBar.setAlignmentX(Component.LEFT_ALIGNMENT);
            groupsProgressBar.setAlignmentY(Component.CENTER_ALIGNMENT);
            progressPanel.add(groupsProgressBar);

            progressPanel.add(Box.createRigidArea(new Dimension(0, 10)));

            JLabel testsLabel = new JLabel("Tests:");
            testsLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
            progressPanel.add(testsLabel);

            testsProgressBar = new JProgressBar();
            testsProgressBar.setMinimumSize(new Dimension(500, 30));
            testsProgressBar.setPreferredSize(new Dimension(500, 30));
            testsProgressBar.setMaximumSize(new Dimension(Short.MAX_VALUE, 30));
            testsProgressBar.setAlignmentX(Component.LEFT_ALIGNMENT);
            testsProgressBar.setAlignmentY(Component.CENTER_ALIGNMENT);
            progressPanel.add(testsProgressBar);

            progressPanel.add(Box.createRigidArea(new Dimension(0, 10)));

            statusLabel = new JLabel();
            progressPanel.add(statusLabel);

            add(progressPanel, BorderLayout.CENTER);

            JButton cancelButton = new JButton("Cancel");
            cancelButton.setDefaultCapable(true);
            cancelButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent event) {
                    task.cancel(true);
                }
            });

            final JPanel cancelButtonPanel = new JPanel();
            cancelButtonPanel.setLayout(new BoxLayout(cancelButtonPanel, BoxLayout.PAGE_AXIS));
            cancelButtonPanel.setBorder(WorkbenchScale.scaleBorder(BorderFactory.createEmptyBorder(0, 3, 3, 3)));
            cancelButton.setMaximumSize(new Dimension(Short.MAX_VALUE, 30));
            cancelButtonPanel.add(cancelButton);

            add(cancelButtonPanel, BorderLayout.PAGE_END);

            getRootPane().setDefaultButton(cancelButton);

            setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
            pack();
            setLocationRelativeTo(null);
            setVisible(true);
        }
    }

    private static class TckDialogRunner extends AbstractRunner {
        public TckDialogRunner(ClientModel model, TckDialog tckDialog) {
            Map<String, String> parameters = new HashMap<String, String>(model.getClientSession()
                    .getSessionParameters());
            parameters.put(SessionParameter.REPOSITORY_ID, model.getClientSession().getSession().getRepositoryInfo()
                    .getId());

            setParameters(parameters);
        }
    }

    private class DialogProgressMonitor implements CmisTestProgressMonitor {

        public DialogProgressMonitor(int numberOfGroups) {
            groupsProgressBar.setStringPainted(true);
            groupsProgressBar.setMinimum(0);
            groupsProgressBar.setMaximum(numberOfGroups);
            groupsProgressBar.setValue(0);
        }

        @Override
        public void startGroup(CmisTestGroup group) {
            groupsProgressBar.setString(group.getName());

            testsProgressBar.setStringPainted(true);
            testsProgressBar.setMinimum(0);
            testsProgressBar.setMaximum(group.getTests().size());
            testsProgressBar.setValue(0);
        }

        @Override
        public void endGroup(CmisTestGroup group) {
            groupsProgressBar.setString("");
            groupsProgressBar.setValue(groupsProgressBar.getValue() + 1);
        }

        @Override
        public void startTest(CmisTest test) {
            testsProgressBar.setString(test.getName());
        }

        @Override
        public void endTest(CmisTest test) {
            testsProgressBar.setString("");
            testsProgressBar.setValue(testsProgressBar.getValue() + 1);

            for (CmisTestResult tr : test.getResults()) {
                int x = status.get(tr.getStatus());
                status.put(tr.getStatus(), x + 1);
            }

            StringBuilder sb = new StringBuilder(128);
            int x;

            sb.append("<html>");

            x = status.get(CmisTestResultStatus.INFO);
            if (x > 0) {
                sb.append("<font color='#000000'>[Info: " + x + "]</font>  ");
            }

            x = status.get(CmisTestResultStatus.SKIPPED);
            if (x > 0) {
                sb.append("<font color='#444444'>[Skipped: " + x + "]</font>  ");
            }

            x = status.get(CmisTestResultStatus.OK);
            if (x > 0) {
                sb.append("<font color='#009900'>[Ok: " + x + "]</font>  ");
            }

            x = status.get(CmisTestResultStatus.WARNING);
            if (x > 0) {
                sb.append("<font color='#999900'>[Warning: " + x + "]</font>  ");
            }

            x = status.get(CmisTestResultStatus.FAILURE);
            if (x > 0) {
                sb.append("<font color='#996000'>[Failure: " + x + "]</font>  ");
            }

            x = status.get(CmisTestResultStatus.UNEXPECTED_EXCEPTION);
            if (x > 0) {
                sb.append("<font color='#990000'>[Exception: " + x + "]</font>  ");
            }

            sb.append("</html>");

            statusLabel.setText(sb.toString());
        }

        @Override
        public void message(String msg) {
        }
    }

    class TckTask extends SwingWorker<Void, Void> {
        private final JDialog dialog;
        private final TckDialogRunner runner;

        public TckTask(JDialog dialog, TckDialogRunner runner) {
            this.dialog = dialog;
            this.runner = runner;
        }

        @Override
        public Void doInBackground() {
            try {
                runner.run(new DialogProgressMonitor(runner.getGroups().size()));
            } catch (InterruptedException ie) {
                runner.cancel();
            } catch (Exception e) {
                JOptionPane
                        .showMessageDialog(owner, "Error: " + e.getMessage(), "TCK Error", JOptionPane.ERROR_MESSAGE);
            }

            return null;
        }

        @Override
        public void done() {
            if (isCancelled()) {
                runner.cancel();
            }

            try {
                SwingReport report = new SwingReport(null, 700, 500);
                report.createReport(runner.getParameters(), runner.getGroups(), (Writer) null);
            } catch (Exception e) {
                JOptionPane.showMessageDialog(owner, "Error: " + e.getMessage(), "Report Error",
                        JOptionPane.ERROR_MESSAGE);
            } finally {
                dialog.dispose();
            }
        }
    }
}
