/**********************************************************************
 * Copyright (c) 2005, 2014 IBM Corporation, Ericsson
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM - Initial API and implementation
 *     Bernd Hufmann - Updated for TMF
 **********************************************************************/

package org.eclipse.tracecompass.tmf.ui.views.uml2sd.core;

import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.tracecompass.internal.tmf.ui.TmfUiTracer;
import org.eclipse.tracecompass.tmf.ui.views.uml2sd.drawings.IGC;
import org.eclipse.tracecompass.tmf.ui.views.uml2sd.preferences.ISDPreferences;
import org.eclipse.tracecompass.tmf.ui.views.uml2sd.preferences.SDViewPref;

/**
 * The base class used for all UML2 graph nodes displayed in the Sequence Diagram SDWidget.
 *
 * @author sveyrier
 * @version 1.0
 */
public abstract class GraphNode {

    private static final String UI_DELIMITER = "*****************************\n"; //$NON-NLS-1$
    // ------------------------------------------------------------------------
    // Attributes
    // ------------------------------------------------------------------------
    /**
     * The start event occurrence.
     */
    private int fStartEventOccurrence = 0;
    /**
     * The event event occurrence.
     */
    private int fEndEventOccurrence = 0;
    /**
     * Preference ColorId to use to draw font
     */
    private String fPrefId = ISDPreferences.PREF_SYNC_MESS;
    /**
     * The selection state of the graph node.
     */
    private boolean fSelected = false;
    /**
     * The focus state of the graph node.
     */
    private boolean fFocused = false;
    /**
     * Flag to indicate whether node has children or not.
     */
    private boolean fHasChilden = false;
    /**
     * The graph node name used to label the graph node in the View.
     */
    private String fName = ""; //$NON-NLS-1$
    /**
     * A map from node name to graph node.
     */
    private Map<String, List<GraphNode>> fNodes;
    /**
     * A map from node name to graph node for forward sorting
     */
    private Map<String, List<GraphNode>> fForwardNodes;
    /**
     * A map from node name to graph node for backwards sorting.
     */
    private Map<String, List<GraphNode>> fBackwardNodes;
    /**
     * A map from node name to index.
     */
    private Map<String, Integer> fIndexes;
    /**
     * A map from node name to flag for forwards sorting.
     */
    private Map<String, Boolean> fForwardSort;
    /**
     * A map from node name to flag for backwards sorting.
     */
    private Map<String, Boolean> fBackwardSort;

    // ------------------------------------------------------------------------
    // Methods
    // ------------------------------------------------------------------------

    /**
     * Reset the internal index of the first visible GraphNode for each ordered GraphNode lists
     */
    public void resetIndex() {
        if (!fHasChilden) {
            return;
        }

        for (Map.Entry<String, Integer> entry : fIndexes.entrySet()) {
            entry.setValue(Integer.valueOf(0));
        }
    }

