/**********************************************************************
 * 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 org.eclipse.tracecompass.tmf.ui.views.uml2sd.drawings.IColor;
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 UML2 syncMessages implementation.<br>
 * This abstract class only define one event occurrence to attach to the message.<br>
 * Usually a message has two event occurrences attached, one for both ends. But some syncMessages(like synchronous
 * syncMessages) only need one event occurrence to represent the time when they appear. Others kind of message
 * representations (like asynchronous syncMessages) will be responsible to define the missing second eventOccurrence
 * property.<br>
 * <br>
 *
 * @see Lifeline Lifeline for more event occurence details
 * @version 1.0
 * @author sveyrier
 */
public abstract class BaseMessage extends GraphNode {

    private static final int ARROW_LENGTH = 7;
    private static final double ARROW_ANGLE = 0.75;
    private static final Double ARROW_HEAD_Y = Double.valueOf(Math.sin(ARROW_ANGLE) * ARROW_LENGTH);
    private static final Double ARROW_HEAD_X = Double.valueOf(Math.cos(ARROW_ANGLE) * ARROW_LENGTH);
    // ------------------------------------------------------------------------
    // Attributes
    // ------------------------------------------------------------------------
    /**
     * The lifeline which send the message
     */
    private Lifeline fStartLifeline = null;
    /**
     * The lifeline which receive the message
     */
    private Lifeline fEndLifeline = null;
    /**
     * The visiblitiy flag.
     */
    private boolean fVisible = true;

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

    @Override
    public int getX() {
        // returns the exact x coordinate
        return getX(false);
    }

    @Override
    public int getY() {
        /*
         * Note: lifeline.getY() return the y coordinate of the top left corner of the rectangle which contain the
         * lifeline name getHeight return the height of this rectangle The message y coordinate is then relative to this
         * position depending of its eventOccurrence Space between syncMessages is constant
         */
        if ((fStartLifeline != null) && (fEndLifeline != null)) {
            /*
             * Regular message, both ends are attached to a lifeline
             */
            return fEndLifeline.getY() + fEndLifeline.getHeight() + (Metrics.getMessageFontHeigth() + Metrics.getMessagesSpacing()) * getEndOccurrence();

        }
        /*
         * UML2 lost message kind
         */
        if (fStartLifeline != null) {
            return fStartLifeline.getY() + fStartLifeline.getHeight() + (Metrics.getMessageFontHeigth() + Metrics.getMessagesSpacing()) * getEndOccurrence();
        }

        /*
         * UML2 found message kind
         */
        if (fEndLifeline != null) {
            return fEndLifeline.getY() + fEndLifeline.getHeight() + (Metrics.getMessageFontHeigth() + Metrics.getMessagesSpacing()) * getEndOccurrence();
        }
        // return 0 by default
        return 0;
    }

    @Override
    public int getWidth() {
        // Returns the exact width
        return getWidth(false);
    }

    @Override
    public int getHeight() {
        return 0;
    }

    /**
     * Returns the graph node x coordinate.<br>
     * Depending on the quick parameter a approximative or exact value is return.<br>
     * The approximative value does not take into account if both message ends are connected to a Lifeline Execution
     * Occurrence.<br>
     * Execution occurrence on a lifeline increase the vertical line width which represent the lifeline, this directly
     * affect the message x coordinate and width.<br>
     * <br>
     * This method is typically used to faster execute none graphical operation like tooltip lookup.<br>
     * <br>
     *
     * @param quick true to get an approximative value<br>
     *            false to get the exact x value<br>
     * @return the graph node x coordinate
     */
    protected int getX(boolean quick) {
        int x = 0;
        int activationWidth = Metrics.EXECUTION_OCCURRENCE_WIDTH / 2;
        if ((fStartLifeline != null) && (fEndLifeline != null)) {
            x = fStartLifeline.getX() + Metrics.getLifelineWidth() / 2;
        } else {
            if (fStartLifeline != null) {
                x = fStartLifeline.getX() + Metrics.getLifelineWidth() / 2;
            }

            if (fEndLifeline != null) {
                x = fEndLifeline.getX() - Metrics.LIFELINE_SPACING / 2;
            }
        }

        if (quick) {
            return x;
        }

        if ((fStartLifeline != null) && (fEndLifeline != null) && (fStartLifeline.getX() > fEndLifeline.getX())) {
            activationWidth = -activationWidth;
        }

        if (isMessageStartInActivation(getEndOccurrence())) {
            x = x + activationWidth;
        }

        return x;
    }

