/*******************************************************************************
 * Copyright (c) 2009, 2015 Xored Software Inc and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Xored Software Inc - initial API and implementation and/or initial documentation
 *******************************************************************************/
package org.eclipse.rcptt.sherlock.ui.reportdetails;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.draw2d.Border;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.GridLayout;
import org.eclipse.draw2d.Layer;
import org.eclipse.draw2d.LightweightSystem;
import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.MouseEvent;
import org.eclipse.draw2d.MouseListener;
import org.eclipse.draw2d.MouseMotionListener;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.EMap;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.rcptt.profiling.core.SherlockJobsCore;
import org.eclipse.rcptt.sherlock.core.model.sherlock.report.Event;
import org.eclipse.rcptt.sherlock.core.model.sherlock.report.EventKind;
import org.eclipse.rcptt.sherlock.core.model.sherlock.report.EventSource;
import org.eclipse.rcptt.sherlock.core.model.sherlock.report.Node;
import org.eclipse.rcptt.sherlock.core.model.sherlock.report.Report;
import org.eclipse.rcptt.sherlock.core.reporting.SimpleReportGenerator;
import org.eclipse.rcptt.sherlock.jobs.jobs.AsyncEventInfo;
import org.eclipse.rcptt.sherlock.jobs.jobs.AsyncInfo;
import org.eclipse.rcptt.sherlock.jobs.jobs.JobEventInfo;
import org.eclipse.rcptt.sherlock.jobs.jobs.JobInfo;
import org.eclipse.rcptt.sherlock.ui.reportdetails.figures.EventFigure;
import org.eclipse.rcptt.sherlock.ui.reportdetails.figures.NodeFigure;
import org.eclipse.rcptt.sherlock.ui.reportdetails.figures.SourceFigure;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.ScrollBar;

public class ReportTimelineComposite {
	private List<Node> nodes = new ArrayList<Node>();
	private Canvas imageCanvas;
	private ScrolledComposite sc;

	private Figure figureParent;
	private LightweightSystem lws;
	private StyledText infoText;
	private int timeWidth = 600;
	private boolean includeTasks = true;
	private ColorManager colors = new ColorManager(true);
	private long minTime;
	private long maxTime;
	private boolean showBegined = true;

