var __rest = this && this.__rest || function(s, e) {
    var t = {};
    for (var p in s) Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0 && (t[p] = s[p]);
    if (null != s && "function" == typeof Object.getOwnPropertySymbols) {
        var i = 0;
        for (p = Object.getOwnPropertySymbols(s); i < p.length; i++) e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]) && (t[p[i]] = s[p[i]]);
    }
    return t;
};

import { merge, isValidNumber, isNil, isLess, isGreater, isNumberClose as isClose, polarToCartesian, computeQuadrant } from "@visactor/vutils";

import { LabelBase } from "./base";

import { isQuadrantRight, isQuadrantLeft, lineCirclePoints, connectLineRadian, checkBoundsOverlap, getAlignOffset } from "./util";

import { registerLabelComponent } from "./data-label-register";

import { isFunction } from "@visactor/vutils";

export class ArcInfo {
    constructor(refDatum, center, outerCenter, quadrant, radian, middleAngle, innerRadius, outerRadius, circleCenter) {
        this.refDatum = refDatum, this.center = center, this.outerCenter = outerCenter, 
        this.quadrant = quadrant, this.radian = radian, this.middleAngle = middleAngle, 
        this.innerRadius = innerRadius, this.outerRadius = outerRadius, this.circleCenter = circleCenter, 
        this.labelVisible = !0;
    }
    getLabelBounds() {
        return this.labelPosition && this.labelSize ? {
            x1: this.labelPosition.x - this.labelSize.width / 2,
            y1: this.labelPosition.y - this.labelSize.height / 2,
            x2: this.labelPosition.x + this.labelSize.width / 2,
            y2: this.labelPosition.y + this.labelSize.height / 2
        } : {
            x1: 0,
            x2: 0,
            y1: 0,
            y2: 0
        };
    }
}