    /**
     * Add a GraphNode into the receiver
     *
     * @param nodeToAdd the node to add
     */
    public void addNode(GraphNode nodeToAdd) {
        if (!fHasChilden) {
            fNodes = new HashMap<>(2);
            fForwardNodes = new HashMap<>(2);
            fBackwardNodes = new HashMap<>(2);
            fIndexes = new HashMap<>(2);
            fBackwardSort = new HashMap<>(2);
            fForwardSort = new HashMap<>(2);
            fHasChilden = true;
        }

        // Nothing to add
        if (nodeToAdd == null) {
            return;
        }

        if (fNodes.get(nodeToAdd.getArrayId()) == null) {
            fNodes.put(nodeToAdd.getArrayId(), new ArrayList<GraphNode>(1));
            fIndexes.put(nodeToAdd.getArrayId(), Integer.valueOf(0));
            fForwardNodes.put(nodeToAdd.getArrayId(), new ArrayList<GraphNode>(1));
            fForwardSort.put(nodeToAdd.getArrayId(), Boolean.FALSE);
            if (nodeToAdd.getBackComparator() != null) {
                fBackwardNodes.put(nodeToAdd.getArrayId(), new ArrayList<GraphNode>(1));
                fBackwardSort.put(nodeToAdd.getArrayId(), Boolean.FALSE);
            }
        }

        List<GraphNode> fNodeList = fForwardNodes.get(nodeToAdd.getArrayId());
        List<GraphNode> bNodeList = null;
        if (fBackwardNodes != null) {
            bNodeList = fBackwardNodes.get(nodeToAdd.getArrayId());
        }
        if (fNodeList != null && !fNodeList.isEmpty()) {
            // check if the nodes are added y ordered
            // if not, tag the list to sort it later (during draw)
            GraphNode node = fNodeList.get(fNodeList.size() - 1);
            Comparator<GraphNode> fcomp = nodeToAdd.getComparator();
            Comparator<GraphNode> bcomp = nodeToAdd.getBackComparator();
            if ((fcomp != null) && (fcomp.compare(node, nodeToAdd) > 0)) {
                fForwardSort.put(nodeToAdd.getArrayId(), Boolean.TRUE);
            }
            if ((bcomp != null) && (bcomp.compare(node, nodeToAdd) > 0)) {
                fBackwardSort.put(nodeToAdd.getArrayId(), Boolean.TRUE);
            }
        }

        if (fNodeList == null) {
            fNodeList = new ArrayList<>();
        }

        fNodeList.add(nodeToAdd);
        fNodes.put(nodeToAdd.getArrayId(), fNodeList);
        fForwardNodes.put(nodeToAdd.getArrayId(), fNodeList);
        if ((bNodeList != null) && (nodeToAdd.getBackComparator() != null)) {
            bNodeList.add(nodeToAdd);
            fBackwardNodes.put(nodeToAdd.getArrayId(), bNodeList);
        }
    }

    /**
     * Set the graph node name.<br>
     * It is the name display in the view to label the graph node.
     *
     * @param nodeName the name to set
     */
    public void setName(String nodeName) {
        fName = nodeName;
    }

    /**
     * Returns the graph node name.<br>
     * It is the name display in the view to label the graph node.
     *
     * @return the graph node name
     */
    public String getName() {
        return fName;
    }

    /**
     * Tags the the graph node has selected.<br>
     * WARNING: This method is only used to draw the graph node using the system selection colors. <br>
     * To use the complete SDViewer selection mechanism (selection management, notification, etc..) see SDWidget class
     *
     * @see org.eclipse.tracecompass.tmf.ui.views.uml2sd.SDWidget#addSelection(GraphNode)
     * @see org.eclipse.tracecompass.tmf.ui.views.uml2sd.SDWidget#removeSelection(GraphNode)
     * @see org.eclipse.tracecompass.tmf.ui.views.uml2sd.SDWidget#clearSelection()
     * @param selection - true to set selected, false to set unselected
     */
    public void setSelected(boolean selection) {
        fSelected = selection;
    }

    /**
     * Tags the the graph node as focused.<br>
     * WARNING: This method is only used to draw the graph node using the system focus style. <br>
     * To use the complete SDViewer focus mechanism see SDWidget class
     *
     * @see org.eclipse.tracecompass.tmf.ui.views.uml2sd.SDWidget#addSelection(GraphNode)
     * @see org.eclipse.tracecompass.tmf.ui.views.uml2sd.SDWidget#removeSelection(GraphNode)
     * @see org.eclipse.tracecompass.tmf.ui.views.uml2sd.SDWidget#clearSelection()
     * @param focus - true to set focued, false otherwise
     */
    public void setFocused(boolean focus) {
        fFocused = focus;
    }

    /**
     * Returns true if the graph node is selected, false otherwise.<br>
     * The returned value is used to highlight the graph node in the View.
     *
     * @return true if selected, false otherwise
     */
    public boolean isSelected() {
        return fSelected;
    }

    /**
     * Returns true if the graph node is focused, false otherwise.<br>
     * The returned value is used to highlight the graph node in the View.
     *
     * @return true if focused, false otherwise
     */
    public boolean hasFocus() {
        return fFocused;
    }

