/**
 * DevExtreme (cjs/viz/series/pie_series.js)
 * Version: 23.2.6 (build 24140-0112)
 * Build date: Sun May 19 2024
 *
 * Copyright (c) 2012 - 2024 Developer Express Inc. ALL RIGHTS RESERVED
 * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
 */
"use strict";
exports.pie = exports.doughnut = exports.donut = void 0;
var _common = require("../../core/utils/common");
var _iterator = require("../../core/utils/iterator");
var _scatter_series = require("./scatter_series");
var _utils = require("../core/utils");
var _extend2 = require("../../core/utils/extend");
var _bar_series = require("./bar_series");
const chartScatterSeries = _scatter_series.chart;
const barSeries = _bar_series.chart.bar;
const _extend = _extend2.extend;
const _each = _iterator.each;
const _noop = _common.noop;
const _map = _utils.map;
const _isFinite = isFinite;
const _max = Math.max;
const ANIMATION_DURATION = .7;
const INSIDE = "inside";
const pie = _extend({}, barSeries, {
    _setGroupsSettings: function() {
        chartScatterSeries._setGroupsSettings.apply(this, arguments);
        this._labelsGroup.attr({
            "pointer-events": null
        })
    },
    _createErrorBarGroup: _noop,
    _drawPoint: function(options) {
        const point = options.point;
        const legendCallback = this._legendCallback;
        chartScatterSeries._drawPoint.call(this, options);
        !point.isVisible() && point.setInvisibility();
        point.isSelected() && legendCallback()
    },
    _getOldPoint: function(data, oldPointsByArgument, index) {
        const point = (this._points || [])[index];
        if (point) {
            oldPointsByArgument[point.argument.valueOf()] = oldPointsByArgument[point.argument.valueOf()].filter(p => p !== point)
        }
        return point
    },
    adjustLabels: function(moveLabelsFromCenter) {
        return (this._points || []).reduce((r, p) => {
            if (p._label.isVisible()) {
                p.setLabelTrackerData();
                r = p.applyWordWrap(moveLabelsFromCenter) || r;
                p.updateLabelCoord(moveLabelsFromCenter);
                return r
            }
        }, false)
    },
    _applyElementsClipRect: _noop,
    getColor: _noop,
    areErrorBarsVisible: _noop,
    drawLabelsWOPoints: function() {
        if (this._options.label.position === INSIDE) {
            return false
        }
        this._labelsGroup.append(this._extGroups.labelsGroup);
        (this._points || []).forEach((function(point) {
            point.drawLabel()
        }));
        return true
    },
    getPointsCount: function() {
        return this._data.filter(d => this._checkData(d)).length
    },
    setMaxPointsCount: function(count) {
        this._pointsCount = count
    },
    _getCreatingPointOptions: function(data, dataIndex) {
        return this._getPointOptions(data, dataIndex)
    },
    _updateOptions: function(options) {
        this.labelSpace = 0;
        this.innerRadius = "pie" === this.type ? 0 : options.innerRadius
    },
    _checkData: function(data, skippedFields) {
        const base = barSeries._checkData.call(this, data, skippedFields, {
            value: this.getValueFields()[0]
        });
        return this._options.paintNullPoints ? base : base && null !== data.value
    },
    _createGroups: chartScatterSeries._createGroups,
    _setMarkerGroupSettings: function() {
        this._markersGroup.attr({
            class: "dxc-markers"
        })
    },
    _getMainColor(data, point) {
        const pointsByArg = this.getPointsByArg(data.argument);
        const argumentIndex = point ? pointsByArg.indexOf(point) : pointsByArg.length;
        return this._options.mainSeriesColor(data.argument, argumentIndex, this._pointsCount)
    },
    _getPointOptions: function(data) {
        return this._parsePointOptions(this._preparePointOptions(), this._options.label, data)
    },
    _getRangeData: function() {
        return this._rangeData
    },
    _createPointStyles: function(pointOptions, data, point) {
        var _pointOptions$color;
        const that = this;
        const mainColor = (0, _utils.extractColor)(pointOptions.color, true) || that._getMainColor(data, point);
        const colorId = null === (_pointOptions$color = pointOptions.color) || void 0 === _pointOptions$color ? void 0 : _pointOptions$color.fillId;
        const hoverStyle = pointOptions.hoverStyle || {};
        const selectionStyle = pointOptions.selectionStyle || {};
        if (colorId) {
            that._turnOffHatching(hoverStyle, selectionStyle)
        }
        return {
            labelColor: mainColor,
            normal: that._parsePointStyle(pointOptions, mainColor, mainColor),
            hover: that._parsePointStyle(hoverStyle, colorId || mainColor, mainColor),
            selection: that._parsePointStyle(selectionStyle, colorId || mainColor, mainColor),
            legendStyles: {
                normal: that._createLegendState(pointOptions, mainColor),
                hover: that._createLegendState(hoverStyle, colorId || mainColor),
                selection: that._createLegendState(selectionStyle, colorId || mainColor)
            }
        }
    },
    _getArrangeMinShownValue: function(points, total) {
        const minSegmentSize = this._options.minSegmentSize;
        let totalMinSegmentSize = 0;
        let totalNotMinValues = 0;
        total = total || points.length;
        _each(points, (function(_, point) {
            if (point.isVisible()) {
                if (point.normalInitialValue < minSegmentSize * total / 360) {
                    totalMinSegmentSize += minSegmentSize
                } else {
                    totalNotMinValues += point.normalInitialValue
                }
            }
        }));
        return totalMinSegmentSize < 360 ? minSegmentSize * totalNotMinValues / (360 - totalMinSegmentSize) : 0
    },
    _applyArrangeCorrection: function(points, minShownValue, total) {
        const options = this._options;
        const isClockWise = "anticlockwise" !== options.segmentsDirection;
        const shiftedAngle = _isFinite(options.startAngle) ? (0, _utils.normalizeAngle)(options.startAngle) : 0;
        const minSegmentSize = options.minSegmentSize;
        let percent;
        let correction = 0;
        let zeroTotalCorrection = 0;
        if (0 === total) {
            total = points.filter((function(el) {
                return el.isVisible()
            })).length;
            zeroTotalCorrection = 1
        }
        _each(isClockWise ? points : points.concat([]).reverse(), (function(_, point) {
            const val = point.isVisible() ? zeroTotalCorrection || point.normalInitialValue : 0;
            let updatedZeroValue;
            if (minSegmentSize && point.isVisible() && val < minShownValue) {
                updatedZeroValue = minShownValue
            }
            percent = val / total;
            point.correctValue(correction, percent, zeroTotalCorrection + (updatedZeroValue || 0));
            point.shiftedAngle = shiftedAngle;
            correction += updatedZeroValue || val
        }));
        this._rangeData = {
            val: {
                min: 0,
                max: correction
            }
        }
    },
    _removePoint: function(point) {
        const points = this.getPointsByArg(point.argument);
        points.splice(points.indexOf(point), 1);
        point.dispose()
    },
    arrangePoints: function() {
        const that = this;
        const originalPoints = that._points || [];
        const minSegmentSize = that._options.minSegmentSize;
        let minShownValue;
        let isAllPointsNegative = true;
        let i = 0;
        const len = originalPoints.length;
        while (i < len && isAllPointsNegative) {
            isAllPointsNegative = originalPoints[i].value <= 0;
            i++
        }
        const points = that._points = _map(originalPoints, (function(point) {
            if (null === point.value || !isAllPointsNegative && point.value < 0) {
                that._removePoint(point);
                return null
            } else {
                return point
            }
        }));
        const maxValue = points.reduce((function(max, p) {
            return _max(max, Math.abs(p.initialValue))
        }), 0);
        points.forEach((function(p) {
            p.normalInitialValue = p.initialValue / (0 !== maxValue ? maxValue : 1)
        }));
        const total = points.reduce((function(total, point) {
            return total + (point.isVisible() ? point.normalInitialValue : 0)
        }), 0);
        if (minSegmentSize) {
            minShownValue = this._getArrangeMinShownValue(points, total)
        }
        that._applyArrangeCorrection(points, minShownValue, total)
    },
    correctPosition: function(correction, canvas) {
        _each(this._points, (function(_, point) {
            point.correctPosition(correction)
        }));
        this.setVisibleArea(canvas)
    },
    correctRadius: function(correction) {
        this._points.forEach((function(point) {
            point.correctRadius(correction)
        }))
    },
    correctLabelRadius: function(labelRadius) {
        this._points.forEach((function(point) {
            point.correctLabelRadius(labelRadius)
        }))
    },
    setVisibleArea: function(canvas) {
        this._visibleArea = {
            minX: canvas.left,
            maxX: canvas.width - canvas.right,
            minY: canvas.top,
            maxY: canvas.height - canvas.bottom
        }
    },
    _applyVisibleArea: _noop,
    _animate: function(firstDrawing) {
        const that = this;
        const points = that._points;
        const pointsCount = points && points.length;
        const completeFunc = function() {
            that._animateComplete()
        };
        let animatePoint;
        if (firstDrawing) {
            animatePoint = function(p, i) {
                p.animate(i === pointsCount - 1 ? completeFunc : void 0, .7, (1 - .7) * i / (pointsCount - 1))
            }
        } else {
            animatePoint = function(p, i) {
                p.animate(i === pointsCount - 1 ? completeFunc : void 0)
            }
        }
        points.forEach(animatePoint)
    },
    getVisiblePoints: function() {
        return _map(this._points, (function(p) {
            return p.isVisible() ? p : null
        }))
    },
    getPointsByKeys: function(arg, argumentIndex) {
        const pointsByArg = this.getPointsByArg(arg);
        return pointsByArg[argumentIndex] && [pointsByArg[argumentIndex]] || []
    }
});
exports.pie = pie;
const doughnut = pie;
exports.doughnut = doughnut;
const donut = pie;
exports.donut = donut;
