var ARROW_SCALE = 0.4;
export var LOOP_SCALE = 0.6;
var ARROW_SIZE_RATIO_SCALE = 2.2;
export var getSelfLoopControlPoints = function (x, y, size, a) {
    if (a === void 0) { a = 0; }
    return {
        x1: x - (size + a) * 7,
        y1: y,
        x2: x,
        y2: y + (size + a) * 7
    };
};
var getArrowPoints = function (x, y, d, sX, sY, size, aSize) {
    var aX = x + ((sX - x) * (d - aSize - size)) / d;
    var aY = y + ((sY - y) * (d - aSize - size)) / d;
    var vX = ((sX - x) * aSize) / d;
    var vY = ((sY - y) * aSize) / d;
    return { aX: aX, aY: aY, vX: vX, vY: vY };
};
var getFirstArrowPoints = function (cp, sX, sY, size, aSize) {
    var d = Math.sqrt(Math.pow(sX - cp.x1, 2) + Math.pow(sY - cp.y1, 2));
    return getArrowPoints(cp.x2, cp.y2, d, sX, sY, size, aSize);
};
var getSecondArrowPoints = function (cp, sX, sY, size, aSize) {
    var d = Math.sqrt(Math.pow(sX - cp.x1, 2) + Math.pow(sY - cp.y1, 2));
    return getArrowPoints(cp.x1, cp.y1, d, sX, sY, size, aSize);
};
var drawArrow = function (context, aX, aY, vX, vY) {
    context.beginPath();
    context.moveTo(aX + vX, aY + vY);
    context.lineTo(aX + vY * ARROW_SCALE, aY - vX * ARROW_SCALE);
    context.lineTo(aX - vY * ARROW_SCALE, aY + vX * ARROW_SCALE);
    context.lineTo(aX + vX, aY + vY);
    context.closePath();
    context.fill();
};
var drawSelfRelationLoop = function (context, edgeData, sourceData) {
    var size = edgeData.size, color = edgeData.color, _a = edgeData.arrowSizeRatio, arrowSizeRatio = _a === void 0 ? 1 : _a;
    var sX = sourceData.x;
    var sY = sourceData.y;
    var sSize = sourceData.size;
    var scale = sSize * LOOP_SCALE;
    var cp = getSelfLoopControlPoints(sX, sY, scale);
    context.strokeStyle = color;
    context.lineWidth = size;
    var bezier = new Path2D();
    if (edgeData.type === 'arrow' || edgeData.type === 'doubleArrow') {
        context.fillStyle = color;
        if (edgeData.type === 'doubleArrow') {
            var firstArrowPoints = getFirstArrowPoints(cp, sX, sY, sSize, size * arrowSizeRatio * ARROW_SIZE_RATIO_SCALE);
            drawArrow(context, firstArrowPoints.aX, firstArrowPoints.aY, firstArrowPoints.vX, firstArrowPoints.vY);
            bezier.moveTo(firstArrowPoints.aX, firstArrowPoints.aY);
        }
        else {
            bezier.moveTo(sX, sY);
        }
        var secondArrowPoints = getSecondArrowPoints(cp, sX, sY, sSize, size * arrowSizeRatio * ARROW_SIZE_RATIO_SCALE);
        bezier.bezierCurveTo(cp.x2, cp.y2, cp.x1, cp.y1, secondArrowPoints.aX, secondArrowPoints.aY);
        context.stroke(bezier);
        drawArrow(context, secondArrowPoints.aX, secondArrowPoints.aY, secondArrowPoints.vX, secondArrowPoints.vY);
    }
    else {
        bezier.moveTo(sX, sY);
        bezier.bezierCurveTo(cp.x1, cp.y1, cp.x2, cp.y2, sX, sY);
        context.stroke(bezier);
    }
    return bezier;
};
export { drawSelfRelationLoop };