    /**
     * Returns true if the graph node contains the point given in parameter,
     * return false otherwise.
     *
     * @param x
     *            the x coordinate of the point to test containment
     * @param y
     *            the y coordinate of the point to test containment
     * @return true if contained, false otherwise
     */
    public abstract boolean contains(int x, int y);

    /**
     * Returns the x coordinate of the graph node
     *
     * @return the x coordinate
     */
    public abstract int getX();

    /**
     * Returns the y coordinate of the graph node
     *
     * @return the y coordinate
     */
    public abstract int getY();

    /**
     * Returns the graph node height
     *
     * @return the graph node height
     */
    public abstract int getHeight();

    /**
     * Returns the graph node width
     *
     * @return the graph node width
     */
    public abstract int getWidth();

    /**
     * Draws the graph node in the given context
     *
     * @param context the graphical context to draw in
     */
    protected abstract void draw(IGC context);

    /**
     * Returns the GraphNode visibility for the given visible area. Wrong
     * visibility calculation, may strongly impact drawing performance
     *
     * @param x
     *            The X coordinate
     * @param y
     *            The Y coordinate
     * @param width
     *            The width of the area
     * @param height
     *            The height of the area
     * @return true if visible, false otherwise
     */
    public boolean isVisible(int x, int y, int width, int height) {
        return true;
    }

    /**
     * Return a comparator to sort the GraphNode of the same type This
     * comparator is used to order the GraphNode array of the given node type.
     * (see getArrayId).
     *
     * @return the comparator
     */
    public Comparator<GraphNode> getComparator() {
        return null;
    }

    /**
     * If needed, return a different comparator to backward scan the GraphNode
     * array
     *
     * @return the backward comparator or null if not needed
     */
    public Comparator<GraphNode> getBackComparator() {
        return null;
    }

    /**
     * Compare two graphNodes
     *
     * @param node
     *            the node to compare to
     * @return true if equal false otherwise
     */
    public boolean isSameAs(GraphNode node) {
        return false;
    }

    /**
     * Return the node type for all class instances. This id is used to store the same nodes kind in the same ordered
     * array.
     *
     * @return the node type identifier
     */
    public abstract String getArrayId();

    /**
     * Return true if the distance from the GraphNode to the given point is positive
     *
     * @param x the point x coordinate
     * @param y the point y coordinate
     * @return true if positive false otherwise
     */
    public boolean positiveDistanceToPoint(int x, int y) {
        return false;
    }

    /**
     * Returns the graph node which contains the point given in parameter WARNING: Only graph nodes in the current
     * visible area can be returned
     *
     * @param x the x coordinate of the point to test
     * @param y the y coordinate of the point to test
     * @return the graph node containing the point given in parameter, null otherwise
     */
    public GraphNode getNodeAt(int x, int y) {
        GraphNode toReturn = null;

        if (!fHasChilden) {
            return null;
        }

        GraphNode node = null;
        for (Map.Entry<String, List<GraphNode>> entry : fNodes.entrySet()) {
            List<GraphNode> list = entry.getValue();
            int index = checkNotNull(fIndexes.get(entry.getKey())).intValue();
            node = getNodeFromListAt(x, y, list, index);
            if (toReturn == null) {
                toReturn = node;
            }
            if (node != null) {
                GraphNode internalNode = node.getNodeAt(x, y);
                if (internalNode != null) {
                    return internalNode;
                } else if (Math.abs(node.getWidth()) < Math.abs(toReturn.getWidth()) || Math.abs(node.getHeight()) < Math.abs(toReturn.getHeight())) {
                    toReturn = node;
                }
            }
        }
        return toReturn;
    }

