/*******************************************************************************
 * Copyright (C) 2007 The University of Manchester
 *
 *  Modifications to the initial code base are copyright of their
 *  respective authors, or their employers as appropriate.
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License
 *  as published by the Free Software Foundation; either version 2.1 of
 *  the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful, but
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 ******************************************************************************/
package net.sf.taverna.t2.workbench.views.results.processor;

import static java.awt.BorderLayout.CENTER;
import static java.awt.BorderLayout.EAST;
import static java.awt.BorderLayout.NORTH;
import static java.awt.BorderLayout.SOUTH;
import static java.awt.BorderLayout.WEST;
import static java.awt.Color.RED;
import static java.awt.GridBagConstraints.BOTH;
import static java.awt.GridBagConstraints.NONE;
import static java.util.Collections.emptyList;
import static java.util.Collections.sort;
import static java.util.Collections.synchronizedSet;
import static javax.swing.BorderFactory.createEmptyBorder;
import static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED;
import static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED;
import static javax.swing.SwingUtilities.invokeLater;
import static javax.swing.SwingUtilities.isEventDispatchThread;
import static javax.swing.border.EtchedBorder.LOWERED;
import static javax.swing.tree.TreeSelectionModel.SINGLE_TREE_SELECTION;
import static net.sf.taverna.t2.workbench.MainWindow.getMainWindow;
import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.closeIcon;
import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.inputIcon;
import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.outputIcon;
import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.saveAllIcon;
import static net.sf.taverna.t2.workbench.views.results.processor.IterationTreeNode.ErrorState.INPUT_ERRORS;
import static net.sf.taverna.t2.workbench.views.results.processor.IterationTreeNode.ErrorState.OUTPUT_ERRORS;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.nio.file.Path;
import java.sql.Timestamp;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTree;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.EtchedBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreePath;

import net.sf.taverna.t2.facade.WorkflowInstanceFacade;
import net.sf.taverna.t2.facade.WorkflowInstanceFacade.State;
import net.sf.taverna.t2.lang.ui.DialogTextArea;
import net.sf.taverna.t2.provenance.ProvenanceConnectorFactory;
import net.sf.taverna.t2.provenance.api.ProvenanceAccess;
import net.sf.taverna.t2.provenance.lineageservice.utils.Port;
import net.sf.taverna.t2.provenance.lineageservice.utils.ProcessorEnactment;
import net.sf.taverna.t2.reference.ReferenceService;
import net.sf.taverna.t2.reference.T2Reference;
import net.sf.taverna.t2.renderers.RendererRegistry;
import net.sf.taverna.t2.workbench.helper.HelpEnabledDialog;
import net.sf.taverna.t2.workbench.ui.SwingWorkerCompletionWaiter;
import net.sf.taverna.t2.workbench.views.results.processor.FilteredIterationTreeModel.FilterType;
import net.sf.taverna.t2.workbench.views.results.processor.IterationTreeNode.ErrorState;
import net.sf.taverna.t2.workbench.views.results.saveactions.SaveAllResultsSPI;
import net.sf.taverna.t2.workbench.views.results.saveactions.SaveIndividualResultSPI;
import net.sf.taverna.t2.workflowmodel.Dataflow;
import net.sf.taverna.t2.workflowmodel.Processor;
import net.sf.taverna.t2.workflowmodel.ProcessorInputPort;
import net.sf.taverna.t2.workflowmodel.ProcessorOutputPort;
import net.sf.taverna.t2.workflowmodel.utils.Tools;

import org.apache.log4j.Logger;

import uk.org.taverna.configuration.database.DatabaseConfiguration;

/**
 * A component that contains a tabbed pane for displaying inputs and outputs of a processor (i.e.
 * intermediate results for a workflow run).
 *<p>
 *FIXME Needs deleting or converting to DataBundles
 * @author Alex Nenadic
 *
 */
@SuppressWarnings("serial")
public class ProcessorResultsComponent extends JPanel {
	private static final Logger logger = Logger.getLogger(ProcessorResultsComponent.class);
	private static final SimpleDateFormat ISO_8601 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	private static final String HOURS = "h";
	private static final String MINUTES = "m";
	private static final String SECONDS = "s";
	private static final String MILLISECONDS = "ms";

	/**
	 * JSplitPane that contains the invocation list for the processor on the
	 * left and a tabbed pane with processors ports on the right.
	 */
	private JSplitPane splitPane;
	/** Tree containing enactments (invocations) of the processor.*/
	protected JTree processorEnactmentsTree;
	/**
	 * Tabbed pane - each tab contains a processor input/outputs data/results
	 * tree and a RenderedProcessorResultComponent, which in turn contains the
	 * currently selected node rendered according to its MIME type.
	 */
	private JTabbedPane tabbedPane;
	/** Panel containing the title*/
	private JPanel titlePanel;
	private Processor processor;
	@SuppressWarnings("unused")
	private Dataflow dataflow;
	private String runId;
	@SuppressWarnings("unused")
	private ReferenceService referenceService;
	private WorkflowInstanceFacade facade; // in the case this is a fresh run
	boolean resultsUpdateNeeded = false;