	public ReportTimelineComposite(Report report2, Composite control) {
		SashForm sform = new SashForm(control, SWT.VERTICAL | SWT.SMOOTH);
		sform.setLayout(new org.eclipse.swt.layout.GridLayout(1, false));
		GridDataFactory.fillDefaults().hint(200, 100).grab(true, true)
				.applyTo(sform);
		sc = new ScrolledComposite(sform, SWT.H_SCROLL | SWT.V_SCROLL
				| SWT.BORDER);

		imageCanvas = new Canvas(sc, SWT.DOUBLE_BUFFERED);
		sc.setContent(imageCanvas);
		final Color color = imageCanvas.getDisplay().getSystemColor(
				SWT.COLOR_WHITE);
		sc.setBackground(new Color(color.getDevice(), color.getRGB()));
		imageCanvas.setBackground(new Color(color.getDevice(), color.getRGB()));

		updateBounds(50, 50);
		GridDataFactory.fillDefaults().hint(200, 100).grab(true, true)
				.applyTo(sc);
		lws = new LightweightSystem(imageCanvas);
		figureParent = new Layer();
		GridLayout gl = new GridLayout(1, true);
		gl.horizontalSpacing = 0;
		gl.verticalSpacing = -1;
		figureParent.setLayoutManager(gl);
		lws.setContents(figureParent);

		Composite g = new Composite(sform, SWT.BORDER);
		// g.setText("Details");
		infoText = new StyledText(g, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
		GridDataFactory.fillDefaults().hint(SWT.DEFAULT, 150).grab(true, false)
				.applyTo(g);
		GridLayoutFactory.swtDefaults().applyTo(g);
		GridDataFactory.fillDefaults().grab(true, true).applyTo(infoText);

		sform.setWeights(new int[] { 80, 20 });
	}

	public void doZoomOut() {
		timeWidth = timeWidth - timeWidth / 4;
		if (timeWidth < 200) {
			timeWidth = 200;
		}
		ScrollBar bar = sc.getHorizontalBar();
		int selection = bar.getSelection();
		int maximum = bar.getMaximum();
		internalUpdate(nodes);
		bar.setSelection((int) ((1.0f * selection / maximum) * bar.getMaximum()));
		bar.notifyListeners(SWT.Selection, new org.eclipse.swt.widgets.Event());
	}

	public void doZoomIn() {
		timeWidth = timeWidth + timeWidth / 4;
		if (timeWidth > 30000) {
			timeWidth = 30000;
		}
		ScrollBar bar = sc.getHorizontalBar();
		int selection = bar.getSelection();
		int maximum = bar.getMaximum();
		internalUpdate(nodes);
		bar.setSelection((int) ((1.0f * selection / maximum) * bar.getMaximum()));
		bar.notifyListeners(SWT.Selection, new org.eclipse.swt.widgets.Event());
	}

	private void updateBounds(int width, int height) {
		imageCanvas.setBounds(0, 0, width, height);
		// imageCanvas.getViewport().setSize(width, height);
		// imageCanvas.setMinSize(width - 1, height - 1);
	}

	public void update(List<Node> newNodes) {
		this.nodes.clear();
		this.nodes.addAll(newNodes);
		timeWidth = 600;
		internalUpdate(nodes);
	}

	private void internalUpdate(List<Node> newNodes) {
		figureParent.removeAll();

		minTime = Long.MAX_VALUE;
		maxTime = Long.MIN_VALUE;
		for (Node node : newNodes) {
			long startTime = node.getStartTime();
			if (startTime < minTime) {
				minTime = startTime;
			}
			long endTime = node.getEndTime();
			if (endTime > maxTime) {
				maxTime = endTime;
			}
		}
		long allTime = maxTime - minTime;

		Set<Event> processed = new HashSet<Event>();

		// Create draw nodes from jobs and asyncs
		final Map<EventSource, List<Event>> sourceEvents = new HashMap<EventSource, List<Event>>();
		for (Node node : newNodes) {
			int st = calcPos(minTime, allTime, node.getStartTime());
			int ed = calcPos(minTime, allTime, node.getEndTime()) - st;
			NodeFigure nodeFig = null;
			if (includeTasks) {
				SourceFigure sources = new SourceFigure(node.getName(),
						getTimeWidth(), 1);
				figureParent.add(sources);

				nodeFig = createNodeFigure();
				nodeFig.setFill(true);
				nodeFig.setNode(node);
				nodeFig.setBackgroundColor(colors.getColor(new RGB(220, 220,
						220)));
				sources.addToContainer(nodeFig, st, 0, ed, 20, 0);
			}
			List<Event> events = new ArrayList<Event>(node.getEvents());

			// We need to collect also events started in all previous and parent
			// nodes and not finished here.
			Map<EventSource, List<Event>> nonFinishedGroups = new HashMap<EventSource, List<Event>>();
			if (showBegined && newNodes.size() < 10) {
				List<Event> priorEvents = collectPriorEvents(node);
				final Map<EventSource, List<Event>> priorEventsSources = new HashMap<EventSource, List<Event>>();
				groupBySources(priorEvents, priorEventsSources);
				mergeSources(priorEventsSources);
				List<EventSource> sourcesKeys = new ArrayList<EventSource>(
						priorEventsSources.keySet());
				Collections.sort(sourcesKeys, new Comparator<EventSource>() {
					public int compare(EventSource o1, EventSource o2) {
						long m1 = getMinTime(priorEventsSources, o1);
						long m2 = getMinTime(priorEventsSources, o2);

						return (int) (m1 - m2);
					}

				});
				for (EventSource source : sourcesKeys) {
					List<Event> events2 = priorEventsSources.get(source);
					Map<String, List<Event>> groups = groupByIDs(events2,
							new ArrayList<Event>());
					// Make small groups
					Collection<List<Event>> gvalues = groups.values();

					List<List<Event>> smallGroups = new ArrayList<List<Event>>();
					for (List<Event> list : gvalues) {
						makeSmallGroups(smallGroups, list);
					}
					Collections.sort(smallGroups,
							new Comparator<List<Event>>() {
								public int compare(List<Event> o1,
										List<Event> o2) {
									long minTime1 = calcMinTime(o1);
									long minTime2 = calcMinTime(o2);

									return (int) (minTime1 - minTime2);
								}
							});

					// Match non finished groups
					for (List<Event> list : smallGroups) {
						if (list.size() > 2) {
							Event last = list.get(list.size() - 1);
							if (!last.getKind().equals(EventKind.END)) {
								List<Event> llist = nonFinishedGroups
										.get(source);
								if (llist == null) {
									llist = new ArrayList<Event>();
									nonFinishedGroups.put(source, llist);
								}
								llist.add(last);
							}
						}
					}

				}
			}

			final Map<EventSource, List<Event>> localSourceEvents = new HashMap<EventSource, List<Event>>();
			// localSourceEvents.putAll(nonFinishedGroups);
			groupBySources(events, sourceEvents);
			groupBySources(events, localSourceEvents);
			// Build draw blocks
			if (includeTasks) {
				mergeSources(localSourceEvents);

				nodeFig.setSources(localSourceEvents);
				List<EventSource> sourcesKeys = new ArrayList<EventSource>(
						localSourceEvents.keySet());
				Collections.sort(sourcesKeys, new Comparator<EventSource>() {
					public int compare(EventSource o1, EventSource o2) {
						long m1 = getMinTime(localSourceEvents, o1);
						long m2 = getMinTime(localSourceEvents, o2);

						return (int) (m1 - m2);
					}

				});
				for (EventSource source : sourcesKeys) {
					processSource(allTime, processed, node, st, ed,
							localSourceEvents, source);
				}
				for (EventSource source : nonFinishedGroups.keySet()) {
					processNonFinishedSource(allTime, node, st, ed,
							nonFinishedGroups, source);
				}
			}

		}
		mergeSources(sourceEvents);
		// Build draw blocks
		List<EventSource> sourcesKeys = new ArrayList<EventSource>(
				sourceEvents.keySet());
		Collections.sort(sourcesKeys, new Comparator<EventSource>() {
			public int compare(EventSource o1, EventSource o2) {
				long m1 = getMinTime(sourceEvents, o1);
				long m2 = getMinTime(sourceEvents, o2);

				return (int) (m1 - m2);
			}

		});
		for (EventSource source : sourcesKeys) {
			// ArrayList<DrawNode> list = new ArrayList<DrawNode>();
			List<Event> events = sourceEvents.get(source);
			events.removeAll(processed);
			if (events.size() > 0) {
				List<List<Event>> instances = groupEvents(events);
				SourceFigure sourceRoot = new SourceFigure(
						getSourceTitle(source), getTimeWidth(),
						instances.size());
				sourceRoot.setSource(source);
				for (List<Event> list : instances) {
					addEventsTo(minTime, allTime, list, sourceRoot, minTime,
							allTime, instances.indexOf(list));
				}
				if (sourceRoot.hasChildInContainer()) {
					figureParent.add(sourceRoot);
				}
				processed.addAll(events);
			}
		}
		Dimension psize = figureParent.getPreferredSize();
		updateBounds(psize.width, psize.height);
	}

	private void groupBySources(List<Event> events,
			final Map<EventSource, List<Event>> localSourceEvents) {
		for (Event event : events) {
			EventSource source = event.getSource();
			if (source != null) {

				// Put also in loca
				List<Event> list = localSourceEvents.get(source);

				if (list == null) {
					list = new ArrayList<Event>();
					localSourceEvents.put(source, list);
				}
				list.add(event);
			}
		}
	}

	/**
	 * Collect events started before node and not finished yet.
	 */
	private List<Event> collectPriorEvents(Node node) {
		Node parent = node.getParent();
		if (parent == null) {
			return new ArrayList<Event>();
		}

		List<Event> result = new ArrayList<Event>();
		result.addAll(collectPriorEvents(parent));
		EList<Event> events = parent.getEvents();
		for (Event event : events) {
			if (!event.getKind().equals(EventKind.INFO)
					&& event.getTime() < node.getStartTime()) {
				result.add(event);
			}
		}

		EList<Node> children = parent.getChildren();
		int pos = children.indexOf(node);

		for (int i = 0; i < pos; i++) {
			EList<Event> evs = children.get(i).getEvents();
			for (Event event : evs) {
				if (!event.getKind().equals(EventKind.INFO)) {
					result.addAll(evs);
				}
			}
		}

		return result;
	}

	private void processSource(long allTime, Set<Event> processed, Node node,
			int st, int ed,
			final Map<EventSource, List<Event>> localSourceEvents,
			EventSource source) {
		List<Event> events2 = localSourceEvents.get(source);
		processed.addAll(events2);
		List<List<Event>> instances = groupEvents(events2);

		SourceFigure sourceRoot = new SourceFigure(getSourceTitle(source),
				getTimeWidth(), instances.size());

		figureParent.add(sourceRoot);
		for (List<Event> list : instances) {
			addEventsTo(minTime, allTime, list, sourceRoot, st, ed,
					instances.indexOf(list));
		}
	}

	private void processNonFinishedSource(long allTime, Node node, int st,
			int ed, final Map<EventSource, List<Event>> localSourceEvents,
			EventSource source) {
		List<Event> events2 = localSourceEvents.get(source);
		List<List<Event>> instances = groupEvents(events2);

		SourceFigure sourceRoot = new SourceFigure(getSourceTitle(source),
				getTimeWidth(), instances.size());

		figureParent.add(sourceRoot);
		for (List<Event> list : instances) {
			int level = instances.indexOf(list);
			Set<Event> processed = new HashSet<Event>();
			int len = list.size();
			for (int i = 0; i < len; i++) {
				Event event = list.get(i);
				if (processed.contains(event)) {
					continue;
				}
				if (event.getKind().equals(EventKind.BEGIN)) {
					// Check for end node
					EventFigure childFig = createEventFigure();
					childFig.setEvent(event);
					childFig.setFill(true);
					if (event.getColor() == null) {
						childFig.setBackgroundColor(colors.getColor(new RGB(0,
								0, 0)));
					} else {
						Color color = colors.getColor(parseColor(event
								.getColor()));
						childFig.setBackgroundColor(color);
					}
					sourceRoot.addToContainer(childFig, st, 0, (int) ed, 20,
							level);
				}

			}
		}
	}

	private List<List<Event>> groupEvents(List<Event> events) {
		List<List<Event>> results = new ArrayList<List<Event>>();

		List<Event> topGroup = new ArrayList<Event>();
		List<Event> infoEvents = new ArrayList<Event>();

		Map<String, List<Event>> groups = groupByIDs(events, infoEvents);

		// Make small groups
		Collection<List<Event>> gvalues = groups.values();

		List<List<Event>> smallGroups = new ArrayList<List<Event>>();
		for (List<Event> list : gvalues) {
			makeSmallGroups(smallGroups, list);
		}
		Collections.sort(smallGroups, new Comparator<List<Event>>() {
			public int compare(List<Event> o1, List<Event> o2) {
				long minTime1 = calcMinTime(o1);
				long minTime2 = calcMinTime(o2);

				return (int) (minTime1 - minTime2);
			}
		});
		// Lets merge groups
		for (List<Event> list : smallGroups) {
			if (isFitGroup(topGroup, list)) {
				topGroup.addAll(list);
			} else {
				// try to merge events by BEGIN,END pairs
				results.add(list);
			}
		}
		if (!topGroup.isEmpty()) {
			results.add(topGroup);
		}
		if (!infoEvents.isEmpty()) {
			topGroup.addAll(infoEvents);
		}

		Collections.sort(results, new Comparator<List<Event>>() {
			public int compare(List<Event> o1, List<Event> o2) {
				long minTime1 = calcMinTime(o1);
				long minTime2 = calcMinTime(o2);

				return (int) (minTime1 - minTime2);
			}
		});

		return results;
	}

	private Map<String, List<Event>> groupByIDs(List<Event> events,
			List<Event> infoEvents) {
		Map<String, List<Event>> groups = new HashMap<String, List<Event>>();

		int len = events.size();
		for (int i = 0; i < len; i++) {
			Event event = events.get(i);
			if (event.getKind().equals(EventKind.INFO)) {
				infoEvents.add(event);
				continue;
			}
			String instance = getEventInstance(event);
			List<Event> list = groups.get(instance);
			if (list == null) {
				list = new ArrayList<Event>();
				groups.put(instance, list);
			}
			list.add(event);
		}
		return groups;
	}

	private void makeSmallGroups(List<List<Event>> smallGroups, List<Event> list) {
		for (int i = 0; i < list.size(); i++) {
			Event event = list.get(i);
			List<Event> tempGroup = new ArrayList<Event>();
			tempGroup.add(event);
			if (event.getKind().equals(EventKind.BEGIN)) {
				for (int j = i + 1; j < list.size(); j++) {
					Event jEvent = list.get(j);
					if (jEvent.getKind().equals(EventKind.BEGIN)) {
						tempGroup.add(jEvent);
					} else if (jEvent.getKind().equals(EventKind.END)) {
						tempGroup.add(jEvent);
						break;
					}
				}
			}
			i += tempGroup.size() - 1;
			smallGroups.add(tempGroup);
		}
	}

	private boolean isFitGroup(List<Event> topGroup, List<Event> list) {
		if (topGroup.isEmpty()) {
			return true;
		}

		List<List<Event>> smallGroups = new ArrayList<List<Event>>();
		makeSmallGroups(smallGroups, topGroup);

		long minTime = calcMinTime(list);
		long maxTime = calcMaxTime(list);

		for (List<Event> glist : smallGroups) {
			long gminTime = calcMinTime(glist);
			long gmaxTime = calcMaxTime(glist);

			if (!(maxTime < gminTime || minTime > gmaxTime)) {
				return false;
			}
		}

		return true;
	}

	private long calcMaxTime(List<Event> list) {
		long maxTime = -1;
		for (Event event : list) {
			if (event.getTime() > maxTime) {
				maxTime = event.getTime();
			}
		}
		return maxTime;
	}

	private long calcMinTime(List<Event> list) {
		long minTime = Long.MAX_VALUE;
		for (Event event : list) {
			if (event.getTime() < minTime) {
				minTime = event.getTime();
			}
		}
		return minTime;
	}

	private String getEventInstance(Event event) {
		EObject data = event.getData();
		if (data != null) {
			if (data instanceof AsyncEventInfo) {
				String id = ((AsyncEventInfo) data).getId();
				if (id != null) {
					return id;
				}
			} else if (data instanceof JobEventInfo) {
				String id = ((JobEventInfo) data).getId();
				if (id != null) {
					return id;
				}
			}
		}
		return "";
	}

	private void addEventsTo(long minTime, long allTime, List<Event> events,
			SourceFigure sourceRoot, long stTime, long edTime, int level) {
		Set<Event> processed = new HashSet<Event>();
		int len = events.size();
		for (int i = 0; i < len; i++) {
			Event event = events.get(i);
			if (processed.contains(event)) {
				continue;
			}
			if (event.getKind().equals(EventKind.END)) {
				EventFigure childFig = createEventFigure();
				childFig.setEvent(event);
				// childFig.setEndEvent(event);
				int cst = (int) stTime;
				int cstEnd = calcPos(minTime, allTime, event.getTime());
				childFig.setFill(true);
				if (event.getColor() == null) {
					childFig.setBackgroundColor(colors
							.getColor(new RGB(0, 0, 0)));
				} else {
					Color color = colors.getColor(parseColor(event.getColor()));
					childFig.setBorder(new LineBorder(color));
					childFig.setBackgroundColor(color);
				}
				sourceRoot.addToContainer(childFig, cst, 0, cstEnd - cst, 20,
						level);
			}
			if (event.getKind().equals(EventKind.BEGIN)) {
				// Check for end node
				boolean found = false;
				for (int j = i + 1; j < len; j++) {
					Event jEvent = events.get(j);
					if (jEvent.getKind().equals(EventKind.END)
							|| jEvent.getKind().equals(EventKind.BEGIN)) {
						if (jEvent.getKind().equals(EventKind.END)) {
							processed.add(jEvent);
						}
						if (!getEventInstance(jEvent).equals(
								getEventInstance(jEvent))) {
							continue;
						}

						EventFigure childFig = createEventFigure();
						childFig.setEvent(event);
						childFig.setEndEvent(jEvent);
						int cst = calcPos(minTime, allTime, event.getTime());
						int cstEnd = calcPos(minTime, allTime, jEvent.getTime());
						childFig.setFill(true);
						if (event.getColor() == null) {
							childFig.setBackgroundColor(colors
									.getColor(new RGB(0, 0, 0)));
						} else {
							Color color = colors.getColor(parseColor(event
									.getColor()));
							childFig.setBorder(new LineBorder(color));
							childFig.setBackgroundColor(color);
						}
						sourceRoot.addToContainer(childFig, cst, 0, cstEnd
								- cst, 20, level);
						found = true;
						break;
					}
				}
				if (!found) {
					EventFigure childFig = createEventFigure();
					childFig.setEvent(event);
					int cst = calcPos(minTime, allTime, event.getTime());
					childFig.setFill(true);
					if (event.getColor() == null) {
						childFig.setBackgroundColor(colors.getColor(new RGB(0,
								0, 0)));
					} else {
						Color color = colors.getColor(parseColor(event
								.getColor()));
						childFig.setBackgroundColor(color);
					}
					sourceRoot.addToContainer(childFig, cst, 0, (int) edTime
							- cst, 20, level);
				}
			}

		}
		for (int i = 0; i < len; i++) {
			Event event = events.get(i);
			if (event.getKind().equals(EventKind.INFO)) {
				EventFigure childFig = createEventFigure();
				int cst = calcPos(minTime, allTime, event.getTime());
				childFig.setFill(true);
				childFig.setEvent(event);
				if (event.getColor() == null) {
					childFig.setBackgroundColor(colors
							.getColor(new RGB(0, 0, 0)));
				} else {
					Color color = colors.getColor(parseColor(event.getColor()));
					childFig.setBorder(new LineBorder(color));
					childFig.setBackgroundColor(color);
				}
				sourceRoot.addToContainer(childFig, cst, 0, 1, 20, level);
			}
		}
		// Locate pairs
	}

	private NodeFigure createNodeFigure() {
		final NodeFigure nodeFig = new NodeFigure();
		nodeFig.addMouseMotionListener(new MouseMotionListener() {
			Border oldBorder;

			public void mouseDragged(MouseEvent me) {
			}

			public void mouseEntered(MouseEvent me) {
				oldBorder = nodeFig.getBorder();
				LineBorder border = new LineBorder(2);
				border.setStyle(Graphics.LINE_SOLID);
				border.setColor(colors.getColor(new RGB(255, 0, 0)));
				nodeFig.setBorder(border);
				imageCanvas.redraw();
			}

			public void mouseExited(MouseEvent me) {
				nodeFig.setBorder(oldBorder);
			}

			public void mouseHover(MouseEvent me) {
			}

			public void mouseMoved(MouseEvent me) {
			}
		});
		nodeFig.addMouseListener(new MouseListener() {

			public void mousePressed(MouseEvent me) {

			}

			public void mouseReleased(MouseEvent me) {
				if (nodeFig.getNode() != null) {
					updateInfo(nodeFig.getNode(), nodeFig.getSources());
				}
			}

			public void mouseDoubleClicked(MouseEvent me) {
			}
		});
		return nodeFig;
	}

	private EventFigure createEventFigure() {
		final EventFigure efig = new EventFigure();
		efig.addMouseMotionListener(new MouseMotionListener() {
			Border oldBorder = null;

			public void mouseDragged(MouseEvent me) {
			}

			public void mouseEntered(MouseEvent me) {
				oldBorder = efig.getBorder();
				LineBorder border = new LineBorder(2);
				border.setStyle(Graphics.LINE_SOLID);
				border.setColor(colors.getColor(new RGB(255, 0, 0)));
				efig.setBorder(border);
				imageCanvas.redraw();
			}

			public void mouseExited(MouseEvent me) {
				efig.setBorder(oldBorder);
			}

			public void mouseHover(MouseEvent me) {
			}

			public void mouseMoved(MouseEvent me) {
			}
		});
		efig.addMouseListener(new MouseListener() {
			public void mousePressed(MouseEvent me) {
				updateInfo(efig.getEvent(), efig.getEndEvent());
			}

			public void mouseReleased(MouseEvent me) {
			}

			public void mouseDoubleClicked(MouseEvent me) {
			}
		});
		return efig;
	}

	private RGB parseColor(String color) {
		if (color.startsWith("#") && color.length() == 7) {
			int r = Integer.parseInt(color.substring(1, 3), 16);
			int g = Integer.parseInt(color.substring(3, 5), 16);
			int b = Integer.parseInt(color.substring(5, 7), 16);
			return new RGB(r, g, b);
		}
		return new RGB(0, 0, 0);
	}

	// Merge sources with same class name into one
	private void mergeSources(Map<EventSource, List<Event>> localSourceEvents) {
		Map<EventSource, List<Event>> result = new HashMap<EventSource, List<Event>>();
		for (EventSource es : localSourceEvents.keySet()) {
			String title = getSourceTitle(es);
			EventSource mergeTo = null;
			for (EventSource res : result.keySet()) {
				if (title.equals(getSourceTitle(res))) {
					mergeTo = res;
					break;
				}
			}
			if (mergeTo == null) {
				result.put(es, localSourceEvents.get(es));
			} else {
				List<Event> rList = new ArrayList<Event>();
				rList.addAll(result.get(mergeTo));
				rList.addAll(localSourceEvents.get(es));
				result.put(mergeTo, rList);
			}
		}
		localSourceEvents.clear();
		localSourceEvents.putAll(result);
	}

	private long getMinTime(
			final Map<EventSource, List<Event>> localSourceEvents,
			EventSource o1) {
		List<Event> list = localSourceEvents.get(o1);
		long minTime1 = calcMinTime(list);
		return minTime1;
	}

	protected void updateInfo(Event event, Event endEvent) {
		StringBuilder builder = new StringBuilder();

		if (event != null && endEvent != null) {
			builder.append(
					"Start time:"
							+ TimeFormatHelper.format(event.getTime() - minTime))
					.append("\n");
			builder.append(
					"Time spend:"
							+ TimeFormatHelper.format(endEvent.getTime()
									- event.getTime())).append("\n");

		} else {
			builder.append(
					"Time:"
							+ TimeFormatHelper.format(event.getTime() - minTime))
					.append("\n");

		}
		EventSource source = event.getSource();
		EObject data = source.getProperties().get(SherlockJobsCore.JOBS);
		if (data != null && data instanceof AsyncInfo) {
			EObject dta = event.getData();

			AsyncInfo info = (AsyncInfo) data;
			if (info.isSync()) {
				builder.append("sync exec:");
			} else {
				builder.append("async exec:");
				if (dta != null && dta instanceof AsyncEventInfo) {
					switch (((AsyncEventInfo) dta).getKind()) {
					case STARTING:
						builder.append("Starting");
						break;
					case RUNNING:
						builder.append("Running");
						break;
					case DONE:
						builder.append("Done");
						break;
					case TIMER_EXEC:
						builder.append("Timer exec");
						break;
					}
				}
			}
			builder.append("\n");
			String cName = info.getRunnableClass();
			if (cName == null || cName.startsWith("$")) {
				cName = info.getSourceClass() + cName;
			}
			builder.append(" class name:" + cName).append("\n");
			if (info.getSourceClass() != null) {
				builder.append(
						" source class name:" + info.getSourceClass() + "."
								+ info.getSourceMethod()).append("\n");
			}
			if (info.getSourceFile() != null) {
				builder.append(" source file:" + info.getSourceFile()).append(
						"\n");
			}
			if (info.getThisClassName() != null) {
				builder.append(" created from:" + info.getThisClassName())
						.append("\n");
			}
		}
		if (data != null && data instanceof JobInfo) {
			JobInfo info = (JobInfo) data;
			builder.append("job:");
			EObject dta = event.getData();
			if (dta != null && dta instanceof JobEventInfo) {
				switch (((JobEventInfo) dta).getKind()) {
				case SHEDULED:
					builder.append("Sheduled");
					break;
				case RUNNING:
					builder.append("Running");
					break;
				case CANCELED:
					builder.append("Canceled");
					break;
				case WAITING:
					builder.append("Waiting");
					break;
				case FINISHED:
					builder.append("Finished");
					break;
				case ASYNC_DONE:
					builder.append("Async Done");
					break;
				case SLEPPING:
					builder.append("Sleeping");
					break;
				case ASYNC_FINISH:
					builder.append("Waiting async");
					break;
				}
			}
			builder.append("\n");

			String cName = info.getJobClassName();
			if (cName == null || cName.startsWith("$")) {
				cName = info.getSourceClass() + cName;
			}
			builder.append(" class name:" + cName).append("\n");
			if (info.getSourceClass() != null) {
				builder.append(
						" source class name:" + info.getSourceClass() + "."
								+ info.getSourceMethod()).append("\n");
			}
			if (info.getSourceFile() != null) {
				builder.append(" source file:" + info.getSourceFile()).append(
						"\n");
			}
			if (info.getThisClassName() != null) {
				builder.append(" created from:" + info.getThisClassName())
						.append("\n");
			}
		}
		infoText.setText(builder.toString());
	}

	protected void updateInfo(Node node, Map<EventSource, List<Event>> sources) {
		StringBuilder builder = new StringBuilder();

		builder.append(
				"Start time:"
						+ TimeFormatHelper.format(node.getStartTime() - minTime))
				.append("\n");
		builder.append(
				"Time spend:"
						+ TimeFormatHelper.format(node.getDuration()))
				.append("\n");

		SimpleReportGenerator gen = new SimpleReportGenerator();
		for (EventSource source : sources.keySet()) {
			builder.append("source:" + getSourceTitle(source)).append("\n");
			List<Event> events = sources.get(source);
			for (Event event : events) {
				builder.append("\t" + "event:"
						+ TimeFormatHelper.format(event.getTime() - minTime));
				StringBuilder b2 = new StringBuilder();
				try {
					gen.toString(b2, 0, event.getData(), true);
				} catch (IOException e) {
					// String Builder does not throw
					throw new RuntimeException(e);
				}
				builder.append(" " + b2.toString().replace('\n', ' ').trim())
						.append("\n");
			}
		}

		infoText.setText(builder.toString());
	}

	private int getTimeWidth() {
		return timeWidth;
	}

	private String getSourceTitle(EventSource source) {

		EMap<String, EObject> properties = source.getProperties();

		EObject eobject = properties.get(SherlockJobsCore.JOBS);
		if (eobject != null && eobject instanceof AsyncInfo) {
			AsyncInfo info = (AsyncInfo) eobject;
			String cName = info.getRunnableClass();
			if (cName == null || cName.startsWith("$")) {
				cName = info.getSourceClass() + cName;
			}
			int pos = cName.lastIndexOf('.');
			if (info.isTimer()) {
				return "\t" + "timer:" + cName.substring(pos + 1);
			}
			return "\t" + (info.isSync() ? "sync: " : "async: ")
					+ cName.substring(pos + 1);
		} else if (eobject != null && eobject instanceof JobInfo) {
			JobInfo jobInfo = (JobInfo) eobject;
			String cName = jobInfo.getJobClassName();
			if (cName == null || cName.startsWith("$")) {
				cName = jobInfo.getSourceClass() + cName;
			}
			int pos = cName.lastIndexOf('.');
			return "\t" + "job: " + cName.substring(pos + 1);
		} /*
		 * else if (teslaInfo != null) { String name = teslaInfo.getName(); int
		 * pos = name.lastIndexOf('.'); return "\t" +"cmd: " +
		 * name.substring(pos + 1); }
		 */

		return "    " + source.getName();
	}

	private int calcPos(long minTime, long allTime, long time) {
		return (int) (getTimeWidth() * (1.0f * (time - minTime) / allTime));
	}

	public void setShowTasks(boolean includeTasks2) {
		includeTasks = includeTasks2;
		internalUpdate(nodes);
	}
}