    /**
     * Gets node list from node A to node B

     * @param from A from node
     * @param to A to node
     * @return the list of nodes
     */
    public List<GraphNode> getNodeList(GraphNode from, GraphNode to) {
        List<GraphNode> result = new ArrayList<>();

        if (from != null) {
            result.add(from);
        } else if (to != null) {
            result.add(to);
        }

        if ((from == null) || (to == null)) {
            return result;
        }

        if (from == to) {
            return result;
        }

        int startX = Math.min(from.getX(), Math.min(to.getX(), Math.min(from.getX() + from.getWidth(), to.getX() + to.getWidth())));
        int endX = Math.max(from.getX(), Math.max(to.getX(), Math.max(from.getX() + from.getWidth(), to.getX() + to.getWidth())));
        int startY = Math.min(from.getY(), Math.min(to.getY(), Math.min(from.getY() + from.getHeight(), to.getY() + to.getHeight())));
        int endY = Math.max(from.getY(), Math.max(to.getY(), Math.max(from.getY() + from.getHeight(), to.getY() + to.getHeight())));

        if (!fHasChilden) {
            return result;
        }

        for (Map.Entry<String, List<GraphNode>> entry : fNodes.entrySet()) {
            List<GraphNode> nodesList = entry.getValue();
            if (nodesList == null || nodesList.isEmpty()) {
                return null;
            }
            for (int i = 0; i < nodesList.size(); i++) {
                GraphNode node = nodesList.get(i);
                int nw = node.getWidth();
                int nh = node.getHeight();
                int nx = node.getX();
                int ny = node.getY();
                if (contains(startX, startY, endX - startX, endY - startY, nx + 1, ny + 1) && contains(startX, startY, endX - startX, endY - startY, nx + nw - 2, ny + nh - 2)) {
                    result.add(node);
                }
                result.addAll(node.getNodeList(from, to));
            }
        }

        if (!result.contains(to)) {
            result.add(to);
        }
        return result;
    }

    /**
     * Returns the graph node which contains the point given in parameter for the given graph node list and starting the
     * iteration at the given index<br>
     * WARNING: Only graph nodes with smaller coordinates than the current visible area can be returned.<br>
     *
     * @param x the x coordinate of the point to test
     * @param y the y coordinate of the point to test
     * @param list the list to search in
     * @param fromIndex list browsing starting point
     * @return the graph node containing the point given in parameter, null otherwise
     */
    protected GraphNode getNodeFromListAt(int x, int y, List<GraphNode> list, int fromIndex) {
        if (list == null) {
            return null;
        }
        for (int i = fromIndex; i < list.size(); i++) {
            GraphNode node = list.get(i);
            if (node.contains(x, y)) {
                return node;
            }
        }
        return null;
    }

    /**
     * Returns the start event occurrence attached to this graphNode.
     *
     * @return the start event occurrence attached to the graphNode
     */
    public int getStartOccurrence() {
        return fStartEventOccurrence;
    }

    /**
     * Returns the end event occurrence attached to this graphNode
     *
     * @return the start event occurrence attached to the graphNode
     */
    public int getEndOccurrence() {
        return fEndEventOccurrence;
    }

