"use strict";
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
var geometry_1 = require("../geometry");
var calcs_1 = require("../utils/calcs");
var constants_1 = require("../utils/constants");
var math_1 = require("../utils/math");
function cutToLength(s, maxLength) {
    return s.length <= maxLength ? s : s.slice(0, Math.max(0, maxLength - 1)) + "\u2026";
}
function linkTextLayout(rectWidth, rectHeight, measure, config, nodesWithoutRoom, currentY, anchorRadius, rawTextGetter, valueGetter, valueFormatter, maxTextLength, diskCenter, containerBackgroundColor) {
    var linkLabel = config.linkLabel, sectorLineStroke = config.sectorLineStroke;
    var maxDepth = nodesWithoutRoom.reduce(function (p, n) { return Math.max(p, n.depth); }, 0);
    var yRelativeIncrement = Math.sin(linkLabel.stemAngle) * linkLabel.minimumStemLength;
    var rowPitch = linkLabel.fontSize + linkLabel.spacing;
    var validBackgroundColor = calcs_1.isColorValid(containerBackgroundColor)
        ? containerBackgroundColor
        : 'rgba(255, 255, 255, 0)';
    var contrastTextColor = containerBackgroundColor
        ? calcs_1.makeHighContrastColor(linkLabel.textColor, validBackgroundColor)
        : linkLabel.textColor;
    var strokeColor = containerBackgroundColor
        ? calcs_1.makeHighContrastColor(sectorLineStroke, validBackgroundColor)
        : undefined;
    var labelFontSpec = __assign(__assign({ fontStyle: 'normal', fontVariant: 'normal', fontFamily: config.fontFamily, fontWeight: 'normal' }, linkLabel), { textColor: contrastTextColor });
    var valueFontSpec = __assign(__assign(__assign({ fontStyle: 'normal', fontVariant: 'normal', fontFamily: config.fontFamily, fontWeight: 'normal' }, linkLabel), linkLabel.valueFont), { textColor: contrastTextColor });
    var linkLabels = nodesWithoutRoom
        .filter(function (n) { return n.depth === maxDepth; })
        .sort(function (n1, n2) { return Math.abs(n2.x0 - n2.x1) - Math.abs(n1.x0 - n1.x1); })
        .slice(0, linkLabel.maxCount)
        .sort(function (n1, n2) {
        var mid1 = geometry_1.meanAngle(n1.x0, n1.x1);
        var mid2 = geometry_1.meanAngle(n2.x0, n2.x1);
        var dist1 = Math.min(Math.abs(mid1 - constants_1.TAU / 4), Math.abs(mid1 - (3 * constants_1.TAU) / 4));
        var dist2 = Math.min(Math.abs(mid2 - constants_1.TAU / 4), Math.abs(mid2 - (3 * constants_1.TAU) / 4));
        return dist1 - dist2;
    })
        .map(function (node) {
        var midAngle = math_1.trueBearingToStandardPositionAngle((node.x0 + node.x1) / 2);
        var north = midAngle < constants_1.TAU / 2 ? 1 : -1;
        var rightSide = constants_1.TAU / 4 < midAngle && midAngle < (3 * constants_1.TAU) / 4 ? 0 : 1;
        var west = rightSide ? 1 : -1;
        var cos = Math.cos(midAngle);
        var sin = Math.sin(midAngle);
        var x0 = cos * anchorRadius;
        var y0 = sin * anchorRadius;
        var x = cos * (anchorRadius + linkLabel.radiusPadding);
        var y = sin * (anchorRadius + linkLabel.radiusPadding);
        var poolIndex = rightSide + (1 - north);
        var relativeY = north * y;
        currentY[poolIndex] = Math.max(currentY[poolIndex] + rowPitch, relativeY + yRelativeIncrement, rowPitch / 2);
        var cy = north * currentY[poolIndex];
        var stemFromX = x;
        var stemFromY = y;
        var stemToX = x + north * west * cy - west * relativeY;
        var stemToY = cy;
        var rawText = rawTextGetter(node);
        var labelText = cutToLength(rawText, maxTextLength);
        var valueText = valueFormatter(valueGetter(node));
        var labelFontSpec = __assign({ fontStyle: 'normal', fontVariant: 'normal', fontFamily: config.fontFamily, fontWeight: 'normal' }, linkLabel);
        var valueFontSpec = __assign(__assign({ fontStyle: 'normal', fontVariant: 'normal', fontFamily: config.fontFamily, fontWeight: 'normal' }, linkLabel), linkLabel.valueFont);
        var translateX = stemToX + west * (linkLabel.horizontalStemLength + linkLabel.gap);
        var valueWidth = measure(linkLabel.fontSize, [__assign(__assign({}, valueFontSpec), { text: valueText })])[0].width;
        var widthAdjustment = valueWidth + 2 * linkLabel.fontSize;
        var allottedLabelWidth = Math.max(0, rightSide
            ? rectWidth - diskCenter.x - translateX - widthAdjustment
            : diskCenter.x + translateX - widthAdjustment);
        var _a = linkLabel.fontSize / 2 <= cy + diskCenter.y && cy + diskCenter.y <= rectHeight - linkLabel.fontSize / 2
            ? fitText(measure, labelText, allottedLabelWidth, linkLabel.fontSize, __assign(__assign({}, labelFontSpec), { text: labelText }))
            : { text: '', width: 0, verticalOffset: 0 }, text = _a.text, width = _a.width, verticalOffset = _a.verticalOffset;
        var linkLabels = [
            [x0, y0],
            [stemFromX, stemFromY],
            [stemToX, stemToY],
            [stemToX + west * linkLabel.horizontalStemLength, stemToY],
        ];
        var translate = [translateX, stemToY];
        var textAlign = rightSide ? 'left' : 'right';
        return {
            linkLabels: linkLabels,
            translate: translate,
            textAlign: textAlign,
            text: text,
            valueText: valueText,
            width: width,
            valueWidth: valueWidth,
            verticalOffset: verticalOffset,
            labelFontSpec: labelFontSpec,
            valueFontSpec: valueFontSpec,
        };
    })
        .filter(function (_a) {
        var text = _a.text;
        return text !== '';
    });
    return { linkLabels: linkLabels, valueFontSpec: valueFontSpec, labelFontSpec: labelFontSpec, strokeColor: strokeColor };
    function fitText(measure, desiredText, allottedWidth, fontSize, box) {
        var desiredLength = desiredText.length;
        var response = function (v) { return measure(fontSize, [__assign(__assign({}, box), { text: box.text.slice(0, Math.max(0, v)) })])[0].width; };
        var visibleLength = calcs_1.monotonicHillClimb(response, desiredLength, allottedWidth, calcs_1.integerSnap);
        var text = visibleLength < 2 && desiredLength >= 2 ? '' : cutToLength(box.text, visibleLength);
        var _a = measure(fontSize, [__assign(__assign({}, box), { text: text })])[0], width = _a.width, emHeightAscent = _a.emHeightAscent, emHeightDescent = _a.emHeightDescent;
        return {
            width: width,
            verticalOffset: -(emHeightDescent + emHeightAscent) / 2,
            text: text,
        };
    }
}
exports.linkTextLayout = linkTextLayout;
//# sourceMappingURL=link_text_layout.js.map