    /**
     * Returns the graph node width.<br>
     * Depending on the quick parameter a approximative or exact value is returned.<br>
     * The approximative value does not take into account if both message ends are connected to a Lifeline Execution
     * Occurrence.<br>
     * Execution occurrence on a lifeline increase the vertical line width which represent the lifeline, this directly
     * affect the message x coordinate and width.<br>
     * <br>
     * This method is typically used to faster execute none graphical operation like tooltip lookup.<br>
     * <br>
     *
     * @param quick true to get an approximative value<br>
     *            false to get the exact x value
     * @return the graph node width
     */
    protected int getWidth(boolean quick) {
        int width = 0;
        int activationWidth = Metrics.EXECUTION_OCCURRENCE_WIDTH / 2;
        if ((fStartLifeline != null) && (fEndLifeline != null)) {
            if (fStartLifeline.equals(fEndLifeline)) {
                width = Metrics.INTERNAL_MESSAGE_WIDTH + Metrics.EXECUTION_OCCURRENCE_WIDTH;
            } else {
                width = fEndLifeline.getX() + Metrics.getLifelineWidth() / 2 - getX(true);
            }
        } else {
            if (fStartLifeline != null) {
                width = Metrics.swimmingLaneWidth() / 2;
            }
            if (fEndLifeline != null) {
                width = Metrics.swimmingLaneWidth() / 2;
            }
        }

        if (quick) {
            return width;
        }

        if ((fStartLifeline != null) && (fEndLifeline != null) && (fStartLifeline.getX() > fEndLifeline.getX())) {
            activationWidth = -activationWidth;
        }

        if (isMessageStartInActivation(getEndOccurrence())) {
            width = width - activationWidth;
        }

        if (isMessageEndInActivation(getEndOccurrence())) {
            width = width - activationWidth;
        }

        return width;
    }

    @Override
    public boolean isVisible(int x, int y, int width, int height) {
        // ***Common*** syncMessages visibility
        // draw the message only if at least one end is visible
        if (fEndLifeline != null && (fEndLifeline.isVisible(x, y, width, height)) || (fStartLifeline != null && fStartLifeline.isVisible(x, y, width, height))) {
            return true;
        }
        // In this case it can be a message which cross the whole visible area
        else if (fEndLifeline != null && (!fEndLifeline.isVisible(x, y, width, height)) && (fStartLifeline != null && !fStartLifeline.isVisible(x, y, width, height))) {
            if (fEndLifeline.getX() > x + width && fStartLifeline.getX() < x) {
                return true;
            } else if (fStartLifeline.getX() > x + width && fEndLifeline.getX() < x) {
                return true;
            }
        }
        return false;
    }

    /**
     * Sets the visibility value.
     *
     * @param value The visibility to set.
     */
    public void setVisible(boolean value) {
        fVisible = value;
    }

    /**
     * @return the visibility value.
     */
    public boolean isVisible() {
        return fVisible;
    }

    /**
     * Set the lifeline from which this message has been sent.
     *
     * @param lifeline - the message sender
     */
    public void setStartLifeline(Lifeline lifeline) {
        fStartLifeline = lifeline;
    }

    /**
     * Returns the lifeline from which this message has been sent.
     *
     * @return the message sender
     */
    public Lifeline getStartLifeline() {
        return fStartLifeline;
    }

    /**
     * Returns the lifeline which has received this message.
     *
     * @return the message receiver
     */
    public Lifeline getEndLifeline() {
        return fEndLifeline;
    }

    /**
     * Set the lifeline which has receive this message.
     *
     * @param lifeline the message receiver
     */
    public void setEndLifeline(Lifeline lifeline) {
        fEndLifeline = lifeline;
    }

    /**
     * Set the event occurrence when this message occurs.<br>
     *
     * @param occurrence the event occurrence to assign to this message.<br>
     * @see Lifeline Lifeline for more event occurence details
     */
    protected void setEventOccurrence(int occurrence) {
        setEndOccurrence(occurrence);
    }