export class ArcLabel extends LabelBase {
    constructor(attributes, options) {
        const {data: data} = attributes, restAttributes = __rest(attributes, [ "data" ]);
        super((null == options ? void 0 : options.skipDefault) ? attributes : Object.assign({
            data: data
        }, merge({}, ArcLabel.defaultAttributes, restAttributes))), this.name = "arc-label", 
        this._ellipsisWidth = 0, this._arcLeft = new Map, this._arcRight = new Map, this._line2MinLength = 0, 
        this._alignOffset = 0;
    }
    _overlapping(labels) {
        return [ "inside", "inside-center" ].includes(this.attribute.position) ? super._overlapping(labels) : labels;
    }
    labeling(textBounds, graphicBounds, position = "outside", offset = 0) {
        if (textBounds && graphicBounds) return {
            x: 0,
            y: 0
        };
    }
    _layout(texts) {
        var _a, _b, _c;
        if (!texts || !texts.length) return [];
        const labels = super._layout(texts), textBoundsArray = labels.map((label => this.getGraphicBounds(label))), ellipsisLabelAttribute = Object.assign(Object.assign({}, this.attribute.textStyle), {
            text: "…"
        });
        let ellipsisWidth = 1 / 0;
        if (!1 !== ellipsisLabelAttribute.ellipsis) {
            const ellipsisText = this._createLabelText(ellipsisLabelAttribute), ellipsisTextBounds = this.getGraphicBounds(ellipsisText);
            ellipsisWidth = ellipsisTextBounds.x2 - ellipsisTextBounds.x1;
        }
        const data = labels.map((label => label.attribute)), currentMarks = Array.from(this._idToGraphic.values());
        this._line2MinLength = isFunction(this.attribute.line.line2MinLength) ? this.attribute.line.line2MinLength(texts, currentMarks, this.attribute) : this.attribute.line.line2MinLength, 
        this._alignOffset = null !== (_a = isFunction(this.attribute.layout.alignOffset) ? this.attribute.layout.alignOffset(texts, currentMarks, this.attribute) : this.attribute.layout.alignOffset) && void 0 !== _a ? _a : 0;
        const arcs = this.layoutArcLabels(this.attribute.position, this.attribute, currentMarks, data, textBoundsArray, ellipsisWidth);
        for (let i = 0; i < data.length; i++) {
            const textData = data[i], basedArc = arcs.find((arc => {
                var _a;
                return (null === (_a = arc.refDatum) || void 0 === _a ? void 0 : _a.id) === textData.id;
            }));
            if (basedArc) {
                const labelAttribute = {
                    visible: basedArc.labelVisible,
                    x: basedArc.labelPosition.x,
                    y: basedArc.labelPosition.y,
                    angle: basedArc.angle,
                    points: basedArc.pointA && basedArc.pointB && basedArc.pointC ? [ basedArc.pointA, basedArc.pointB, basedArc.pointC ] : void 0,
                    line: basedArc.labelLine
                };
                "richtext" === labels[i].type ? labelAttribute.width = null !== (_b = basedArc.labelLimit) && void 0 !== _b ? _b : labels[i].attribute.width : labelAttribute.maxLineWidth = null !== (_c = basedArc.labelLimit) && void 0 !== _c ? _c : labels[i].attribute.maxLineWidth, 
                basedArc.refArc && "arc3d" === basedArc.refArc.type && (labelAttribute.anchor3d = [ basedArc.circleCenter.x - labelAttribute.x, basedArc.circleCenter.y - labelAttribute.y ], 
                labelAttribute.beta = basedArc.refArc.attribute.beta), labels[i].setAttributes(labelAttribute);
            }
        }
        return labels;
    }
    layoutArcLabels(position, attribute, currentMarks, data, textBoundsArray, ellipsisWidth) {
        this._arcLeft.clear(), this._arcRight.clear(), this._ellipsisWidth = ellipsisWidth;
        let maxRadius = 0;
        currentMarks.forEach((currentMark => {
            const graphicAttribute = this.getGraphicFinalLayoutAttributes(currentMark);
            graphicAttribute.outerRadius > maxRadius && (maxRadius = graphicAttribute.outerRadius);
        })), data.forEach(((d, index) => {
            var _a, _b;
            const currentMark = this._idToGraphic.get(d.id), graphicAttribute = this.getGraphicFinalLayoutAttributes(currentMark), center = {
                x: null !== (_a = null == graphicAttribute ? void 0 : graphicAttribute.x) && void 0 !== _a ? _a : 0,
                y: null !== (_b = null == graphicAttribute ? void 0 : graphicAttribute.y) && void 0 !== _b ? _b : 0
            };
            if (!isNil(data[index]) && !isNil(textBoundsArray[index])) {
                const item = data[index] ? data[index] : null, textBounds = textBoundsArray[index] ? textBoundsArray[index] : {
                    x1: 0,
                    x2: 0,
                    y1: 0,
                    y2: 0
                }, arcMiddleAngle = (graphicAttribute.startAngle + graphicAttribute.endAngle) / 2, intervalAngle = graphicAttribute.endAngle - graphicAttribute.startAngle, arcQuadrant = computeQuadrant(graphicAttribute.endAngle - intervalAngle / 2), arcMiddle = polarToCartesian(center, graphicAttribute.outerRadius, arcMiddleAngle), outerArcMiddle = polarToCartesian(center, maxRadius + attribute.line.line1MinLength, arcMiddleAngle), arc = new ArcInfo(item, arcMiddle, outerArcMiddle, arcQuadrant, intervalAngle, arcMiddleAngle, graphicAttribute.innerRadius, graphicAttribute.outerRadius, center);
                arc.refArc = currentMark, arc.pointA = polarToCartesian(center, this.computeDatumRadius(2 * center.x, 2 * center.y, graphicAttribute.outerRadius), arc.middleAngle), 
                arc.labelSize = {
                    width: textBounds.x2 - textBounds.x1,
                    height: textBounds.y2 - textBounds.y1
                }, isQuadrantRight(arc.quadrant) ? this._arcRight.set(arc.refDatum, arc) : isQuadrantLeft(arc.quadrant) && this._arcLeft.set(arc.refDatum, arc);
            }
        }));
        const leftArcs = Array.from(this._arcLeft.values()), rightArcs = Array.from(this._arcRight.values()), arcs = [];
        switch (position) {
          case "inside":
          case "inside-inner":
          case "inside-outer":
          case "inside-center":
            arcs.push(...this._layoutInsideLabels(rightArcs, attribute, currentMarks)), arcs.push(...this._layoutInsideLabels(leftArcs, attribute, currentMarks));
            break;

          default:
            arcs.push(...this._layoutOutsideLabels(rightArcs, attribute, currentMarks)), arcs.push(...this._layoutOutsideLabels(leftArcs, attribute, currentMarks));
        }
        return arcs;
    }
    _layoutInsideLabels(arcs, attribute, currentMarks) {
        var _a, _b;
        const labelConfig = attribute, spaceWidth = labelConfig.spaceWidth, position = null !== (_a = labelConfig.position) && void 0 !== _a ? _a : "inside", offsetRadius = null !== (_b = labelConfig.offsetRadius) && void 0 !== _b ? _b : -spaceWidth;
        return arcs.forEach((arc => {
            var _a, _b, _c;
            const {labelSize: labelSize, radian: radian} = arc, innerRadius = arc.innerRadius, outerRadius = arc.outerRadius;
            let limit;
            if (radian < connectLineRadian(outerRadius, labelSize.height)) limit = 0; else {
                let minRadius;
                minRadius = radian >= Math.PI ? innerRadius : Math.max(innerRadius, labelSize.height / 2 / Math.tan(radian / 2)), 
                limit = outerRadius - minRadius - spaceWidth;
            }
            !0 !== labelConfig.rotate && (limit = outerRadius - spaceWidth);
            const text = this._getFormatLabelText(arc.refDatum, limit);
            arc.labelText = text;
            const labelWidth = Math.min(limit, arc.labelSize.width), align = this._computeAlign(arc, attribute);
            let labelRadius, alignOffset = 0;
            if ("inside" === position && (alignOffset = "left" === align ? labelWidth : "right" === align ? 0 : labelWidth / 2), 
            labelRadius = "inside-inner" === position ? innerRadius - offsetRadius + alignOffset : "inside-center" === position ? innerRadius + (outerRadius - innerRadius) / 2 : outerRadius + offsetRadius - alignOffset, 
            arc.labelPosition = polarToCartesian(arc.circleCenter, labelRadius, arc.middleAngle), 
            arc.labelLimit = labelWidth, isGreater(labelWidth, 0) || (arc.labelVisible = !1), 
            !1 !== labelConfig.rotate) {
                arc.angle = null !== (_b = null === (_a = attribute.textStyle) || void 0 === _a ? void 0 : _a.angle) && void 0 !== _b ? _b : arc.middleAngle;
                let offsetAngle = null !== (_c = labelConfig.offsetAngle) && void 0 !== _c ? _c : 0;
                [ "inside-inner", "inside-outer" ].includes(position) && (offsetAngle += Math.PI / 2), 
                arc.angle += offsetAngle;
            }
        })), arcs;
    }
    _layoutOutsideLabels(arcs, attribute, currentMarks) {
        var _a, _b, _c;
        const center_x = null !== (_a = currentMarks[0].attribute.x) && void 0 !== _a ? _a : 0, height = 2 * (null !== (_b = currentMarks[0].attribute.y) && void 0 !== _b ? _b : 0), labelLayout = attribute.layout, spaceWidth = attribute.spaceWidth;
        if (arcs.forEach((arc => {
            const direction = isQuadrantLeft(arc.quadrant) ? -1 : 1;
            arc.labelPosition = {
                x: arc.outerCenter.x + direction * (arc.labelSize.width / 2 + this._line2MinLength + spaceWidth),
                y: arc.outerCenter.y
            };
        })), arcs.sort(((a, b) => a.labelPosition.y - b.labelPosition.y)), !1 !== attribute.coverEnable || "none" === labelLayout.strategy) {
            for (const arc of arcs) {
                const {labelPosition: labelPosition, labelSize: labelSize} = arc;
                arc.labelLimit = labelSize.width, arc.pointB = isQuadrantLeft(arc.quadrant) ? {
                    x: labelPosition.x + labelSize.width / 2 + this._line2MinLength + spaceWidth,
                    y: labelPosition.y
                } : {
                    x: labelPosition.x - labelSize.width / 2 - this._line2MinLength - spaceWidth,
                    y: labelPosition.y
                }, this._computeX(arc, attribute, currentMarks);
            }
            !1 === attribute.coverEnable && "none" === labelLayout.strategy && this._coverLabels(arcs);
        } else {
            const maxLabels = height / ((null === (_c = attribute.textStyle) || void 0 === _c ? void 0 : _c.fontSize) || 16);
            this._adjustY(arcs, maxLabels, attribute, currentMarks);
            const {minY: minY, maxY: maxY} = arcs.reduce(((yInfo, arc) => {
                const {y1: y1, y2: y2} = arc.getLabelBounds();
                return yInfo.minY = Math.max(0, Math.min(y1, yInfo.minY)), yInfo.maxY = Math.min(height, Math.max(y2, yInfo.maxY)), 
                yInfo;
            }), {
                minY: 1 / 0,
                maxY: -1 / 0
            }), halfY = Math.max(Math.abs(height / 2 - minY), Math.abs(maxY - height / 2)), r = this._computeLayoutRadius(halfY, attribute, currentMarks);
            for (const arc of arcs) this._computePointB(arc, r, attribute, currentMarks), this._computeX(arc, attribute, currentMarks);
        }
        const width = 2 * center_x;
        return arcs.forEach((arc => {
            var _a, _b;
            arc.labelVisible && (isLess(arc.pointB.x, this._line2MinLength + spaceWidth) || isGreater(arc.pointB.x, width - this._line2MinLength - spaceWidth)) && (arc.labelVisible = !1), 
            arc.angle = null !== (_b = null === (_a = attribute.textStyle) || void 0 === _a ? void 0 : _a.angle) && void 0 !== _b ? _b : 0, 
            attribute.offsetAngle && (arc.angle += attribute.offsetAngle), arc.labelLine = Object.assign(Object.assign({}, attribute.line), {
                visible: arc.labelVisible
            });
        })), arcs;
    }
    _computeX(arc, attribute, currentMarks) {
        var _a;
        const center = arc.circleCenter, plotLayout_x1 = 0, plotLayout_x2 = this.attribute.width;
        this.attribute.height;
        let maxRadius = 0;
        currentMarks.forEach((currentMark => {
            const graphicAttribute = this.getGraphicFinalLayoutAttributes(currentMark);
            graphicAttribute.outerRadius > maxRadius && (maxRadius = graphicAttribute.outerRadius);
        }));
        const radiusRatio = this.computeLayoutOuterRadius(maxRadius, attribute.width, attribute.height), line1MinLength = attribute.line.line1MinLength, labelLayoutAlign = null === (_a = attribute.layout) || void 0 === _a ? void 0 : _a.align, spaceWidth = attribute.spaceWidth, {labelPosition: labelPosition, quadrant: quadrant, pointB: pointB} = arc;
        isValidNumber(pointB.x * pointB.y) || (arc.pointC = {
            x: NaN,
            y: NaN
        }, labelPosition.x = NaN, arc.labelLimit = 0);
        const radius = this.computeRadius(radiusRatio, attribute.width, attribute.height), flag = isQuadrantLeft(quadrant) ? -1 : 1;
        let cx = 0, limit = (flag > 0 ? plotLayout_x2 - pointB.x : pointB.x - plotLayout_x1) + this._alignOffset - this._line2MinLength - spaceWidth;
        "labelLine" === labelLayoutAlign && (cx = (radius + line1MinLength + this._line2MinLength) * flag + center.x, 
        limit = (flag > 0 ? plotLayout_x2 - cx : cx - plotLayout_x1) - spaceWidth);
        const text = this._getFormatLabelText(arc.refDatum, limit);
        arc.labelText = text;
        let labelWidth = Math.min(limit, arc.labelSize.width);
        switch (labelLayoutAlign) {
          case "labelLine":
            break;

          case "edge":
            cx = flag > 0 ? plotLayout_x2 - labelWidth - spaceWidth : plotLayout_x1 + labelWidth + spaceWidth;
            break;

          default:
            cx = pointB.x + flag * this._line2MinLength;
        }
        labelWidth = Math.max(this._ellipsisWidth, labelWidth);
        const needAdjustLimit = labelWidth < arc.labelSize.width - 1;
        arc.labelLimit = needAdjustLimit ? labelWidth : null, arc.pointC = {
            x: cx,
            y: labelPosition.y
        };
        const align = this._computeAlign(arc, attribute), targetCenterOffset = getAlignOffset(align) * (needAdjustLimit ? labelWidth : arc.labelSize.width);
        "edge" === labelLayoutAlign ? (labelPosition.x = (flag > 0 ? plotLayout_x2 : plotLayout_x1) - flag * targetCenterOffset + flag * this._alignOffset, 
        arc.pointC.x += flag * this._alignOffset) : labelPosition.x = cx + flag * (this._alignOffset + spaceWidth + targetCenterOffset);
    }
    _computeAlign(arc, attribute) {
        var _a, _b, _c, _d, _e, _f;
        const labelConfig = attribute, textAlign = null !== (_b = null === (_a = labelConfig.textStyle) || void 0 === _a ? void 0 : _a.textAlign) && void 0 !== _b ? _b : null === (_c = labelConfig.textStyle) || void 0 === _c ? void 0 : _c.align, layoutAlign = null !== (_e = null === (_d = labelConfig.layout) || void 0 === _d ? void 0 : _d.textAlign) && void 0 !== _e ? _e : null === (_f = labelConfig.layout) || void 0 === _f ? void 0 : _f.align;
        return "inside" !== labelConfig.position ? isNil(textAlign) || "auto" === textAlign ? "edge" === layoutAlign ? isQuadrantLeft(arc.quadrant) ? "left" : "right" : isQuadrantLeft(arc.quadrant) ? "right" : "left" : textAlign : isNil(textAlign) || "auto" === textAlign ? "center" : textAlign;
    }
    _getFormatLabelText(value, limit) {
        var _a;
        return null !== (_a = null == value ? void 0 : value.text) && void 0 !== _a ? _a : "";
    }
    _adjustY(arcs, maxLabels, attribute, currentMarks) {
        var _a, _b;
        _a = currentMarks[0].attribute.x;
        const plotRect_height = 2 * (null !== (_b = currentMarks[0].attribute.y) && void 0 !== _b ? _b : 0), labelLayout = attribute.layout;
        if ("vertical" === labelLayout.strategy) {
            let delta, lastY = 0;
            const len = arcs.length;
            if (len <= 0) return;
            for (let i = 0; i < len; i++) {
                const {y1: y1} = arcs[i].getLabelBounds();
                if (delta = y1 - lastY, isLess(delta, 0)) {
                    const index = this._shiftY(arcs, i, len - 1, -delta);
                    this._shiftY(arcs, index, 0, delta / 2);
                }
                const {y2: y2} = arcs[i].getLabelBounds();
                lastY = y2;
            }
            const {y1: firstY1} = arcs[0].getLabelBounds();
            delta = firstY1 - 0, isLess(delta, 0) && this._shiftY(arcs, 0, len - 1, -delta);
            for (let i = arcs.length - 1; i >= 0 && arcs[i].getLabelBounds().y2 > plotRect_height; i--) arcs[i].labelVisible = !1;
        } else if ("none" !== labelLayout.strategy) {
            const priorityArcs = arcs.map(((arc, i) => ({
                arc: arc,
                originIndex: i,
                priorityIndex: 0
            })));
            priorityArcs.sort(((a, b) => b.arc.radian - a.arc.radian)), priorityArcs.forEach(((priorityArc, i) => {
                priorityArc.priorityIndex = i, priorityArc.arc.labelVisible = !1;
            }));
            let topLabelIndex = 1 / 0, bottomLabelIndex = -1 / 0;
            for (let i = 0; i < maxLabels && i < arcs.length; i++) {
                this._storeY(arcs);
                const arc = priorityArcs[i].arc;
                this._computeYRange(arc, attribute, currentMarks), arc.labelVisible = !0;
                const curY = arc.labelPosition.y, {lastIndex: lastIndex, nextIndex: nextIndex} = this._findNeighborIndex(arcs, priorityArcs[i]), lastArc = arcs[lastIndex], nextArc = arcs[nextIndex];
                if (-1 === lastIndex && -1 !== nextIndex) {
                    const nextY = nextArc.labelPosition.y;
                    curY > nextY ? arc.labelPosition.y = nextY - nextArc.labelSize.height / 2 - arc.labelSize.height / 2 : this._twoWayShift(arcs, arc, nextArc, nextIndex);
                } else if (-1 !== lastIndex && -1 === nextIndex) {
                    const lastY = lastArc.labelPosition.y;
                    curY < lastY ? arc.labelPosition.y = lastY + lastArc.labelSize.height / 2 + arc.labelSize.height / 2 : this._twoWayShift(arcs, lastArc, arc, priorityArcs[i].originIndex);
                } else if (-1 !== lastIndex && -1 !== nextIndex) {
                    const lastY = lastArc.labelPosition.y, nextY = nextArc.labelPosition.y;
                    curY > nextY ? (arc.labelPosition.y = nextY - nextArc.labelSize.height / 2 - arc.labelSize.height / 2, 
                    this._twoWayShift(arcs, lastArc, arc, priorityArcs[i].originIndex)) : curY < lastY ? (arc.labelPosition.y = lastY + lastArc.labelSize.height / 2 + arc.labelSize.height / 2, 
                    this._twoWayShift(arcs, arc, nextArc, nextIndex)) : (this._twoWayShift(arcs, lastArc, arc, priorityArcs[i].originIndex), 
                    this._twoWayShift(arcs, arc, nextArc, nextIndex));
                }
                const nextTopIndex = Math.min(topLabelIndex, priorityArcs[i].originIndex), nextBottomIndex = Math.max(bottomLabelIndex, priorityArcs[i].originIndex);
                let delta;
                if (delta = arcs[nextBottomIndex].getLabelBounds().y2 - plotRect_height, isGreater(delta, 0) && this._shiftY(arcs, nextBottomIndex, 0, -delta), 
                delta = arcs[nextTopIndex].getLabelBounds().y1 - 0, isLess(delta, 0) && this._shiftY(arcs, nextTopIndex, arcs.length - 1, -delta), 
                delta = arcs[nextBottomIndex].getLabelBounds().y2 - plotRect_height, isGreater(delta, 0)) {
                    arc.labelVisible = !1, this._restoreY(arcs);
                    break;
                }
                labelLayout.tangentConstraint && !this._checkYRange(arcs) ? (arc.labelVisible = !1, 
                this._restoreY(arcs)) : (topLabelIndex = nextTopIndex, bottomLabelIndex = nextBottomIndex);
            }
        }
    }
    _shiftY(arcs, start, end, delta) {
        const direction = start < end ? 1 : -1;
        let index = start;
        for (;-1 !== index; ) {
            arcs[index].labelPosition.y += delta;
            const nextIndex = this._findNextVisibleIndex(arcs, index, end, direction);
            if (nextIndex >= 0 && nextIndex < arcs.length) {
                const {y1: curY1, y2: curY2} = arcs[index].getLabelBounds(), {y1: nextY1, y2: nextY2} = arcs[nextIndex].getLabelBounds();
                if (direction > 0 && curY2 < nextY1 || direction < 0 && curY1 > nextY2) return index;
            }
            index = nextIndex;
        }
        return end;
    }
    _findNextVisibleIndex(arcs, start, end, direction) {
        const diff = (end - start) * direction;
        for (let i = 1; i <= diff; i++) {
            const index = start + i * direction;
            if (arcs[index].labelVisible) return index;
        }
        return -1;
    }
    _computePointB(arc, r, attribute, currentMarks) {
        const labelConfig = attribute;
        let maxRadius = 0;
        currentMarks.forEach((currentMark => {
            const graphicAttribute = this.getGraphicFinalLayoutAttributes(currentMark);
            graphicAttribute.outerRadius > maxRadius && (maxRadius = graphicAttribute.outerRadius);
        }));
        const radiusRatio = this.computeLayoutOuterRadius(maxRadius, attribute.width, attribute.height), line1MinLength = labelConfig.line.line1MinLength;
        if ("none" === labelConfig.layout.strategy) arc.pointB = {
            x: arc.outerCenter.x,
            y: arc.outerCenter.y
        }; else {
            const center = arc.circleCenter, radius = this.computeRadius(radiusRatio, attribute.width, attribute.height), {labelPosition: labelPosition, quadrant: quadrant} = arc, rd = r - Math.max(radius + line1MinLength, arc.outerRadius), x = Math.sqrt(r ** 2 - Math.abs(center.y - labelPosition.y) ** 2) - rd;
            isValidNumber(x) ? arc.pointB = {
                x: center.x + x * (isQuadrantLeft(quadrant) ? -1 : 1),
                y: labelPosition.y
            } : arc.pointB = {
                x: NaN,
                y: NaN
            };
        }
    }
    _storeY(arcs) {
        for (const arc of arcs) arc.labelVisible && (arc.lastLabelY = arc.labelPosition.y);
    }
    _computeYRange(arc, attribute, currentMarks) {
        const center = arc.circleCenter, plotRect = {
            width: 2 * center.x,
            height: 2 * center.y
        };
        let maxRadius = 0;
        currentMarks.forEach((currentMark => {
            const graphicAttribute = this.getGraphicFinalLayoutAttributes(currentMark);
            graphicAttribute.outerRadius > maxRadius && (maxRadius = graphicAttribute.outerRadius);
        }));
        const radiusRatio = this.computeLayoutOuterRadius(maxRadius, attribute.width, attribute.height), line1MinLength = attribute.line.line1MinLength, {width: width, height: height} = plotRect, radius = this.computeRadius(radiusRatio, attribute.width, attribute.height), r = this._computeLayoutRadius(height / 2, attribute, currentMarks), cx = Math.abs(arc.center.x - width / 2), cy = arc.center.y - height / 2;
        let a, b, c;
        if (isClose(width / 2, cx)) a = 0, b = 1, c = -cy; else if (isClose(height / 2, cy)) a = 1, 
        b = 0, c = -cx; else {
            const k = -1 / (cy / cx);
            a = k, b = -1, c = cy - k * cx;
        }
        const points = lineCirclePoints(a, b, c, line1MinLength + radius - r, 0, r);
        if (points.length < 2) return;
        let min, max;
        points[0].x > points[1].x && points.reverse(), points[0].x < 0 ? isClose(points[0].y, points[1].y) ? isGreater(arc.middleAngle, -Math.PI) && isLess(arc.middleAngle, 0) || isGreater(arc.middleAngle, Math.PI) && isLess(arc.middleAngle, 2 * Math.PI) ? (min = 0, 
        max = points[1].y + height / 2) : (min = points[1].y + height / 2, max = height) : points[0].y < points[1].y ? (min = 0, 
        max = points[1].y + height / 2) : (min = points[1].y + height / 2, max = plotRect.height) : (min = Math.min(points[0].y, points[1].y) + height / 2, 
        max = Math.max(points[0].y, points[1].y) + height / 2), arc.labelYRange = [ min, max ];
    }
    _computeLayoutRadius(halfYLength, attribute, currentMarks) {
        const labelConfig = attribute, layoutArcGap = labelConfig.layoutArcGap, line1MinLength = labelConfig.line.line1MinLength;
        let maxRadius = 0;
        currentMarks.forEach((currentMark => {
            const graphicAttribute = this.getGraphicFinalLayoutAttributes(currentMark);
            graphicAttribute.outerRadius > maxRadius && (maxRadius = graphicAttribute.outerRadius);
        }));
        const radiusRatio = this.computeLayoutOuterRadius(maxRadius, attribute.width, attribute.height), outerR = this.computeRadius(radiusRatio, attribute.width, attribute.height) + line1MinLength, a = outerR - layoutArcGap;
        return Math.max((a ** 2 + halfYLength ** 2) / (2 * a), outerR);
    }
    _findNeighborIndex(arcs, priorityArc) {
        const index = priorityArc.originIndex;
        let lastIndex = -1, nextIndex = -1;
        for (let i = index - 1; i >= 0; i--) if (arcs[i].labelVisible) {
            lastIndex = i;
            break;
        }
        for (let i = index + 1; i < arcs.length; i++) if (arcs[i].labelVisible) {
            nextIndex = i;
            break;
        }
        return {
            lastIndex: lastIndex,
            nextIndex: nextIndex
        };
    }
    _twoWayShift(arcs, lastArc, nextArc, nextIndex) {
        const delta = nextArc.getLabelBounds().y1 - lastArc.getLabelBounds().y2;
        if (isLess(delta, 0)) {
            const i = this._shiftY(arcs, nextIndex, arcs.length - 1, -delta);
            this._shiftY(arcs, i, 0, delta / 2);
        }
    }
    _restoreY(arcs) {
        for (const arc of arcs) arc.labelVisible && (arc.labelPosition.y = arc.lastLabelY);
    }
    _checkYRange(arcs) {
        for (const arc of arcs) {
            const {labelYRange: labelYRange, labelPosition: labelPosition} = arc;
            if (arc.labelVisible && labelYRange && (isLess(labelPosition.y, labelYRange[0]) || isGreater(labelPosition.y, labelYRange[1]))) return !1;
        }
        return !0;
    }
    _coverLabels(arcs) {
        if (arcs.length <= 1) return;
        let lastBounds = arcs[0].getLabelBounds();
        for (let i = 1; i < arcs.length; i++) {
            const bounds = arcs[i].getLabelBounds();
            checkBoundsOverlap(lastBounds, bounds) ? arcs[i].labelVisible = !1 : lastBounds = bounds;
        }
    }
    _getLabelLinePoints(text, baseMark) {
        return text.attribute.points;
    }
    _createLabelLine(text, baseMark) {
        var _a, _b, _c, _d, _e;
        const {line: line = {}, visible: visible} = text.attribute, lineGraphic = super._createLabelLine(text, baseMark);
        if (lineGraphic && (lineGraphic.setAttributes({
            visible: null === (_c = null !== (_a = line.visible && visible) && void 0 !== _a ? _a : null === (_b = text.attribute) || void 0 === _b ? void 0 : _b.visible) || void 0 === _c || _c,
            lineWidth: null !== (_e = null === (_d = line.style) || void 0 === _d ? void 0 : _d.lineWidth) && void 0 !== _e ? _e : 1
        }), line.smooth && lineGraphic.setAttributes({
            curveType: "basis"
        }), "arc3d" === baseMark.type && baseMark)) {
            const {beta: beta, x: x, y: y} = this.getGraphicFinalLayoutAttributes(baseMark);
            lineGraphic.setAttributes({
                beta: beta,
                anchor3d: [ x, y ]
            });
        }
        return lineGraphic;
    }
    computeRadius(r, width, height, k) {
        return this.computeLayoutRadius(width || 0, height || 0) * r * (isNil(k) ? 1 : k);
    }
    computeLayoutRadius(width, height) {
        return Math.min(width / 2, height / 2);
    }
    _canPlaceInside(textBound, shapeBound) {
        return "inside" === this.attribute.position || "inside-center" === this.attribute.position;
    }
    computeLayoutOuterRadius(r, width, height) {
        return r / (Math.min(width, height) / 2);
    }
    computeDatumRadius(width, height, outerRadius) {
        const outerRadiusRatio = this.computeLayoutOuterRadius(outerRadius, width, height);
        return this.computeLayoutRadius(width || 0, height || 0) * outerRadiusRatio;
    }
}

ArcLabel.defaultAttributes = {
    coverEnable: !1,
    spaceWidth: 5,
    layoutArcGap: 6,
    textStyle: {
        visible: !0,
        fontSize: 14,
        fontWeight: "normal",
        fillOpacity: 1,
        boundsPadding: [ -1, 0, -1, 0 ],
        ellipsis: !0
    },
    position: "outside",
    line: {
        visible: !0,
        line1MinLength: 20,
        line2MinLength: 10
    },
    layout: {
        align: "arc",
        strategy: "priority",
        tangentConstraint: !0
    }
};

export const registerArcDataLabel = () => {
    registerLabelComponent("arc", ArcLabel);
};
//# sourceMappingURL=arc.js.map