    /**
     * Computes the index of the first visible GraphNode for each ordered graph node lists depending on the visible area
     * given in parameter
     *
     * @param x visible area top left corner x coordinate
     * @param y visible area top left corner y coordinate
     * @param width visible area width
     * @param height visible area height
     */
    public void updateIndex(int x, int y, int width, int height) {
        if (!fHasChilden) {
            return;
        }
        if(TmfUiTracer.isIndexTraced()) {
            TmfUiTracer.traceIndex(UI_DELIMITER);
            TmfUiTracer.traceIndex("Visible area position in virtual screen (x,y)= " + x + " " + y + "\n\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        }

        for (Map.Entry<String, List<GraphNode>> entry : fNodes.entrySet()) {
            String nodeType = entry.getKey();
            int direction = 1;
            int drawIndex = checkNotNull(fIndexes.get(nodeType)).intValue();
            if ((entry.getValue() != null) && (entry.getValue().size() > 1)) {
                if (entry.getValue().get(drawIndex).positiveDistanceToPoint(x, y)) {
                    direction = -1;
                }

                if (drawIndex == 0) {
                    direction = 1;
                }

                List<GraphNode> nodes = fBackwardNodes.get(nodeType);
                if ((direction == -1) && (nodes != null)) {
                    GraphNode currentNode = entry.getValue().get(drawIndex);
                    drawIndex = Arrays.binarySearch(nodes.toArray(new GraphNode[nodes.size()]),
                            entry.getValue().get(drawIndex), currentNode.getBackComparator());
                    entry.setValue(nodes);
                    if (drawIndex < 0) {
                        drawIndex = 0;
                        direction = 1;
                    } else {
                        entry.setValue(fBackwardNodes.get(nodeType));
                    }
                }
                GraphNode prev = null;

                for (int i = drawIndex; i < entry.getValue().size() && i >= 0; i = i + direction) {
                    drawIndex = i;
                    fIndexes.put(nodeType, Integer.valueOf(i));

                    GraphNode currentNode = entry.getValue().get(i);

                    if (prev == null) {
                        prev = currentNode;
                    }

                    Comparator<GraphNode> comp = currentNode.getComparator();
                    Map<String, Boolean> sort = fForwardSort;

                    if ((direction == -1) && (currentNode.getBackComparator() != null)) {
                        comp = currentNode.getBackComparator();
                        sort = fBackwardSort;
                    }

                    if (i < entry.getValue().size() - 1) {
                        GraphNode next = entry.getValue().get(i + 1);

                        if ((comp != null) && (comp.compare(currentNode, next) > 0)) {
                            sort.put(nodeType, Boolean.TRUE);
                        }
                    }
                    if (direction == 1) {
                        if (entry.getValue().get(i).positiveDistanceToPoint(x, y)) {
                            break;
                        }
                    } else {
                        if (currentNode.getBackComparator() == null) {
                            if (!currentNode.positiveDistanceToPoint(x, y)) {
                                break;
                            }
                        } else {
                            if (currentNode.isVisible(x, y, width, height) && !currentNode.positiveDistanceToPoint(x, y)) {
                                if ((comp != null) && (comp.compare(currentNode, prev) <= 0)) {
                                    break;
                                }
                            } else if ((comp != null) && (comp.compare(currentNode, prev) <= 0)) {
                                prev = currentNode;
                            }
                        }
                    }
                }

                entry.setValue(fForwardNodes.get(nodeType));
                if ((fBackwardNodes.get(nodeType) != null) && (direction == -1)) {
                    int index = checkNotNull(fIndexes.get(nodeType)).intValue();
                    List<GraphNode> list = entry.getValue();
                    List<GraphNode> backList = checkNotNull(fBackwardNodes.get(nodeType));
                    GraphNode currentNode = (backList.get(index));
                    if (index > 0) {
                        index = Arrays.binarySearch(list.toArray(new GraphNode[list.size()]), backList.get(index), currentNode.getComparator());
                        if (index < 0) {
                            index = 0;
                        }
                        fIndexes.put(nodeType, Integer.valueOf(index));
                    }
                }

                for (int i = drawIndex; i < entry.getValue().size() && i >= 0; i++) {
                    GraphNode toDraw = entry.getValue().get(i);
                    toDraw.updateIndex(x, y, width, height);
                    if (!toDraw.isVisible(x, y, width, height)) {
                        break;
                    }
                }
            }
            if (TmfUiTracer.isIndexTraced()) {
                TmfUiTracer.traceIndex("First drawn " + nodeType + " index = " + drawIndex + "\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                TmfUiTracer.traceIndex(nodeType + " found in " + 0 + " iterations\n"); //$NON-NLS-1$ //$NON-NLS-2$
            }
        }

        if (TmfUiTracer.isIndexTraced()) {
            TmfUiTracer.traceIndex(UI_DELIMITER);
        }
    }

    /**
     * Draws the children nodes on the given context.<br>
     * This method start width GraphNodes ordering if needed.<br>
     * After, depending on the visible area, only visible GraphNodes are drawn.<br>
     *
     * @param context the context to draw to
     * @see org.eclipse.tracecompass.tmf.ui.views.uml2sd.core.GraphNode#draw(IGC)
     */
    protected void drawChildenNodes(IGC context) {

        if (!fHasChilden) {
            return;
        }
        // If the nodes have not been added ordered, the array is ordered
        for (Map.Entry<String, Boolean> entry : fForwardSort.entrySet()) {
            boolean sort = entry.getValue().booleanValue();
            if (sort) {
                sortNodes(fForwardNodes, entry, true);
            }
        }

        for (Map.Entry<String, Boolean> entry : fBackwardSort.entrySet()) {
            boolean sort = entry.getValue().booleanValue();
            if (sort) {
                sortNodes(fBackwardNodes, entry, false);
            }
        }

        if (TmfUiTracer.isDisplayTraced()) {
            TmfUiTracer.traceDisplay(UI_DELIMITER);
        }

        int arrayStep = 1;
        if ((Metrics.getMessageFontHeigth() + Metrics.MESSAGES_NAME_SPACING * 2) * context.getZoom() < Metrics.MESSAGE_SIGNIFICANT_VSPACING) {
            arrayStep = Math.round(Metrics.MESSAGE_SIGNIFICANT_VSPACING / ((Metrics.getMessageFontHeigth() + Metrics.MESSAGES_NAME_SPACING * 2) * context.getZoom()));
        }

        int count = 0;
        for (Map.Entry<String, Boolean> entry : fForwardSort.entrySet()) {
            count = 0;
            String nodeType = entry.getKey();
            GraphNode node = checkNotNull(fNodes.get(nodeType)).get(0);
            context.setFont(SDViewPref.getInstance().getFont(node.fPrefId));
            int index = checkNotNull(fIndexes.get(nodeType)).intValue();
            count = drawNodes(context, fNodes.get(nodeType), index, arrayStep);
            if (TmfUiTracer.isDisplayTraced()) {
                TmfUiTracer.traceDisplay(count + " " + nodeType + " drawn, starting from index " + index + "\r\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
            }
        }
        if (TmfUiTracer.isDisplayTraced()) {
            TmfUiTracer.traceDisplay(UI_DELIMITER);
        }

    }

    private void sortNodes(Map<String, List<GraphNode>> nodesToSort, Map.Entry<String, Boolean> sortMapEntry, boolean forward) {
        String nodeType = sortMapEntry.getKey();
        List<GraphNode> temp = checkNotNull(nodesToSort.get(nodeType));
        GraphNode node = checkNotNull(fNodes.get(nodeType)).get(0);
        if (forward) {
            temp.sort(node.getComparator());
            fNodes.put(nodeType, temp);
        } else {
            temp.sort(node.getBackComparator());
        }
        nodesToSort.put(nodeType, temp);
        sortMapEntry.setValue(Boolean.FALSE);
        if (TmfUiTracer.isSortingTraced()) {
            TmfUiTracer.traceSorting(nodeType + " array sorted\n"); //$NON-NLS-1$
        }
    }

    /**
     * Draw the GraphNode stored in the given list, starting at index startIndex with the given step
     *
     * @param context the context to draw to
     * @param list the GraphNodes list
     * @param startIndex the start index
     * @param step the step to browse the list
     * @return the number of GraphNodes drawn
     */
    protected int drawNodes(IGC context, List<GraphNode> list, int startIndex, int step) {
        if (!fHasChilden) {
            return 0;
        }

        GraphNode last = null;
        int nodesCount = 0;
        if (list.isEmpty()) {
            return 0;
        }

        GraphNode node = list.get(0);
        context.setFont(SDViewPref.getInstance().getFont(node.fPrefId));
        Comparator<GraphNode> comparator = node.getComparator();
        for (int i = startIndex; i < list.size(); i = i + step) {
            GraphNode toDraw = list.get(i);
            if (i < list.size() - 1) {
                GraphNode next = list.get(i + 1);
                if ((comparator != null) && (comparator.compare(toDraw, next) > 0)) {
                    fForwardSort.put(next.getArrayId(), Boolean.TRUE);
                }
            }
            int cx = context.getContentsX();
            int cy = context.getContentsY();
            int cw = context.getVisibleWidth();
            int ch = context.getVisibleHeight();
            // The arrays should be ordered, no needs to continue for this one
            if (!toDraw.isVisible(cx, cy, cw, ch) && toDraw.positiveDistanceToPoint(cx + cw, cy + ch)) {
                break;
            }
            // ***Common*** nodes visibility
            if ((!toDraw.isSameAs(last) || toDraw.isSelected()) && (toDraw.isVisible(context.getContentsX(), context.getContentsY(), context.getVisibleWidth(), context.getVisibleHeight()))) {
                nodesCount++;

                toDraw.draw(context);
                if (hasFocus()) {
                    toDraw.drawFocus(context);
                }
            }
            last = toDraw;
        }
        return nodesCount;
    }

    /**
     * Draws the focus within the graphical context.
     *
     * @param context
     *            The context
     */
    public void drawFocus(IGC context) {
        context.drawFocus(getX(), getY(), getWidth(), getHeight());
    }

    /**
     * Determine if the given point (px,py) is contained in the rectangle (x,y,width,height)
     *
     * @param x the rectangle x coordinate
     * @param y the rectangle y coordinate
     * @param width the rectangle width
     * @param height the rectangle height
     * @param px the x coordinate of the point to test
     * @param py the y coordinate of the point to test
     * @return true if contained false otherwise
     */
    public static boolean contains(int x, int y, int width, int height, int px, int py) {
        int locX = x;
        int locY = y;
        int locWidth = width;
        int locHeight = height;

        if (width < 0) {
            locX = locX + width;
            locWidth = -locWidth;
        }

        if (height < 0) {
            locY = locY + height;
            locHeight = -locHeight;
        }
        return (px >= locX) && (py >= locY) && ((px - locX) <= locWidth) && ((py - locY) <= locHeight);
    }

    /**
     * Sets the start event occurrence attached to this graphNode.
     *
     * @param occurence
     *          the start event occurrence attached to the graphNode
     */
    protected void setStartOccurrence(int occurence) {
        fStartEventOccurrence = occurence;
    }

    /**
     * Sets the end event occurrence attached to this graphNode
     *
     * @param occurence
     *          the start event occurrence attached to the graphNode
     */
    protected void setEndOccurrence(int occurence) {
        fEndEventOccurrence = occurence;
    }

    /**
     * Sets the color preference id
     * @param id
     *          The color preference id
     */
    protected void setColorPrefId(String id) {
        fPrefId = id;
    }

    /**
     * Gets the color preference id
     * @return the color preference id
     */
    protected String getColorPrefId() {
        return fPrefId;
    }

    /**
     * @return if node has children or not
     */
    protected boolean hasChildren() {
        return fHasChilden;
    }

    /**
     * Sets the flag indicating where the node has children or not.
     * @param hasChildren
     *          if node has children or not
     */
    protected void hasChildren(boolean hasChildren) {
        fHasChilden = hasChildren;
    }
    /**
     * Returns a map from node name to graph node.
     *
     * @return map with children graph bodes
     */
    protected Map<String, List<GraphNode>> getNodeMap() {
        return fNodes;
    }
    /**
     * Returns a map from node name to graph node for forward sorting
     *
     * @return forward sorting map
     */
    protected Map<String, List<GraphNode>> getForwardNodes() {
        return fForwardNodes;
    }
    /**
     * Returns a map from node name to graph node for backwards sorting.
     *
     * @return backwards sorting map
     */
    protected Map<String, List<GraphNode>> getBackwardNodes() {
        return fBackwardNodes;
    }
    /**
     * Returns a map from node name to index.
     *
     * @return map with node name to index
     */
    protected Map<String, Integer> getIndexes() {
        return fIndexes;
    }

    /**
     * Returns a map from node name to sort flag for forwards sorting.
     * @return a map from node name to sort flag
     */
    protected Map<String, Boolean> getForwardSortMap() {
        return fForwardSort;
    }
    /**
     * Returns a map from node name to flag for backwards sorting.
     * @return map from node name to flag for backwards sorting.
     */
    protected Map<String, Boolean> getBackwardSortMap() {
        return fBackwardSort;
    }
}