	/** Enactments received for this processor */
	private Set<ProcessorEnactment> enactmentsGotSoFar = synchronizedSet(new HashSet<ProcessorEnactment>());
	private Set<String> enactmentIdsGotSoFar = synchronizedSet(new HashSet<String>());

	private Map<String, ProcessorPortResultsViewTab> inputPortTabMap = new ConcurrentHashMap<>();
	private Map<String, ProcessorPortResultsViewTab> outputPortTabMap = new ConcurrentHashMap<>();

	/** All data for intermediate results is pulled from provenance.*/
	private ProvenanceAccess provenanceAccess;
	private ProcessorEnactmentsTreeModel processorEnactmentsTreeModel;
	private FilteredIterationTreeModel filteredTreeModel;

	/**
	 * Map: enactment -> (port, t2Ref, tree).
	 * <p>
	 * Each enactment is mapped to a list of 3-element lists. The 3-element list
	 * contains processor input/output port, t2ref to data consumed/produced on
	 * that port and tree view of the data. Tree is only created on demand -
	 * i.e. when user selects a particular enactment and a specific port.
	 */
	protected Map<ProcessorEnactment, List<List<Object>>> enactmentsToInputPortData = new ConcurrentHashMap<>();
	protected Map<ProcessorEnactment, List<List<Object>>> enactmentsToOutputPortData = new ConcurrentHashMap<>();

	protected Set<ProcessorEnactment> enactmentsWithErrorInputs = synchronizedSet(new HashSet<ProcessorEnactment>());
	protected Set<ProcessorEnactment> enactmentsWithErrorOutputs = synchronizedSet(new HashSet<ProcessorEnactment>());

	private JLabel iterationLabel;
	/**
	 * List of all existing 'save results' actions, each one can save results in
	 * a different format
	 */
	private final List<SaveAllResultsSPI> saveActions;
	private JButton saveAllButton;
	private String processorId = null;
	private List<Processor> processorsPath;
	private ProcessorEnactmentsTreeNode procEnactmentTreeNode = null;
	private final RendererRegistry rendererRegistry;
	private final List<SaveIndividualResultSPI> saveIndividualActions;

	public ProcessorResultsComponent(Processor processor, Dataflow dataflow,
			String runId, ReferenceService referenceService,
			RendererRegistry rendererRegistry,
			List<SaveAllResultsSPI> saveActions,
			List<SaveIndividualResultSPI> saveIndividualActions,
			List<ProvenanceConnectorFactory> provenanceConnectorFactories,
			DatabaseConfiguration databaseConfiguration) {
		super(new BorderLayout());
		this.processor = processor;
		this.rendererRegistry = rendererRegistry;
		this.saveActions = saveActions;
		this.saveIndividualActions = saveIndividualActions;
		this.processorsPath = Tools.getNestedPathForProcessor(processor,
				dataflow);
		this.dataflow = dataflow;
		this.runId = runId;
		this.referenceService = referenceService;
		this.facade = null;
		provenanceAccess = new ProvenanceAccess(
				databaseConfiguration.getConnectorType(),
				provenanceConnectorFactories);
		initComponents();
	}

	public ProcessorResultsComponent(WorkflowInstanceFacade facade, Processor processor,
			Dataflow dataflow, String runId, ReferenceService referenceService,
			RendererRegistry rendererRegistry, List<SaveAllResultsSPI> saveActions,
			List<SaveIndividualResultSPI> saveIndividualActions,
			List<ProvenanceConnectorFactory> provenanceConnectorFactories,
			DatabaseConfiguration databaseConfiguration) {
		super(new BorderLayout());
		this.processor = processor;
		this.rendererRegistry = rendererRegistry;
		this.saveActions = saveActions;
		this.saveIndividualActions = saveIndividualActions;
		this.processorsPath = Tools.getNestedPathForProcessor(processor, dataflow);
		this.dataflow = dataflow;
		this.runId = runId;
		this.referenceService = referenceService;
		this.facade = facade;
		provenanceAccess = new ProvenanceAccess(databaseConfiguration.getConnectorType(), provenanceConnectorFactories);

		/**
		 * Is this still a running wf - do we need to periodically check with
		 * provenance for new results?
		 */
		resultsUpdateNeeded = !(facade.getState().equals(State.cancelled) || facade
				.getState().equals(State.completed));

		initComponents();
	}

