"use strict";
var __read = (this && this.__read) || function (o, n) {
    var m = typeof Symbol === "function" && o[Symbol.iterator];
    if (!m) return o;
    var i = m.call(o), r, ar = [], e;
    try {
        while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
    }
    catch (error) { e = { error: error }; }
    finally {
        try {
            if (r && !r.done && (m = i["return"])) m.call(i);
        }
        finally { if (e) throw e.error; }
    }
    return ar;
};
var __spread = (this && this.__spread) || function () {
    for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
    return ar;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.renderPartitionCanvas2d = void 0;
var color_calcs_1 = require("../../../../common/color_calcs");
var constants_1 = require("../../../../common/constants");
var text_utils_1 = require("../../../../common/text_utils");
var canvas_1 = require("../../../../renderers/canvas");
var viewmodel_1 = require("../../layout/viewmodel/viewmodel");
var LINE_WIDTH_MULT = 10;
var TAPER_OFF_LIMIT = 50;
function renderTextRow(ctx, _a, linkLabelTextColor) {
    var fontSize = _a.fontSize, fillTextColor = _a.fillTextColor, rotation = _a.rotation, verticalAlignment = _a.verticalAlignment, leftAlign = _a.leftAlign, container = _a.container, clipText = _a.clipText;
    return function (currentRow) {
        var crx = leftAlign
            ? currentRow.rowAnchorX - currentRow.maximumLength / 2
            : currentRow.rowAnchorX - (Math.cos(rotation) * currentRow.length) / 2;
        var cry = -currentRow.rowAnchorY + (Math.sin(rotation) * currentRow.length) / 2;
        if (!Number.isFinite(crx) || !Number.isFinite(cry)) {
            return;
        }
        canvas_1.withContext(ctx, function (ctx) {
            ctx.scale(1, -1);
            if (clipText) {
                ctx.rect(container.x0 + 1, container.y0 + 1, container.x1 - container.x0 - 2, container.y1 - container.y0 - 2);
                ctx.clip();
            }
            ctx.beginPath();
            ctx.translate(crx, cry);
            ctx.rotate(-rotation);
            ctx.fillStyle = fillTextColor !== null && fillTextColor !== void 0 ? fillTextColor : linkLabelTextColor;
            ctx.textBaseline = verticalAlignment;
            currentRow.rowWords.forEach(function (box) {
                ctx.font = text_utils_1.cssFontShorthand(box, fontSize);
                ctx.fillText(box.text, box.width / 2 + box.wordBeginning, 0);
            });
            ctx.closePath();
        });
    };
}
function renderTextRows(ctx, rowSet, linkLabelTextColor) {
    rowSet.rows.forEach(renderTextRow(ctx, rowSet, linkLabelTextColor));
}
function renderRowSets(ctx, rowSets, linkLabelTextColor) {
    rowSets.forEach(function (rowSet) { return renderTextRows(ctx, rowSet, linkLabelTextColor); });
}
function renderTaperedBorder(ctx, _a) {
    var strokeWidth = _a.strokeWidth, strokeStyle = _a.strokeStyle, fillColor = _a.fillColor, x0 = _a.x0, x1 = _a.x1, y0px = _a.y0px, y1px = _a.y1px;
    var X0 = x0 - constants_1.TAU / 4;
    var X1 = x1 - constants_1.TAU / 4;
    ctx.fillStyle = fillColor;
    ctx.beginPath();
    ctx.arc(0, 0, y0px, X0, X0);
    ctx.arc(0, 0, y1px, X0, X1, false);
    ctx.arc(0, 0, y0px, X1, X0, true);
    ctx.fill();
    if (strokeWidth > 0.001 && !(x0 === 0 && x1 === constants_1.TAU)) {
        ctx.lineWidth = strokeWidth;
        var tapered = x1 - x0 < (15 * constants_1.TAU) / 360;
        if (tapered) {
            ctx.beginPath();
            ctx.arc(0, 0, y1px, X0, X1, false);
            ctx.stroke();
            ctx.beginPath();
            ctx.arc(0, 0, y0px, X1, X0, true);
            ctx.stroke();
            ctx.fillStyle = strokeStyle;
            ctx.beginPath();
            var yThreshold = Math.max(TAPER_OFF_LIMIT, (LINE_WIDTH_MULT * strokeWidth) / (X1 - X0));
            var beta = strokeWidth / yThreshold;
            ctx.arc(0, 0, y0px, X0, X0 + beta * (yThreshold / y0px));
            ctx.arc(0, 0, Math.min(yThreshold, y1px), X0 + beta, X0 + beta);
            ctx.arc(0, 0, y1px, X0 + beta * (yThreshold / y1px), X0, true);
            ctx.arc(0, 0, y0px, X0, X0);
            ctx.fill();
        }
        else {
            ctx.strokeStyle = strokeStyle;
            ctx.stroke();
        }
    }
}
function renderSectors(ctx, quadViewModel) {
    canvas_1.withContext(ctx, function (ctx) {
        ctx.scale(1, -1);
        quadViewModel.forEach(function (quad) {
            if (quad.x0 === quad.x1)
                return;
            renderTaperedBorder(ctx, quad);
        });
    });
}
function renderRectangles(ctx, quadViewModel) {
    canvas_1.withContext(ctx, function (ctx) {
        ctx.scale(1, -1);
        quadViewModel.forEach(function (_a) {
            var strokeWidth = _a.strokeWidth, fillColor = _a.fillColor, x0 = _a.x0, x1 = _a.x1, y0px = _a.y0px, y1px = _a.y1px;
            if (x1 - x0 >= 1 && y1px - y0px >= 1) {
                ctx.fillStyle = fillColor;
                ctx.beginPath();
                ctx.moveTo(x0, y0px);
                ctx.lineTo(x0, y1px);
                ctx.lineTo(x1, y1px);
                ctx.lineTo(x1, y0px);
                ctx.lineTo(x0, y0px);
                ctx.fill();
                if (strokeWidth > 0.001) {
                    ctx.lineWidth = strokeWidth;
                    ctx.stroke();
                }
            }
        });
    });
}
function renderFillOutsideLinks(ctx, outsideLinksViewModel, linkLabelTextColor, linkLabelLineWidth) {
    canvas_1.withContext(ctx, function (ctx) {
        ctx.lineWidth = linkLabelLineWidth;
        ctx.strokeStyle = linkLabelTextColor;
        outsideLinksViewModel.forEach(function (_a) {
            var points = _a.points;
            ctx.beginPath();
            ctx.moveTo(points[0][0], points[0][1]);
            for (var i = 1; i < points.length; i++) {
                ctx.lineTo(points[i][0], points[i][1]);
            }
            ctx.stroke();
        });
    });
}
function renderLinkLabels(ctx, linkLabelFontSize, linkLabelLineWidth, _a, linkLineColor) {
    var linkLabels = _a.linkLabels, labelFontSpec = _a.labelFontSpec, valueFontSpec = _a.valueFontSpec, strokeColor = _a.strokeColor;
    var labelColor = color_calcs_1.addOpacity(labelFontSpec.textColor, labelFontSpec.textOpacity);
    var valueColor = color_calcs_1.addOpacity(valueFontSpec.textColor, valueFontSpec.textOpacity);
    var labelValueGap = linkLabelFontSize / 2;
    canvas_1.withContext(ctx, function (ctx) {
        ctx.lineWidth = linkLabelLineWidth;
        linkLabels.forEach(function (_a) {
            var linkLabels = _a.linkLabels, translate = _a.translate, textAlign = _a.textAlign, text = _a.text, valueText = _a.valueText, width = _a.width, valueWidth = _a.valueWidth;
            ctx.beginPath();
            ctx.moveTo.apply(ctx, __spread(linkLabels[0]));
            linkLabels.slice(1).forEach(function (point) { return ctx.lineTo.apply(ctx, __spread(point)); });
            ctx.strokeStyle = strokeColor !== null && strokeColor !== void 0 ? strokeColor : linkLineColor;
            ctx.stroke();
            canvas_1.withContext(ctx, function (ctx) {
                ctx.translate.apply(ctx, __spread(translate));
                ctx.scale(1, -1);
                ctx.textAlign = textAlign;
                ctx.strokeStyle = labelColor;
                ctx.fillStyle = labelColor;
                ctx.font = labelFontSpec.fontStyle + " " + labelFontSpec.fontVariant + " " + labelFontSpec.fontWeight + " " + linkLabelFontSize + "px " + labelFontSpec.fontFamily;
                ctx.fillText(text, textAlign === 'right' ? -valueWidth - labelValueGap : 0, 0);
                ctx.strokeStyle = valueColor;
                ctx.fillStyle = valueColor;
                ctx.font = valueFontSpec.fontStyle + " " + valueFontSpec.fontVariant + " " + valueFontSpec.fontWeight + " " + linkLabelFontSize + "px " + valueFontSpec.fontFamily;
                ctx.fillText(valueText, textAlign === 'left' ? width + labelValueGap : 0, 0);
            });
        });
    });
}
var midlineOffset = 0.35;
var innerPad = midlineOffset * viewmodel_1.panelTitleFontSize;
function renderPartitionCanvas2d(ctx, dpr, _a) {
    var width = _a.width, height = _a.height, panelTitle = _a.panelTitle, config = _a.config, quadViewModel = _a.quadViewModel, rowSets = _a.rowSets, outsideLinksViewModel = _a.outsideLinksViewModel, linkLabelViewModels = _a.linkLabelViewModels, diskCenter = _a.diskCenter, outerRadius = _a.outerRadius;
    var sectorLineWidth = config.sectorLineWidth, sectorLineStroke = config.sectorLineStroke, linkLabel = config.linkLabel;
    var linkLineColor = color_calcs_1.addOpacity(linkLabel.textColor, linkLabel.textOpacity);
    canvas_1.withContext(ctx, function (ctx) {
        ctx.scale(dpr, dpr);
        ctx.textAlign = 'center';
        ctx.textBaseline = 'bottom';
        ctx.fillText(panelTitle, viewmodel_1.isSunburst(config.partitionLayout) ? diskCenter.x : diskCenter.x + (config.width * width) / 2, viewmodel_1.isSunburst(config.partitionLayout)
            ? config.linkLabel.maxCount > 0
                ? diskCenter.y - (config.height * height) / 2 + viewmodel_1.panelTitleFontSize
                : diskCenter.y - outerRadius - innerPad
            : diskCenter.y + 12);
        ctx.textBaseline = 'middle';
        ctx.translate(diskCenter.x, diskCenter.y);
        ctx.scale(1, -1);
        ctx.lineJoin = 'round';
        ctx.strokeStyle = sectorLineStroke;
        ctx.lineWidth = sectorLineWidth;
        canvas_1.renderLayers(ctx, [
            function (ctx) {
                return viewmodel_1.isSunburst(config.partitionLayout) ? renderSectors(ctx, quadViewModel) : renderRectangles(ctx, quadViewModel);
            },
            function (ctx) { return renderRowSets(ctx, rowSets, linkLineColor); },
            function (ctx) {
                return renderFillOutsideLinks(ctx, outsideLinksViewModel, linkLineColor, linkLabel.lineWidth);
            },
            function (ctx) {
                return renderLinkLabels(ctx, linkLabel.fontSize, linkLabel.lineWidth, linkLabelViewModels, linkLineColor);
            },
        ]);
    });
}
exports.renderPartitionCanvas2d = renderPartitionCanvas2d;
//# sourceMappingURL=canvas_renderers.js.map