    /**
     * Returns the event occurence when is message occurs.<br>
     *
     * @return the event occurrence assigned to this message.<br>
     * @see Lifeline Lifeline for more event occurence details
     */
    public int getEventOccurrence() {
        return getEndOccurrence();
    }

    /**
     * Determines if the given eventOccurence occurs on a executionOccurence owned by the sending lifeline.<br>
     * WARNING: this method will return a valid result only for execution occurrences which are visible in the View.<br>
     * As consequence this method is only used for drawing purpose, especially to determine the exact message x
     * coordinate and width.<br>
     *
     * @see BaseMessage#getX(boolean)
     * @param event the event occurrence to test
     * @return true if occurs on a execution occurrence owned by the sending lifeine, false otherwise
     */
    protected boolean isMessageStartInActivation(int event) {
        boolean inActivation = false;
        if ((fStartLifeline != null) && (fStartLifeline.getExecutions() != null)) {
            // int acIndex=startLifeline.getExecOccurrenceDrawIndex();
            // acIndex = first visible execution occurrence
            // for drawing speed reason with only search on the visivle subset
            int thisY = getY();
            for (int i = 0; i < fStartLifeline.getExecutions().size(); i++) {
                BasicExecutionOccurrence toDraw = (BasicExecutionOccurrence) fStartLifeline.getExecutions().get(i);
                if ((event >= toDraw.getStartOccurrence()) && (event <= toDraw.getEndOccurrence())) {
                    inActivation = true;
                }
                // if we are outside the visible area we stop right now
                // This works because execution occurrences are ordered along the Y axis
                if (toDraw.getY() > thisY) {
                    break;
                }
            }
        }
        return inActivation;
    }

    /**
     * Determines if the given event occurrence occurs on a execution occurrence owned by the receiving lifeline.<br>
     * WARNING: this method will return a valid result only for execution occurrences which are visible in the View.<br>
     * As consequence this method is only used for drawing purpose, especially to determine the exact message x
     * coordinate and width.<br>
     *
     * @see BaseMessage#getX(boolean)
     * @param event the event occurrence to test
     * @return true if occurs on a execution occurrence owned by the receiving lifeline, false otherwise
     */
    protected boolean isMessageEndInActivation(int event) {
        boolean inActivation = false;
        if ((fEndLifeline != null) && (fEndLifeline.getExecutions() != null)) {
            // acIndex = first visible execution occurrence
            // for drawing speed reason with only search on the visivle subset
            for (int i = 0; i < fEndLifeline.getExecutions().size(); i++) {
                BasicExecutionOccurrence toDraw = (BasicExecutionOccurrence) fEndLifeline.getExecutions().get(i);
                if ((event >= toDraw.getStartOccurrence()) && (event <= toDraw.getEndOccurrence())) {
                    inActivation = true;
                }
                // if we are outside the visible area we stop right now
                // This works because execution occurrences are ordered along the Y axis
                if (toDraw.getY() > getY()) {
                    break;
                }
            }
        }
        return inActivation;
    }