	public void initComponents() {
		setBorder(new EtchedBorder());

		titlePanel = new JPanel(new BorderLayout());
		titlePanel.setBorder(new EmptyBorder(5, 0, 5, 0));
		titlePanel.add(new JLabel("Intermediate results for service: " + processor.getLocalName()),
				WEST);

		String title = "<html><body>Intermediate values for the service <b>"
				+ processor.getLocalName() + "</b></body></html>";
		JLabel tableLabel = new JLabel(title);
		titlePanel.add(tableLabel, WEST);
		iterationLabel = new JLabel();
		int spacing = iterationLabel.getFontMetrics(iterationLabel.getFont()).charWidth(' ');
		iterationLabel.setBorder(createEmptyBorder(0, spacing * 5, 0, 0));
		titlePanel.add(iterationLabel, CENTER);

		saveAllButton = new JButton(new SaveAllAction("Save iteration values", this));
		saveAllButton.setEnabled(false);

		titlePanel.add(saveAllButton, EAST);
		add(titlePanel, NORTH);

		tabbedPane = new JTabbedPane();

		// Create enactment to (port, t2ref, tree) lists maps.
		enactmentsToInputPortData = new HashMap<>();
		enactmentsToOutputPortData = new HashMap<>();

		// Processor input ports
		List<ProcessorInputPort> processorInputPorts = new ArrayList<>(
				processor.getInputPorts());
		sort(processorInputPorts, new Comparator<ProcessorInputPort>() {
			@Override
			public int compare(ProcessorInputPort o1, ProcessorInputPort o2) {
				return o1.getName().compareTo(o2.getName());
			}
		});
		for (ProcessorInputPort processorInputPort : processorInputPorts) {
			String portName = processorInputPort.getName();
			ProcessorPortResultsViewTab resultTab = new ProcessorPortResultsViewTab(
					portName, rendererRegistry, saveIndividualActions);
			resultTab.setIsOutputPortTab(false);
			inputPortTabMap.put(portName, resultTab);
			tabbedPane.addTab(portName, inputIcon, resultTab, "Input port "
					+ portName);
		}

		// Processor output ports
		List<ProcessorOutputPort> processorOutputPorts = new ArrayList<>(
				processor.getOutputPorts());
		sort(processorOutputPorts, new Comparator<ProcessorOutputPort>() {
			@Override
			public int compare(ProcessorOutputPort o1, ProcessorOutputPort o2) {
				return o1.getName().compareTo(o2.getName());
			}
		});
		for (ProcessorOutputPort processorOutputPort : processorOutputPorts) {
			String portName = processorOutputPort.getName();
			ProcessorPortResultsViewTab resultTab = new ProcessorPortResultsViewTab(
					portName, rendererRegistry, saveIndividualActions);
			resultTab.setIsOutputPortTab(true);
			outputPortTabMap.put(portName, resultTab);
			tabbedPane.addTab(portName, outputIcon, resultTab, "Output port "
					+ portName);
		}

		processorEnactmentsTreeModel = new ProcessorEnactmentsTreeModel(enactmentsGotSoFar,
				enactmentsWithErrorInputs, enactmentsWithErrorOutputs);
		filteredTreeModel = new FilteredIterationTreeModel(processorEnactmentsTreeModel);
		processorEnactmentsTree = new JTree(filteredTreeModel);
		processorEnactmentsTree.setRootVisible(false);
		processorEnactmentsTree.setShowsRootHandles(true);
		processorEnactmentsTree.getSelectionModel().setSelectionMode(
				SINGLE_TREE_SELECTION);
		// Start listening for selections in the enactments tree
		processorEnactmentsTree.addTreeSelectionListener(new TreeSelectionListener() {
			@Override
			public void valueChanged(TreeSelectionEvent e) {
				// Change the result for the selected enactment in the
				// current tab
				setDataTreeForResultTab();
			}
		});
		processorEnactmentsTree.setCellRenderer(new DefaultTreeCellRenderer() {
			@Override
			public Component getTreeCellRendererComponent(JTree tree, Object value,
					boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
				super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row,
						hasFocus);
				if (value instanceof IterationTreeNode) {
					IterationTreeNode iterationTreeNode = (IterationTreeNode) value;
					ErrorState errorState = iterationTreeNode.getErrorState();
					if (errorState.equals(OUTPUT_ERRORS))
						setForeground(RED);
					else if (errorState.equals(INPUT_ERRORS))
						setForeground(new Color(0xdd, 0xa7, 0x00));
				}
				return this;
			}
		});

		// Register a tab change listener
		tabbedPane.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent evt) {
				setDataTreeForResultTab();
			}
		});

		splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
		splitPane.setBottomComponent(tabbedPane);

		final JComboBox<FilterType> filterChoiceBox = new JComboBox<>(
				new FilterType[] { FilterType.ALL, FilterType.RESULTS,
						FilterType.ERRORS, FilterType.SKIPPED });
		filterChoiceBox.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				filteredTreeModel.setFilter((FilterType) filterChoiceBox.getSelectedItem());
				ProcessorResultsComponent.this.updateTree();
			}
		});

		filterChoiceBox.setSelectedIndex(0);
		JPanel enactmentsTreePanel = new JPanel(new BorderLayout());
		JPanel enactmentsComboPanel = new JPanel(new BorderLayout());
		enactmentsComboPanel.add(filterChoiceBox, BorderLayout.WEST);
		enactmentsTreePanel.add(enactmentsComboPanel, NORTH);
		enactmentsTreePanel.add(new JScrollPane(processorEnactmentsTree,
				VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED),
				CENTER);
		splitPane.setTopComponent(enactmentsTreePanel);
		add(splitPane, CENTER);

		resultsUpdateNeeded = true;
		update();
	}

	public static String formatMilliseconds(long timeInMiliseconds) {
		double timeInSeconds;
		if (timeInMiliseconds < 1000)
			return timeInMiliseconds + " " + MILLISECONDS;
		NumberFormat numberFormat = NumberFormat.getNumberInstance();
		numberFormat.setMaximumFractionDigits(1);
		numberFormat.setMinimumFractionDigits(1);
		timeInSeconds = timeInMiliseconds / 1000.0;
		if (timeInSeconds < 60)
			return numberFormat.format(timeInSeconds) + " " + SECONDS;
		double timeInMinutes = timeInSeconds / 60.0;
		if (timeInMinutes < 60)
			return numberFormat.format(timeInMinutes) + " " + MINUTES;
		double timeInHours = timeInMinutes / 60.0;
		return numberFormat.format(timeInHours) + " " + HOURS;
	}

	private void setDataTreeForResultTab() {
		final ProcessorPortResultsViewTab selectedResultTab = (ProcessorPortResultsViewTab) tabbedPane
				.getSelectedComponent();
		if (processorEnactmentsTree.getSelectionModel().isSelectionEmpty()) {
			disableResultTabForNode(selectedResultTab, null);
			return;
		}
		TreePath selectedPath = processorEnactmentsTree.getSelectionModel()
				.getSelectionPath();
		Object lastPathComponent = selectedPath.getLastPathComponent();
		if (!(lastPathComponent instanceof ProcessorEnactmentsTreeNode)) {
			// Just an IterationTreeNode along the way, no data to show
			disableResultTabForNode(selectedResultTab,
					(DefaultMutableTreeNode) lastPathComponent);
			return;
		}

		procEnactmentTreeNode = (ProcessorEnactmentsTreeNode) lastPathComponent;
		ProcessorEnactment processorEnactment = (ProcessorEnactment) procEnactmentTreeNode
				.getUserObject();

		if (!processorEnactment.getProcessorId().equals(processorId)) {
			/*
			 * It's not our processor, must be a nested workflow iteration,
			 * which we should not show
			 */
			disableResultTabForNode(selectedResultTab, procEnactmentTreeNode);
			return;
		}

		// Update iterationLabel
		StringBuilder iterationLabelText = labelForProcEnactment(procEnactmentTreeNode,
				processorEnactment);
		iterationLabel.setText(iterationLabelText.toString());
		saveAllButton.setEnabled(true);

		Map<ProcessorEnactment, List<List<Object>>> map;
		if (selectedResultTab.getIsOutputPortTab()) // output port tab
			map = enactmentsToOutputPortData;
		else // input port tab
			map = enactmentsToInputPortData;
		List<List<Object>> listOfListsOfPortData = map.get(processorEnactment);
		if (listOfListsOfPortData == null)
			listOfListsOfPortData = emptyList();

		JTree tree = null;
		/*
		 * Get the tree for this port and this enactment and show it on results
		 * tab
		 */
		for (List<Object> listOfPortData : listOfListsOfPortData)
			// Find data in the map for this port
			if (selectedResultTab.getPortName().equals(
					((Port) listOfPortData.get(0)).getPortName())) {
				// list.get(0) contains the port
				// list.get(1) contains the t2Ref to data
				// list.get(2) contains the tree
				if (listOfPortData.get(2) == null)
					// tree has not been created yet
					tree = createTreeForPort(selectedResultTab,
							processorEnactment, map, listOfListsOfPortData,
							listOfPortData);
				else
					tree = updateTreeForPort(selectedResultTab, listOfPortData);
				break;
			}

		// Show the tree
		selectedResultTab.setResultsTree(tree);
	}

	private JTree createTreeForPort(ProcessorPortResultsViewTab selectedTab,
			ProcessorEnactment enactment,
			Map<ProcessorEnactment, List<List<Object>>> map,
			List<List<Object>> listOfPortDataLists, List<Object> portDataList) {
		// Clear previously shown rendered result, if any
		RenderedProcessorResultComponent renderedResultComponent = selectedTab
				.getRenderedResultComponent();
		renderedResultComponent.clearResult();

		// Create a tree for this data
		ProcessorResultsTreeModel treeModel = new ProcessorResultsTreeModel(
				(Path) portDataList.get(1));
		JTree tree = new JTree(new FilteredProcessorValueTreeModel(treeModel));
		/*
		 * Remember this triple and its index in the big list so we can update
		 * the map for this enactment after we have finished iterating
		 */
		int index = listOfPortDataLists.indexOf(portDataList);
		tree.getSelectionModel().setSelectionMode(SINGLE_TREE_SELECTION);
		tree.setExpandsSelectedPaths(true);
		tree.setRootVisible(false);
		tree.setShowsRootHandles(true);
		tree.setCellRenderer(new ProcessorResultCellRenderer());
		// Expand the whole tree
		/*
		 * for (int row = 0; row < tree.getRowCount(); row++) { tree.expandRow(row); }
		 */
		tree.addTreeSelectionListener(new TreeSelectionListener() {
			@Override
			public void valueChanged(TreeSelectionEvent e) {
				TreePath selectionPath = e.getNewLeadSelectionPath();
				if (selectionPath != null) {
					// Get the selected node
					Object selectedNode = selectionPath.getLastPathComponent();
					ProcessorPortResultsViewTab selectedResultTab = (ProcessorPortResultsViewTab) tabbedPane
							.getSelectedComponent();
					selectedResultTab.getRenderedResultComponent().setNode(
							(ProcessorResultTreeNode) selectedNode);
				}
			}
		});

		portDataList.set(2, tree); // set the new tree
		if (index != -1) {
			/*
			 * Put the tree in the map and put the modified list back to the map
			 */
			listOfPortDataLists.set(index, portDataList);
			map.put(enactment, listOfPortDataLists);
		}
		return tree;
	}

	private JTree updateTreeForPort(ProcessorPortResultsViewTab selectedTab,
			List<Object> portDataList) {
		JTree tree = (JTree) portDataList.get(2);
		/*
		 * Show the right value in the rendering component i.e. render the
		 * selected value for this port and this enactment if anything was
		 * selected in the result for port tree.
		 */
		TreePath selectionPath = tree.getSelectionPath();
		if (selectionPath != null) {
			// Get the selected node
			Object selectedNode = selectionPath.getLastPathComponent();
			selectedTab.getRenderedResultComponent().setNode(
					(ProcessorResultTreeNode) selectedNode);
		}
		return tree;
	}

	private void disableResultTabForNode(final ProcessorPortResultsViewTab selectedResultTab,
			DefaultMutableTreeNode lastPathComponent) {
		selectedResultTab.setResultsTree(null);
		String label = labelForNode(lastPathComponent);
		iterationLabel.setText(label);
		saveAllButton.setEnabled(false);
	}

	private StringBuilder labelForProcEnactment(ProcessorEnactmentsTreeNode procEnactmentTreeNode,
			ProcessorEnactment processorEnactment) {
		StringBuilder iterationLabelText = new StringBuilder();
		// Use <html> so we can match font metrics of titleJLabel
		iterationLabelText.append("<html><body>");
		iterationLabelText.append(procEnactmentTreeNode);
		Timestamp started = processorEnactment.getEnactmentStarted();
		Timestamp ended = processorEnactment.getEnactmentEnded();
		if (started != null) {
			if (procEnactmentTreeNode.getErrorState() == INPUT_ERRORS)
				iterationLabelText.append(" <font color='#cc9700'>skipped</font> ");
			else
				iterationLabelText.append(" started ");
			iterationLabelText.append(ISO_8601.format(started));
		}
		if (ended != null
				&& procEnactmentTreeNode.getErrorState() != INPUT_ERRORS) {
			// Don't show End time if there was input errors

			if (started != null) {
				iterationLabelText.append(", ");
			}
			if (procEnactmentTreeNode.getErrorState() == OUTPUT_ERRORS)
				iterationLabelText.append(" <font color='red'>failed</font> ");
			else
				iterationLabelText.append(" ended ");
			iterationLabelText.append(ISO_8601.format(ended));
			if (started != null) {
				long duration = ended.getTime() - started.getTime();
				iterationLabelText.append(" (");
				iterationLabelText.append(formatMilliseconds(duration));
				iterationLabelText.append(")");
			}
		}
		iterationLabelText.append("</body></html>");
		return iterationLabelText;
	}

	private String labelForNode(DefaultMutableTreeNode node) {
		if (node == null)
			return "No selection";
		StringBuilder label = new StringBuilder();
		label.append(node);
		if (node.getUserObject() != null) {
			label.append(" containing ");
			label.append(node.getLeafCount());
			label.append(" iterations");
		}
		return label.toString();
	}

	public void populateEnactmentsMaps() {
		synchronized (enactmentsGotSoFar) {
			// Get processor enactments (invocations) from provenance

			// Create the array of nested processors' names
			String[] processorNamesPath = null;
			if (processorsPath != null) { // should not be null really
				processorNamesPath = new String[processorsPath.size()];
				int i = 0;
				for (Processor proc : processorsPath)
					processorNamesPath[i++] = proc.getLocalName();
			} else { // This should not really happen!
				processorNamesPath = new String[1];
				processorNamesPath[0] = processor.getLocalName();
			}

			List<ProcessorEnactment> processorEnactmentsStack = provenanceAccess
					.getProcessorEnactments(runId, processorNamesPath);

			if (processorId == null && !processorEnactmentsStack.isEmpty()) {
				// Extract processor ID from very first processorEnactment
				processorId = processorEnactmentsStack.get(0).getProcessorId();
			}

			while (!processorEnactmentsStack.isEmpty()) {
				// fetch LAST one first, so we'll get the parent's early
				ProcessorEnactment processorEnactment = processorEnactmentsStack
						.remove(processorEnactmentsStack.size() - 1);
				if (!enactmentsGotSoFar.contains(processorEnactment)) {
					enactmentsGotSoFar.add(processorEnactment);
					enactmentIdsGotSoFar.add(processorEnactment
							.getProcessEnactmentId());

					String parentId = processorEnactment
							.getParentProcessorEnactmentId();
					if (parentId != null
							&& !enactmentIdsGotSoFar.contains(parentId)) {
						/*
						 * Also add parent (and their parent, etc) - so that we
						 * can show the full iteration treeenactmentIdsGotSoFar
						 */
						ProcessorEnactment parentEnactment = provenanceAccess
								.getProcessorEnactment(parentId);
						if (parentEnactment == null) {
							logger.error("Could not find parent processor enactment id="
									+ parentId
									+ ", skipping "
									+ processorEnactment);
							enactmentsGotSoFar.remove(processorEnactment);
							enactmentIdsGotSoFar.remove(processorEnactment);
							continue;
						}
						processorEnactmentsStack.add(parentEnactment);
					}
				}
				if (!processorEnactment.getProcessorId().equals(processorId))
					// A parent processors, no need to fetch their data bindings
					continue;

				String initialInputs = processorEnactment.getInitialInputsDataBindingId();
				String finalOutputs = processorEnactment.getFinalOutputsDataBindingId();

				boolean fetchingInputs = initialInputs != null
						&& !enactmentsToInputPortData.containsKey(processorEnactment);
				boolean fetchingOutputs = finalOutputs != null
						&& !enactmentsToOutputPortData.containsKey(processorEnactment);

				Map<Port, T2Reference> dataBindings = new HashMap<Port, T2Reference>();

				if (fetchingInputs) {
					dataBindings = provenanceAccess.getDataBindings(initialInputs);
					enactmentsToInputPortData
							.put(processorEnactment, new ArrayList<List<Object>>());
				}
				if (fetchingOutputs) {
					enactmentsToOutputPortData.put(processorEnactment,
							new ArrayList<List<Object>>());
					if (!fetchingInputs
							|| (finalOutputs != null && !finalOutputs
									.equals(initialInputs)))
						dataBindings.putAll(provenanceAccess.getDataBindings(finalOutputs));
				}

				for (Entry<Port, T2Reference> entry : dataBindings.entrySet()) {
					/*
					 * Create (port, t2Ref, tree) list for this enactment. Tree
					 * is set to null initially and populated on demand (when
					 * user clicks on particular enactment/iteration node).
					 */
					List<Object> dataOnPortList = new ArrayList<>();
					Port port = entry.getKey();
					dataOnPortList.add(port); // port
					T2Reference t2Reference = entry.getValue();
					dataOnPortList.add(t2Reference); // t2Ref
					/*
					 * tree (will be populated when a user clicks on this iteration and this port
					 * tab is selected)
					 */
					dataOnPortList.add(null);

					if (port.isInputPort() && fetchingInputs) { // Input port
						if (t2Reference.containsErrors())
							enactmentsWithErrorInputs.add(processorEnactment);
						List<List<Object>> listOfPortDataLists = enactmentsToInputPortData
								.get(processorEnactment);
						listOfPortDataLists.add(dataOnPortList);
						enactmentsToInputPortData.put(processorEnactment, listOfPortDataLists);
					} else if (!port.isInputPort() && fetchingOutputs) { // output port
						if (t2Reference.containsErrors())
							enactmentsWithErrorOutputs.add(processorEnactment);
						List<List<Object>> listOfPortDataLists = enactmentsToOutputPortData
								.get(processorEnactment);
						listOfPortDataLists.add(dataOnPortList);
						enactmentsToOutputPortData.put(processorEnactment, listOfPortDataLists);
					}
				}
			}
		}
	}

	private List<TreePath> expandedPaths = new ArrayList<>();
	private TreePath selectionPath = null;

	private void rememberPaths() {
		expandedPaths.clear();
		for (Enumeration<?> e = processorEnactmentsTree
				.getExpandedDescendants(new TreePath(filteredTreeModel
						.getRoot())); (e != null) && e.hasMoreElements();)
			expandedPaths.add((TreePath) e.nextElement());
		selectionPath = processorEnactmentsTree.getSelectionPath();
	}

	private void reinstatePaths() {
		for (TreePath path : expandedPaths)
			if (filteredTreeModel.isShown((DefaultMutableTreeNode) path
					.getLastPathComponent()))
				processorEnactmentsTree.expandPath(path);
		if (selectionPath != null) {
			if (filteredTreeModel
					.isShown((DefaultMutableTreeNode) selectionPath
							.getLastPathComponent()))
				processorEnactmentsTree.setSelectionPath(selectionPath);
			else
				processorEnactmentsTree.clearSelection();
		}
	}

	public void updateTree() {
		rememberPaths();
		processorEnactmentsTreeModel.update(enactmentsGotSoFar);
		filteredTreeModel.reload();
		reinstatePaths();
		DefaultMutableTreeNode firstLeaf = ((DefaultMutableTreeNode) filteredTreeModel
				.getRoot()).getFirstLeaf();
		if ((firstLeaf != null)
				&& (processorEnactmentsTree.getPathForRow(0) == null))
			processorEnactmentsTree.scrollPathToVisible(new TreePath(
					(Object[]) firstLeaf.getPath()));

		if (facade == null)
			resultsUpdateNeeded = false;
		setDataTreeForResultTab();
	}

	private Runnable updateTreeRunnable = new Runnable() {
		@Override
		public void run() {
			updateTree();
		}
	};

	public void update() {
		if (resultsUpdateNeeded) {
			IntermediateValuesSwingWorker intermediateValuesSwingWorker = new IntermediateValuesSwingWorker(
					this);
			IntermediateValuesInProgressDialog dialog = new IntermediateValuesInProgressDialog();
			intermediateValuesSwingWorker
					.addPropertyChangeListener(new SwingWorkerCompletionWaiter(
							dialog));
			intermediateValuesSwingWorker.execute();

			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
			}
			if (!intermediateValuesSwingWorker.isDone())
				dialog.setVisible(true);
			if (intermediateValuesSwingWorker.getException() != null)
				logger.error("Populating enactments failed",
						intermediateValuesSwingWorker.getException());
			else if (isEventDispatchThread())
				updateTreeRunnable.run();
			else
				invokeLater(updateTreeRunnable);
		}
	}

	public void clear() {
		tabbedPane.removeAll();
	}

	public void onDispose() {
	}

	@Override
	protected void finalize() throws Throwable {
		onDispose();
	}

	private class SaveAllAction extends AbstractAction {
		// private WorkflowResultsComponent parent;

		public SaveAllAction(String name, ProcessorResultsComponent resultViewComponent) {
			super(name);
			// this.parent = resultViewComponent;
			putValue(SMALL_ICON, saveAllIcon);
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			ProcessorEnactment processorEnactment = (ProcessorEnactment) procEnactmentTreeNode
					.getUserObject();

			String initialInputs = processorEnactment.getInitialInputsDataBindingId();
			String finalOutputs = processorEnactment.getFinalOutputsDataBindingId();

			Map<String, T2Reference> inputBindings = new TreeMap<>();
			for (Entry<Port, T2Reference> entry : provenanceAccess
					.getDataBindings(initialInputs).entrySet())
				inputBindings.put(entry.getKey().getPortName(),
						entry.getValue());
			Map<String, T2Reference> outputBindings = new TreeMap<>();
			for (Entry<Port, T2Reference> entry : provenanceAccess
					.getDataBindings(finalOutputs).entrySet())
				outputBindings.put(entry.getKey().getPortName(),
						entry.getValue());

			String title = "Service iteration data saver";

			final JDialog dialog = new HelpEnabledDialog(getMainWindow(),
					title, true);
			dialog.setResizable(false);
			dialog.setLocationRelativeTo(getMainWindow());
			JPanel panel = new JPanel(new BorderLayout());
			DialogTextArea explanation = new DialogTextArea();
			explanation
					.setText("Select the service input and output ports to save the associated data");
			explanation.setColumns(40);
			explanation.setEditable(false);
			explanation.setOpaque(false);
			explanation.setBorder(new EmptyBorder(5, 20, 5, 20));
			explanation.setFocusable(false);
			explanation.setFont(new JLabel().getFont()); // make the font the same as for other
															// components in the dialog
			panel.add(explanation, NORTH);
			final Map<String, JCheckBox> inputChecks = new HashMap<>();
			final Map<String, JCheckBox> outputChecks = new HashMap<>();
			final Map<JCheckBox, T2Reference> checkReferences = new HashMap<>();
			final Map<String, T2Reference> chosenReferences = new HashMap<>();
			final Set<Action> actionSet = new HashSet<Action>();

			ItemListener listener = new ItemListener() {
				@Override
				public void itemStateChanged(ItemEvent e) {
					JCheckBox source = (JCheckBox) e.getItemSelectable();
					if (inputChecks.containsValue(source)
							&& source.isSelected()
							&& outputChecks.containsKey(source.getText()))
						outputChecks.get(source.getText()).setSelected(false);
					if (outputChecks.containsValue(source)
							&& source.isSelected()
							&& inputChecks.containsKey(source.getText()))
						inputChecks.get(source.getText()).setSelected(false);
					chosenReferences.clear();
					for (JCheckBox checkBox : checkReferences.keySet())
						if (checkBox.isSelected())
							chosenReferences.put(checkBox.getText(),
									checkReferences.get(checkBox));
				}
			};
			JPanel portsPanel = new JPanel(new GridBagLayout());
			portsPanel.setBorder(new CompoundBorder(new EmptyBorder(new Insets(
					5, 10, 5, 10)), new EtchedBorder(LOWERED)));
			if (!inputBindings.isEmpty()) {
				GridBagConstraints gbc = new GridBagConstraints();
				gbc.gridx = 0;
				gbc.gridy = 0;
				gbc.anchor = GridBagConstraints.WEST;
				gbc.fill = NONE;
				gbc.weightx = 0.0;
				gbc.weighty = 0.0;
				gbc.insets = new Insets(5, 10, 5, 10);
				portsPanel.add(new JLabel("Iteration inputs:"), gbc);
				// JPanel inputsPanel = new JPanel();
				// WeakHashMap<String, T2Reference> pushedDataMap = null;

				TreeMap<String, JCheckBox> sortedBoxes = new TreeMap<>();
				for (Entry<String, T2Reference> inputEntry : inputBindings
						.entrySet()) {
					String portName = inputEntry.getKey();
					T2Reference o = inputEntry.getValue();
					JCheckBox checkBox = new JCheckBox(portName);
					checkBox.setSelected(!outputBindings.containsKey(portName));
					checkBox.addItemListener(listener);
					inputChecks.put(portName, checkBox);
					sortedBoxes.put(portName, checkBox);
					checkReferences.put(checkBox, o);
				}
				gbc.insets = new Insets(0, 10, 0, 10);
				for (String portName : sortedBoxes.keySet()) {
					gbc.gridy++;
					portsPanel.add(sortedBoxes.get(portName), gbc);
				}
				gbc.gridy++;
				gbc.fill = BOTH;
				gbc.weightx = 1.0;
				gbc.weighty = 1.0;
				gbc.insets = new Insets(5, 10, 5, 10);
				portsPanel.add(new JLabel(""), gbc); // empty space
			}
			if (!outputBindings.isEmpty()) {
				GridBagConstraints gbc = new GridBagConstraints();
				gbc.gridx = 1;
				gbc.gridy = 0;
				gbc.anchor = GridBagConstraints.WEST;
				gbc.fill = NONE;
				gbc.weightx = 0.0;
				gbc.weighty = 0.0;
				gbc.insets = new Insets(5, 10, 5, 10);
				portsPanel.add(new JLabel("Iteration outputs:"), gbc);
				TreeMap<String, JCheckBox> sortedBoxes = new TreeMap<>();
				for (Entry<String, T2Reference> outputEntry : outputBindings.entrySet()) {
					String portName = outputEntry.getKey();
					T2Reference o = outputEntry.getValue();
					JCheckBox checkBox = new JCheckBox(portName);
					checkBox.setSelected(true);

					checkReferences.put(checkBox, o);
					checkBox.addItemListener(listener);
					outputChecks.put(portName, checkBox);
					sortedBoxes.put(portName, checkBox);
				}
				gbc.insets = new Insets(0, 10, 0, 10);
				for (String portName : sortedBoxes.keySet()) {
					gbc.gridy++;
					portsPanel.add(sortedBoxes.get(portName), gbc);
				}
				gbc.gridy++;
				gbc.fill = BOTH;
				gbc.weightx = 1.0;
				gbc.weighty = 1.0;
				gbc.insets = new Insets(5, 10, 5, 10);
				portsPanel.add(new JLabel(""), gbc); // empty space
			}
			panel.add(portsPanel, CENTER);
			chosenReferences.clear();
			for (JCheckBox checkBox : checkReferences.keySet())
				if (checkBox.isSelected())
					chosenReferences.put(checkBox.getText(),
							checkReferences.get(checkBox));

			JPanel buttonsBar = new JPanel();
			buttonsBar.setLayout(new FlowLayout());
			// Get all existing 'Save result' actions
			for (SaveAllResultsSPI spi : saveActions) {
				AbstractAction action = spi.getAction();
				actionSet.add(action);
				JButton saveButton = new JButton((AbstractAction) action);
				if (action instanceof SaveAllResultsSPI) {
					// ((SaveAllResultsSPI) action).setChosenReferences(chosenReferences);
					((SaveAllResultsSPI) action).setParent(dialog);
				}
				// saveButton.setEnabled(true);
				buttonsBar.add(saveButton);
			}
			JButton cancelButton = new JButton("Cancel", closeIcon);
			cancelButton.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					dialog.setVisible(false);
				}
			});
			buttonsBar.add(cancelButton);
			panel.add(buttonsBar, SOUTH);
			panel.revalidate();
			dialog.add(panel);
			dialog.pack();
			dialog.setVisible(true);
		}
	}
}