    @Override
    public boolean contains(int xValue, int yValue) {
        int x = getX();
        int y = getY();
        int width = getWidth();
        int height = getHeight();

        // Used to create a rectangle which contains the message label to allow selection when clicking the label
        int tempHeight = Metrics.MESSAGES_NAME_SPACING + Metrics.getMessageFontHeigth();

        // Is it a self message?
        if (fStartLifeline.equals(fEndLifeline)) {
            /*
             * Rectangle.contains(x,y, width, height) does not works with negative height or width We check here if the
             * rectangle width is negative.
             */
            if (getName().length() * Metrics.getAverageCharWidth() > Metrics.swimmingLaneWidth() - Metrics.EXECUTION_OCCURRENCE_WIDTH / 2 + -Metrics.INTERNAL_MESSAGE_WIDTH) {
                if (GraphNode.contains(x + Metrics.INTERNAL_MESSAGE_WIDTH + 10, y, Metrics.swimmingLaneWidth() - Metrics.EXECUTION_OCCURRENCE_WIDTH / 2 + -Metrics.INTERNAL_MESSAGE_WIDTH, Metrics.getMessageFontHeigth(), xValue, yValue)) {
                    return true;
                }
            } else {
                if (GraphNode.contains(x + Metrics.INTERNAL_MESSAGE_WIDTH + 10, y, getName().length() * Metrics.getAverageCharWidth(), Metrics.getMessageFontHeigth(), xValue, yValue)) {
                    return true;
                }
            }

            // Test if the point is in part 1 of the self message
            // see: "private void drawMessage (NGC context)" method for self message drawing schema
            if (GraphNode.contains(x, y - Metrics.MESSAGE_SELECTION_TOLERANCE / 2, Metrics.INTERNAL_MESSAGE_WIDTH / 2, Metrics.MESSAGE_SELECTION_TOLERANCE, xValue, yValue)) {
                return true;
            }

            // Test if the point is in part 3 of the self message
            if (GraphNode.contains(x + Metrics.INTERNAL_MESSAGE_WIDTH - Metrics.MESSAGE_SELECTION_TOLERANCE / 2, y, Metrics.MESSAGE_SELECTION_TOLERANCE, height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT, xValue, yValue)) {
                return true;
            }

            // Test if the point is in part 5 of the self message
            return (GraphNode.contains(x, y + height - Metrics.MESSAGE_SELECTION_TOLERANCE / 2 + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT, Metrics.INTERNAL_MESSAGE_WIDTH / 2, Metrics.MESSAGE_SELECTION_TOLERANCE, xValue, yValue));
        }
        return GraphNode.contains(x, y - tempHeight, width, tempHeight, xValue, yValue);
    }

    /**
     * Method to draw the message using the graphical context.
     *
     * @param context A graphical context to draw in.
     */
    protected void drawMessage(IGC context) {
        int fX = 0;
        int fY = 0;
        int fW = 0;
        int fH = 0;

        // temporary store the coordinates to avoid more methods calls
        int x = getX();
        int y = getY();
        int width = getWidth();
        int height = getHeight();

        ISDPreferences pref = SDViewPref.getInstance();

        // UML2 found message (always drawn from left to right)
        // or UML2 lost message (always drawn from left to right)
        if ((fStartLifeline == null || fEndLifeline == null) && !fStartLifeline.equals(fEndLifeline)) {
            // Draw the message label above the message and centered
            // The label is truncated if it cannot fit between the two message end
            // 2*Metrics.MESSAGES_NAME_SPACING = space above the label + space below the label
            IColor temp = context.getForeground();
            context.setForeground(pref.getFontColor(getColorPrefId()));
            context.drawTextTruncatedCentred(getName(), x, y - Metrics.getMessageFontHeigth() - 2 * Metrics.MESSAGES_NAME_SPACING, width, 2 * Metrics.MESSAGES_NAME_SPACING + Metrics.getMessageFontHeigth(), !isSelected());
            context.setForeground(temp);
            int margin = 0;
            if (fEndLifeline == null) {
                margin = Metrics.MESSAGE_CIRCLE_RAY;
            }

            // Draw the message main line
            context.drawLine(x, y, x + width, y + height);
            // Draw the two little lines which make a arrow part of the message
            Double xt = ARROW_HEAD_X;
            Double yt = ARROW_HEAD_Y;
            if (context.getLineStyle() == context.getLineSolidStyle()) {
                IColor backcolor = context.getBackground();
                context.setBackground(context.getForeground());
                int[] points = { x + width - margin, y + height, x + width - xt.intValue() - margin, y + height - yt.intValue(), x + width - xt.intValue() - margin, y + height + yt.intValue(), x + width - margin, y + height };
                context.fillPolygon(points);
                context.drawPolygon(points);
                context.setBackground(backcolor);
            } else {
                int currentStyle = context.getLineStyle();
                int currentWidth = context.getLineWidth();
                context.setLineWidth(currentWidth + 2);
                context.setLineStyle(context.getLineSolidStyle());
                context.drawLine(x + width - xt.intValue() - margin, y + height - yt.intValue(), x + width - margin, y + height);
                context.drawLine(x + width - xt.intValue() - margin, y + height + yt.intValue(), x + width - margin, y + height);
                context.setLineStyle(currentStyle);
                context.setLineWidth(currentWidth);
            }
            IColor storedColor = context.getBackground();
            context.setBackground(context.getForeground());

            // Draw a circle at the message end (endLifeline side)
            int ray = Metrics.MESSAGE_CIRCLE_RAY;
            if (context.getLineWidth() != Metrics.NORMAL_LINE_WIDTH) {
                ray = ray + Metrics.SELECTION_LINE_WIDTH - Metrics.NORMAL_LINE_WIDTH;
            }
            if (fStartLifeline == null) {
                context.fillOval(x - ray, y - ray, ray * 2, ray * 2);
            } else {
                context.fillOval(x + width - ray, y + height - ray, ray * 2, ray * 2);
            }
            context.setBackground(storedColor);
            context.setForeground(pref.getFontColor(getColorPrefId()));
            fX = x;
            fY = y - yt.intValue();
            fW = width;
            fH = height + 2 * yt.intValue();
        }
        // it is self message (always drawn at the left side of the owning lifeLifeline)
        else if (fStartLifeline != null && fEndLifeline != null && fStartLifeline.equals(fEndLifeline)) {
            /*
             * Self syncMessages are drawn in 5 parts 1 -----------+ + 2 + | | | 3 | + 5 + 4 -----------+
             */
            int tempy = Metrics.INTERNAL_MESSAGE_WIDTH / 2;
            if (Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT <= Metrics.INTERNAL_MESSAGE_WIDTH) {
                tempy = Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT / 2;
            }

            // Part 1
            context.drawLine(x, y, x + Metrics.INTERNAL_MESSAGE_WIDTH / 2, y);
            // Part 3
            context.drawLine(x + Metrics.INTERNAL_MESSAGE_WIDTH, y + tempy, x + Metrics.INTERNAL_MESSAGE_WIDTH, y + height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT - tempy);
            // Part 5
            context.drawLine(x, y + height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT, x + Metrics.INTERNAL_MESSAGE_WIDTH / 2, y + height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT);

            Double xt = ARROW_HEAD_X;
            Double yt = ARROW_HEAD_Y;

            fX = x;
            fY = y;
            fW = Metrics.INTERNAL_MESSAGE_WIDTH;
            fH = height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT;

            // Draw the two little lines which make a arrow part of the message
            if (context.getLineStyle() == context.getLineSolidStyle()) {
                IColor backcolor = context.getBackground();
                context.setBackground(context.getForeground());
                int[] points = { x, y + height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT, x + xt.intValue(), y + height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT + yt.intValue(), x + xt.intValue(),
                        y + height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT - yt.intValue(), x, y + height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT };
                context.fillPolygon(points);
                context.drawPolygon(points);
                context.setBackground(backcolor);
            } else {
                int currentStyle = context.getLineStyle();
                int currentWidth = context.getLineWidth();
                context.setLineWidth(currentWidth + 2);
                context.setLineStyle(context.getLineSolidStyle());
                context.drawLine(x + xt.intValue(), y + height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT + yt.intValue(), x, y + height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT);
                context.drawLine(x + xt.intValue(), y + height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT - yt.intValue(), x, y + height + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT);
                context.setLineStyle(currentStyle);
                context.setLineWidth(currentWidth);
            }

            // Part 2
            context.drawArc(x, y, Metrics.INTERNAL_MESSAGE_WIDTH, 2 * tempy, 0, 90);
            // Part 4
            context.drawArc(x, y + Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT, Metrics.INTERNAL_MESSAGE_WIDTH, -2 * tempy, 0, -90);

            // Draw the message label above the message and centered
            // The label is truncated if it cannot fit between the two message end
            // 2*Metrics.MESSAGES_NAME_SPACING = space above the label + space below the label

            // the space available for the text is sorter if are drawing internal message on the last lifeline
            context.setForeground(pref.getFontColor(getColorPrefId()));
            if (fStartLifeline.getIndex() == fStartLifeline.getFrame().getHorizontalIndex()) {
                context.drawTextTruncated(getName(), x + width + Metrics.INTERNAL_MESSAGE_V_MARGIN / 2, y, Metrics.swimmingLaneWidth() / 2 - Metrics.EXECUTION_OCCURRENCE_WIDTH + -Metrics.INTERNAL_MESSAGE_WIDTH, +Metrics.MESSAGES_NAME_SPACING
                        - Metrics.getMessageFontHeigth(), !isSelected());
            } else {
                context.drawTextTruncated(getName(), x + width + Metrics.INTERNAL_MESSAGE_V_MARGIN / 2, y, Metrics.swimmingLaneWidth() - Metrics.EXECUTION_OCCURRENCE_WIDTH + -Metrics.INTERNAL_MESSAGE_WIDTH,
                        +Metrics.MESSAGES_NAME_SPACING - Metrics.getMessageFontHeigth(), !isSelected());
            }
        }
        // it is regular message
        else if (fStartLifeline != null && fEndLifeline != null) {
            // Draw the message main line
            context.drawLine(x, y, x + width, y + height);

            int spaceBTWStartEnd = fEndLifeline.getX() - fStartLifeline.getX();

            double a = height;
            double b = width;
            double angle = Math.atan(a / b);
            // Compute the coordinates of the two little lines which make the arrow part of the message
            int sign = 1;
            if (spaceBTWStartEnd < 0) {
                sign = -1;
            }
            Double x1 = Double.valueOf(sign * Math.cos(angle - ARROW_ANGLE) * ARROW_LENGTH);
            Double y1 = Double.valueOf(sign * Math.sin(angle - ARROW_ANGLE) * ARROW_LENGTH);
            Double x2 = Double.valueOf(sign * Math.cos(angle + ARROW_ANGLE) * ARROW_LENGTH);
            Double y2 = Double.valueOf(sign * Math.sin(angle + ARROW_ANGLE) * ARROW_LENGTH);

            fX = getX();
            fY = y + height - y2.intValue();
            fW = getWidth();
            fH = y2.intValue() - y1.intValue() + 1;
            if (fW < 0) {
                fW = -fW;
                fX = fX - fW;
            }

            if (fH < 0) {
                fH = -fH;
                fY = fY - fH;
            }

            // Draw the two little lines which make a arrow part of the message
            if (context.getLineStyle() == context.getLineSolidStyle()) {
                IColor backcolor = context.getBackground();
                context.setBackground(context.getForeground());
                int[] points = { x + width - x1.intValue(), y + height - y1.intValue(), x + width, y + height, x + width - x2.intValue(), y + height - y2.intValue(), x + width - x1.intValue(), y + height - y1.intValue() };
                context.fillPolygon(points);
                context.drawPolygon(points);
                context.setBackground(backcolor);
            } else {
                int currentStyle = context.getLineStyle();
                int currentWidth = context.getLineWidth();
                context.setLineWidth(currentWidth + 2);
                context.setLineStyle(context.getLineSolidStyle());
                context.drawLine(x + width - x1.intValue(), y + height - y1.intValue(), x + width, y + height);
                context.drawLine(x + width - x2.intValue(), y + height - y2.intValue(), x + width, y + height);
                context.setLineStyle(currentStyle);
                context.setLineWidth(currentWidth);
            }

            // Draw the message label above the message and centered
            // The label is truncated if it cannot fit between the two message end
            // 2*Metrics.MESSAGES_NAME_SPACING = space above the label + space below the label
            context.setForeground(pref.getFontColor(getColorPrefId()));
            if (spaceBTWStartEnd > 0) {
                context.drawTextTruncatedCentred(getName(), x, y + height / 2 - (2 * Metrics.MESSAGES_NAME_SPACING + Metrics.getMessageFontHeigth()), width, 2 * Metrics.MESSAGES_NAME_SPACING + Metrics.getMessageFontHeigth(), !isSelected());
            } else {
                context.drawTextTruncatedCentred(getName(), x + width, y + height / 2 - (2 * Metrics.MESSAGES_NAME_SPACING + Metrics.getMessageFontHeigth()), -width, 2 * Metrics.MESSAGES_NAME_SPACING + +Metrics.getMessageFontHeigth(), !isSelected());
            }
        }
    }

    @Override
    public void draw(IGC context) {
        if (!isVisible()) {
            return;
        }

        // Draw it selected?*/
        if (isSelected()) {
            ISDPreferences pref = SDViewPref.getInstance();
            /*
             * Draw it twice First time, bigger inverting selection colors Second time, regular drawing using selection
             * colors This create the highlight effect
             */
            context.setForeground(pref.getBackGroundColorSelection());
            context.setLineWidth(Metrics.SELECTION_LINE_WIDTH);
            drawMessage(context);
            context.setBackground(pref.getBackGroundColorSelection());
            context.setForeground(pref.getForeGroundColorSelection());
            // Second drawing is done after
        }
        context.setLineWidth(Metrics.NORMAL_LINE_WIDTH);
        if (hasFocus()) {
            context.setDrawTextWithFocusStyle(true);
        }
        drawMessage(context);
        int oldStyle = context.getLineStyle();
        if (hasFocus()) {
            context.setDrawTextWithFocusStyle(false);
            drawFocus(context);
        }
        // restore the context
        context.setLineStyle(oldStyle);
    }

    /**
     * Determine if two messages are identical. This default implementation considers that overlapping messages with
     * same coordinates are identical.
     *
     * @param message - the message to compare with
     * @return true if identical false otherwise
     *
     * @see org.eclipse.tracecompass.tmf.ui.views.uml2sd.core.GraphNode#isSameAs(org.eclipse.tracecompass.tmf.ui.views.uml2sd.core.GraphNode)
     */
    @Override
    public boolean isSameAs(GraphNode message) {
        if (message == null) {
            return false;
        }
        if (!(message instanceof BaseMessage)) {
            return super.isSameAs(message);
        }
        return ((getX() == message.getX()) && (getY() == message.getY()) && (getWidth() == message.getWidth()) && (getHeight() == message.getHeight()));
    }

    /**
     * Method drawRot.
     *
     * @param x A x coordinate
     * @param y A y coordinate
     * @param w A width
     * @param h A height
     * @param context A graphical context
     */
    public void drawRot(int x, int y, int w, int h, IGC context) {
        double angleA = Math.atan2(getHeight(), getWidth());
        double cosA = Math.cos(angleA);
        double sinA = Math.sin(angleA);

        int gx = getX();
        int gy = getY();

        int localHeight = h;
        localHeight = localHeight / 2;

        double cw = Math.sqrt(w * w + getHeight() * getHeight());

        int x1 = Math.round((float) ((x - gx) * cosA - (y - gy) * sinA));
        int y1 = Math.round((float) ((x - gx) * sinA + (y - gy) * cosA));

        int x2 = Math.round((float) (cw * cosA - (y - gy) * sinA));
        int y2 = Math.round((float) (cw * sinA + (y - gy) * cosA));

        int x3 = Math.round((float) (cw * cosA - (localHeight) * sinA));
        int y3 = Math.round((float) (cw * sinA + (localHeight) * cosA));

        int x4 = Math.round((float) ((x - gx) * cosA - (localHeight) * sinA));
        int y4 = Math.round((float) ((x - gx) * sinA + (localHeight) * cosA));

        int[] points = { x1 + getX(), y1 + getY(), x2 + getX(), y2 + getY(), x3 + getX(), y3 + getY(), x4 + getX(), y4 + getY() };
        context.drawPolygon(points);
    }

    @Override
    public void drawFocus(IGC context) {

        ISDPreferences pref = SDViewPref.getInstance();

        if ((!fStartLifeline.equals(fEndLifeline)) && (getStartOccurrence() == getEndOccurrence())) {
            context.setLineStyle(context.getLineDotStyle());
            context.setLineWidth(Metrics.NORMAL_LINE_WIDTH);
            context.setBackground(pref.getBackGroundColorSelection());
            context.setForeground(pref.getForeGroundColorSelection());
            context.drawFocus(getX(), getY() - 3, getWidth(), getHeight() + 6);
        } else if ((fStartLifeline == fEndLifeline) && (getStartOccurrence() == getEndOccurrence())) {
            context.drawFocus(getX(), getY() - 3, getWidth(), Metrics.SYNC_INTERNAL_MESSAGE_HEIGHT + 6);
        } else if ((!fStartLifeline.equals(fEndLifeline)) && (getStartOccurrence() != getEndOccurrence())) {
            context.setLineStyle(context.getLineDotStyle());
            context.setLineWidth(Metrics.NORMAL_LINE_WIDTH);
            context.setBackground(pref.getBackGroundColor(ISDPreferences.PREF_LIFELINE_HEADER));
            context.setForeground(pref.getForeGroundColor(ISDPreferences.PREF_LIFELINE_HEADER));
            drawRot(getX(), getY() - 5, getWidth(), 10, context);
        } else {
            super.drawFocus(context);
        }
    }
}
