var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
/**
 * AccumulationChart base file
 */
import { Property, ChildProperty, Complex, createElement, Browser, animationMode, extend } from '@syncfusion/ej2-base';
import { isNullOrUndefined, getValue } from '@syncfusion/ej2-base';
import { DataManager } from '@syncfusion/ej2-data';
import { Border, Font, Animation, EmptyPointSettings, Connector, Accessibility } from '../../common/model/base';
import { Rect, PathOption, measureText } from '@syncfusion/ej2-svg-base';
import { stringToNumber, appendChildElement, subtractRect } from '../../common/utils/helper';
import { seriesRender, pointRender } from '../../common/model/constants';
import { getSeriesColor } from '../../common/model/theme';
import { getElement, firstToLowerCase } from '../../common/utils/helper';
import { BaseSelection } from '../../common/user-interaction/selection';
import { LegendOptions } from '../../common/legend/legend';
/**
 * Configures the annotation settings for an accumulation chart.
 * Annotations are used to highlight or provide additional information about specific points or regions in the accumulation chart.
 */
var AccumulationAnnotationSettings = /** @class */ (function (_super) {
    __extends(AccumulationAnnotationSettings, _super);
    function AccumulationAnnotationSettings() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    __decorate([
        Property(null)
    ], AccumulationAnnotationSettings.prototype, "content", void 0);
    __decorate([
        Property('0')
    ], AccumulationAnnotationSettings.prototype, "x", void 0);
    __decorate([
        Property('0')
    ], AccumulationAnnotationSettings.prototype, "y", void 0);
    __decorate([
        Property('Pixel')
    ], AccumulationAnnotationSettings.prototype, "coordinateUnits", void 0);
    __decorate([
        Property('Chart')
    ], AccumulationAnnotationSettings.prototype, "region", void 0);
    __decorate([
        Property('Middle')
    ], AccumulationAnnotationSettings.prototype, "verticalAlignment", void 0);
    __decorate([
        Property('Center')
    ], AccumulationAnnotationSettings.prototype, "horizontalAlignment", void 0);
    __decorate([
        Property(null)
    ], AccumulationAnnotationSettings.prototype, "description", void 0);
    return AccumulationAnnotationSettings;
}(ChildProperty));
export { AccumulationAnnotationSettings };
/**
 * This class provides options to customize the appearance and behavior of data labels within a series.
 */
var AccumulationDataLabelSettings = /** @class */ (function (_super) {
    __extends(AccumulationDataLabelSettings, _super);
    function AccumulationDataLabelSettings() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    __decorate([
        Property(false)
    ], AccumulationDataLabelSettings.prototype, "visible", void 0);
    __decorate([
        Property(true)
    ], AccumulationDataLabelSettings.prototype, "showZero", void 0);
    __decorate([
        Property(null)
    ], AccumulationDataLabelSettings.prototype, "name", void 0);
    __decorate([
        Property('transparent')
    ], AccumulationDataLabelSettings.prototype, "fill", void 0);
    __decorate([
        Property('Inside')
    ], AccumulationDataLabelSettings.prototype, "position", void 0);
    __decorate([
        Property(5)
    ], AccumulationDataLabelSettings.prototype, "rx", void 0);
    __decorate([
        Property(5)
    ], AccumulationDataLabelSettings.prototype, "ry", void 0);
    __decorate([
        Property(0)
    ], AccumulationDataLabelSettings.prototype, "angle", void 0);
    __decorate([
        Property(false)
    ], AccumulationDataLabelSettings.prototype, "enableRotation", void 0);
    __decorate([
        Complex({ width: null, color: null }, Border)
    ], AccumulationDataLabelSettings.prototype, "border", void 0);
    __decorate([
        Complex({ fontFamily: null, size: null, fontStyle: null, fontWeight: null, color: null }, Font)
    ], AccumulationDataLabelSettings.prototype, "font", void 0);
    __decorate([
        Complex({}, Connector)
    ], AccumulationDataLabelSettings.prototype, "connectorStyle", void 0);
    __decorate([
        Property(null)
    ], AccumulationDataLabelSettings.prototype, "template", void 0);
    __decorate([
        Property('')
    ], AccumulationDataLabelSettings.prototype, "format", void 0);
    __decorate([
        Property(null)
    ], AccumulationDataLabelSettings.prototype, "maxWidth", void 0);
    __decorate([
        Property('Ellipsis')
    ], AccumulationDataLabelSettings.prototype, "textOverflow", void 0);
    __decorate([
        Property('Normal')
    ], AccumulationDataLabelSettings.prototype, "textWrap", void 0);
    return AccumulationDataLabelSettings;
}(ChildProperty));
export { AccumulationDataLabelSettings };
/**
 * The `PieCenter` class provides options to set the center position for the Pie series in a chart.
 */
var PieCenter = /** @class */ (function (_super) {
    __extends(PieCenter, _super);
    function PieCenter() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    __decorate([
        Property('50%')
    ], PieCenter.prototype, "x", void 0);
    __decorate([
        Property('50%')
    ], PieCenter.prototype, "y", void 0);
    return PieCenter;
}(ChildProperty));
export { PieCenter };
/**
 * The `AccPoints` class is used to define and manage the data points within a series of accumulation charts.
 *
 * @public
 */
var AccPoints = /** @class */ (function () {
    function AccPoints() {
        /** Accumulation point visibility. */
        this.visible = true;
        /** Accumulation point symbol location. */
        this.symbolLocation = null;
        /** @private */
        this.region = null;
        /** @private */
        this.labelRegion = null;
        /** @private */
        this.labelVisible = true;
        this.regions = null;
        /** @private */
        this.isExplode = false;
        /** @private */
        this.isClubbed = false;
        /** @private */
        this.isSliced = false;
        /** @private  */
        this.argsData = null;
        /** @private */
        this.isLabelUpdated = null;
        /** @private */
        this.initialLabelRegion = null;
    }
    return AccPoints;
}());
export { AccPoints };
/**
 * Configures the series in the accumulation chart.
 */
var AccumulationSeries = /** @class */ (function (_super) {
    __extends(AccumulationSeries, _super);
    function AccumulationSeries() {
        /**
         * Specifies the data source for the series. It can be an array of JSON objects, or an instance of DataManager.
         * ```html
         * <div id='Pie'></div>
         * ```
         * ```typescript
         * let dataManager: DataManager = new DataManager({
         *    url: 'https://services.syncfusion.com/js/production/api/orders'
         * });
         * let query: Query = new Query().take(5);
         * let pie: AccumulationChart = new AccumulationChart({
         * ...
         *     series: [{
         *        dataSource: dataManager,
         *        xName: 'CustomerID',
         *        yName: 'Freight',
         *        query: query
         *    }],
         * ...
         * });
         * pie.appendTo('#Pie');
         * ```
         *
         * @default ''
         */
        var _this = _super !== null && _super.apply(this, arguments) || this;
        /** @private */
        _this.points = [];
        /** @private */
        _this.clubbedPoints = [];
        /** @private */
        _this.sumOfPoints = 0;
        /** @private */
        _this.isRectSeries = true;
        /** @private */
        _this.clipRect = new Rect(0, 0, 0, 0);
        /** @private */
        _this.category = 'Series';
        /** @private */
        _this.rightSidePoints = [];
        /** @private */
        _this.leftSidePoints = [];
        return _this;
    }
    /**
     * To refresh the Datamanager for series.
     *
     * @private
     * @param {AccumulationChart} accumulation - The accumulation chart control.
     * @param {boolean} render - Specifies whether to render the accumulation chart after refreshing the DataManager.
     * @returns {void}
     */
    AccumulationSeries.prototype.refreshDataManager = function (accumulation, render) {
        var _this = this;
        this.accumulation = accumulation;
        this.radius = this.radius ? this.radius : (Browser.isDevice && this.dataLabel.position === 'Outside') ? '40%' : '80%';
        var dateSource = this.dataSource || accumulation.dataSource;
        if (!(dateSource instanceof DataManager) && isNullOrUndefined(this.query)) {
            this.dataManagerSuccess({ result: dateSource, count: dateSource.length }, accumulation, render);
            return;
        }
        var dataManager = this.dataModule.getData(this.dataModule.generateQuery().requiresCount());
        dataManager.then(function (e) { return _this.dataManagerSuccess(e, accumulation); });
    };
    /**
     * To get points on dataManager is success.
     *
     * @private
     * @param {Object} e - The data manager result object.
     * @param {Object} e.result - The result of the data manager process.
     * @param {number} e.count - The count of items in the result.
     * @param {AccumulationChart} accumulation - The accumulation chart control.
     * @param {boolean} render - Specifies whether to render the accumulation chart after retrieving the points.
     * @returns {void}
     */
    AccumulationSeries.prototype.dataManagerSuccess = function (e, accumulation, render) {
        if (render === void 0) { render = true; }
        var argsData = {
            name: seriesRender, series: this, data: e.result
        };
        accumulation.allowServerDataBinding = false;
        accumulation.trigger(seriesRender, argsData);
        this.resultData = e.result !== '' ? e.result : [];
        if (!render) {
            this.getPoints(this.resultData, accumulation); // To update datasource using onPropertyChanged method. incident id: 290690
        }
        if ((++accumulation.seriesCounts === accumulation.visibleSeries.length && render)) {
            this.getPoints(this.resultData, accumulation);
            accumulation.refreshChart();
        }
    };
    /**
     * To find points from result data.
     *
     * @private
     * @param {Object} result - The result of the process.
     * @param {AccumulationChart} accumulation - The accumulation chart control.
     * @returns {void}
     */
    AccumulationSeries.prototype.getPoints = function (result, accumulation) {
        var length = Object.keys(result).length;
        this.sumOfPoints = 0;
        if (length === 0) {
            // fix for Pie datalabels are not removed for empty datasource
            this.points = [];
            return null;
        }
        if (this.groupTo) {
            this.findSumOfPoints(result);
        }
        this.points = [];
        this.clubbedPoints = [];
        this.sumOfClub = 0;
        var point;
        var colors = this.palettes.length ? this.palettes : getSeriesColor(accumulation.theme);
        var clubValue = stringToNumber(this.groupTo, this.sumOfPoints);
        for (var i = 0; i < length; i++) {
            point = this.setPoints(result, i, colors, accumulation);
            if (!this.isClub(point, clubValue, i)) {
                if (isNullOrUndefined(point.y)) {
                    point.visible = false;
                }
                this.pushPoints(point, colors);
            }
            else {
                point.index = this.clubbedPoints.length;
                point.isExplode = true;
                this.clubbedPoints.push(point);
                point.isSliced = true;
            }
        }
        if (!this.groupTo) {
            this.findSumOfPoints(result);
        }
        this.lastGroupTo = this.groupTo;
        if (this.sumOfClub > 0) {
            var clubPoint_1 = this.generateClubPoint();
            this.pushPoints(clubPoint_1, colors);
            var pointsLength_1 = this.points.length - 1;
            this.clubbedPoints.map(function (point) {
                point.index += pointsLength_1;
                point.color = clubPoint_1.color;
            });
        }
        if (this.clubbedPoints.length && this.explode && this.type === 'Pie'
            && (this.explodeAll || this.points[this.points.length - 1].index === this.explodeIndex)) {
            this.points.splice(this.points.length - 1, 1);
            this.points = this.points.concat(this.clubbedPoints);
        }
    };
    AccumulationSeries.prototype.generateClubPoint = function () {
        var clubPoint = new AccPoints();
        clubPoint.isClubbed = true;
        clubPoint.x = 'Others';
        clubPoint.y = this.sumOfClub;
        clubPoint.text = clubPoint.originalText = clubPoint.x + ': ' + this.sumOfClub;
        clubPoint.sliceRadius = '80%';
        return clubPoint;
    };
    /**
     * Method to set point index and color.
     *
     * @param {AccPoints} point - The point data.
     * @param {string[]} colors - The array of colors used in the accumulation chart.
     * @returns {void}
     */
    AccumulationSeries.prototype.pushPoints = function (point, colors) {
        point.index = this.points.length;
        point.isExplode = this.explodeAll || (point.index === this.explodeIndex);
        point.color = point.color || colors[point.index % colors.length];
        this.points.push(point);
    };
    /**
     * Method to find club point.
     *
     * @param {AccPoints} point - The point data.
     * @param {number} clubValue - The club value for accumulation chart.
     * @param {number} index - The index of the point in the data set.
     * @returns {boolean} - false
     */
    AccumulationSeries.prototype.isClub = function (point, clubValue, index) {
        if (!isNullOrUndefined(clubValue)) {
            if (this.groupMode === 'Value' && Math.abs(point.y) <= clubValue) {
                this.sumOfClub += Math.abs(point.y);
                return true;
            }
            else if (this.groupMode === 'Point' && index >= clubValue) {
                this.sumOfClub += Math.abs(point.y);
                return true;
            }
        }
        return false;
    };
    /**
     * Method to find sum of points in the series.
     *
     * @param {Object} result - The result of the process.
     * @returns {void}
     */
    AccumulationSeries.prototype.findSumOfPoints = function (result) {
        var length = Object.keys(result).length;
        for (var i = 0; i < length; i++) {
            if (!isNullOrUndefined(result[i]) && !isNullOrUndefined(result[i][this.yName])
                && !isNaN(result[i][this.yName]) && (this.points.length && this.points[i] &&
                this.points[i].visible && !isNullOrUndefined(this.points[i].y) || this.groupTo)) {
                this.sumOfPoints += Math.abs(result[i][this.yName]);
            }
        }
    };
    /**
     * Method to set points x, y and text from data source.
     *
     * @param {Object} data - The data containing information for the points.
     * @param {number} i - The index of the current point in the data set.
     * @param {string[]} colors - The array of colors used in the accumulation chart.
     * @param {AccumulationChart} accumulation - The accumulation chart control.
     * @returns {AccPoints} - The point data retrieved from the specified index.
     */
    AccumulationSeries.prototype.setPoints = function (data, i, colors, accumulation) {
        var point = new AccPoints();
        point.x = getValue(this.xName, data[i]);
        point.y = getValue(this.yName, data[i]);
        point.legendImageUrl = getValue(this.legendImageUrl, data[i]);
        point.color = getValue(this.pointColorMapping, data[i]);
        point.text = point.originalText = getValue(this.dataLabel.name || '', data[i]);
        point.tooltip = getValue(this.tooltipMappingName || '', data[i]);
        point.sliceRadius = getValue(this.radius, data[i]);
        point.sliceRadius = isNullOrUndefined(point.sliceRadius) ? '80%' : point.sliceRadius;
        point.separatorY = accumulation.intl.formatNumber(point.y, { useGrouping: accumulation.useGroupingSeparator });
        this.setVisibility(point, i);
        this.setAccEmptyPoint(point, i, data);
        return point;
    };
    /**
     * Method render the series elements for accumulation chart.
     *
     * @private
     * @param {AccumulationChart} accumulation - The AccumulationChart control.
     * @param {boolean} redraw - Specifies whether to redraw the points.
     * @returns {void}
     */
    AccumulationSeries.prototype.renderSeries = function (accumulation, redraw) {
        var seriesGroup = redraw ? getElement(accumulation.element.id + '_Series_' + this.index) :
            accumulation.renderer.createGroup({ id: accumulation.element.id + '_Series_' + this.index });
        this.renderPoints(accumulation, seriesGroup, redraw);
        var datalabelGroup;
        if (accumulation.accumulationDataLabelModule && this.dataLabel.visible) {
            datalabelGroup = accumulation.renderer.createGroup({ id: accumulation.element.id + '_datalabel_Series_' + this.index });
            datalabelGroup.style.visibility =
                (((this.animation.enable && animationMode !== 'Disable') || animationMode === 'Enable') && accumulation.animateSeries && this.type === 'Pie') ? 'hidden' : 'visible';
            this.renderDataLabel(accumulation, datalabelGroup, redraw);
        }
        if (this.type === 'Pie') {
            if (!accumulation.redraw) {
                this.findMaxBounds(this.labelBound, this.accumulationBound);
            }
            accumulation.pieSeriesModule.animateSeries(accumulation, this.animation, this, seriesGroup, this.borderRadius, this.points);
        }
        if (!accumulation.redraw && accumulation.accumulationLegendModule) {
            this.labelBound.x -= accumulation.explodeDistance;
            this.labelBound.y -= accumulation.explodeDistance;
            this.labelBound.height += (accumulation.explodeDistance - this.labelBound.y);
            this.labelBound.width += (accumulation.explodeDistance - this.labelBound.x);
        }
    };
    /**
     * Method render the points elements for accumulation chart series.
     *
     * @param {AccumulationChart} accumulation - The AccumulationChart control.
     * @param {Element} seriesGroup - The group element to contain the point elements.
     * @param {boolean} redraw - Specifies whether to redraw the points.
     * @param {boolean} previouRadius - Specifies the previous radius of the pie when animating the individual series point.
     * @param {boolean} previousCenter - Specifies the previous center of the pie when animating the individual series point.
     * @param {boolean} pointAnimation - Specifies whether the point based animation is enabled.
     * @returns {void}
     */
    AccumulationSeries.prototype.renderPoints = function (accumulation, seriesGroup, redraw, previouRadius, previousCenter, pointAnimation) {
        var pointId = accumulation.element.id + '_Series_' + this.index + '_Point_';
        var option;
        var patternFill;
        var options = [];
        var visiblePoints = [];
        var patterns = ['Chessboard', 'Dots', 'DiagonalForward', 'Crosshatch', 'Pacman', 'DiagonalBackward', 'Grid', 'Turquoise', 'Star', 'Triangle', 'Circle', 'Tile', 'HorizontalDash', 'VerticalDash', 'Rectangle', 'Box', 'VerticalStripe', 'HorizontalStripe', 'Bubble'];
        for (var _i = 0, _a = this.points; _i < _a.length; _i++) {
            var point = _a[_i];
            point.percentage = (+(point.y / this.sumOfPoints * 100).toFixed(2));
            var argsData = {
                cancel: false, name: pointRender, series: this, point: point, fill: point.color,
                border: this.isEmpty(point) ? { width: this.emptyPointSettings.border.width, color: this.emptyPointSettings.border.color } :
                    { width: this.border.width, color: this.border.color }, pattern: this.applyPattern ? patterns[point.index % patterns.length] : 'None'
            };
            accumulation.trigger(pointRender, argsData);
            point.color = argsData.fill;
            patternFill = point.color;
            if (this.applyPattern) {
                var selection = new BaseSelection(accumulation);
                patternFill = selection.pattern(accumulation, point.color, point.index, argsData.pattern, this.opacity);
            }
            option = new PathOption(pointId + point.index, patternFill, argsData.border.width || 1, argsData.border.color || point.color, this.opacity, argsData.series.dashArray, '');
            if (this.funnelMode === 'Trapezoidal' && this.type === 'Funnel') {
                options.push(option);
                if (point.visible) {
                    visiblePoints.push(point);
                }
            }
            else {
                accumulation[(firstToLowerCase(this.type) + 'SeriesModule')].
                    renderPoint(point, this, accumulation, option, seriesGroup, redraw, previouRadius, previousCenter, pointAnimation);
            }
        }
        if (this.funnelMode === 'Trapezoidal' && this.type === 'Funnel') {
            accumulation[(firstToLowerCase(this.type) + 'SeriesModule')].
                renderTrapezoidalFunnel(this, visiblePoints, accumulation, options, seriesGroup, redraw);
        }
        else {
            appendChildElement(false, accumulation.getSeriesElement(), seriesGroup, redraw);
        }
    };
    /**
     * Method render the datalabel elements for accumulation chart.
     *
     * @param {AccumulationChart} accumulation - The AccumulationChart control.
     * @param {Element} datalabelGroup - The group element to contain the data label elements.
     * @param {boolean} redraw - Specifies whether to redraw the data labels.
     * @returns {void}
     */
    AccumulationSeries.prototype.renderDataLabel = function (accumulation, datalabelGroup, redraw) {
        accumulation.accumulationDataLabelModule.findAreaRect();
        var element = createElement('div', {
            id: accumulation.element.id + '_Series_0' + '_DataLabelCollections'
        });
        this.leftSidePoints = [];
        this.rightSidePoints = [];
        var firstQuarter = [];
        var secondQuarter = [];
        for (var _i = 0, _a = this.points; _i < _a.length; _i++) {
            var point = _a[_i];
            if (point.visible) {
                if (this.dataLabel.showZero || (!this.dataLabel.showZero && ((point.y !== 0) || (point.y === 0 &&
                    this.emptyPointSettings.mode === 'Zero')))) {
                    accumulation.accumulationDataLabelModule.renderDataLabel(point, this.dataLabel, datalabelGroup, this.points, this.index, element, redraw);
                }
            }
            if (point.midAngle >= 90 && point.midAngle <= 270) {
                this.leftSidePoints.push(point);
            }
            else {
                if (point.midAngle >= 0 && point.midAngle <= 90) {
                    secondQuarter.push(point);
                }
                else {
                    firstQuarter.push(point);
                }
            }
        }
        firstQuarter.sort(function (a, b) { return a.midAngle - b.midAngle; });
        secondQuarter.sort(function (a, b) { return a.midAngle - b.midAngle; });
        this.leftSidePoints.sort(function (a, b) { return a.midAngle - b.midAngle; });
        this.rightSidePoints = firstQuarter.concat(secondQuarter);
        accumulation.accumulationDataLabelModule.drawDataLabels(this, this.dataLabel, datalabelGroup, element, redraw);
        if (this.dataLabel.template !== null && element.childElementCount) {
            var dataLabelCallBack = accumulation.accumulationDataLabelModule.drawDataLabels.bind(accumulation.accumulationDataLabelModule, this, this.dataLabel, datalabelGroup, element, redraw);
            if (accumulation.isReact) {
                accumulation.renderReactTemplates(dataLabelCallBack);
            }
            appendChildElement(false, getElement(accumulation.element.id + '_Secondary_Element'), element, redraw);
        }
        appendChildElement(false, accumulation.getSeriesElement(), datalabelGroup, redraw);
    };
    /**
     * To find maximum bounds for smart legend placing.
     *
     * @private
     * @param {Rect} totalbound - The total bounding rect.
     * @param {Rect} bound - The bounding rect to be compared.
     * @returns {void}
     */
    AccumulationSeries.prototype.findMaxBounds = function (totalbound, bound) {
        totalbound.x = bound.x < totalbound.x ? bound.x : totalbound.x;
        totalbound.y = bound.y < totalbound.y ? bound.y : totalbound.y;
        totalbound.height = (bound.y + bound.height) > totalbound.height ? (bound.y + bound.height) : totalbound.height;
        totalbound.width = (bound.x + bound.width) > totalbound.width ? (bound.x + bound.width) : totalbound.width;
    };
    /**
     * Finds the maximum width of the labels for legend placement.
     *
     * @private
     * @returns {number} The maximum label width.
     */
    AccumulationSeries.prototype.findMaxLabelWidth = function () {
        var max;
        for (var i = 0; i < this.points.length; i++) {
            max = this.points[0].textSize.width;
            if (max < this.points[i].textSize.width) {
                max = this.points[i].textSize.width;
            }
        }
        return max;
    };
    /**
     * To set empty point value for null points.
     *
     * @private
     * @param {AccPoints} point - The point to set as empty.
     * @param {number} i - The index of the point in the data set.
     * @param {Object} data - The data object.
     * @returns {void}
     */
    AccumulationSeries.prototype.setAccEmptyPoint = function (point, i, data) {
        if (!(isNullOrUndefined(point.y) || isNaN(point.y))) {
            return null;
        }
        point.color = this.emptyPointSettings.fill || point.color;
        switch (this.emptyPointSettings.mode) {
            case 'Zero':
                point.y = 0;
                point.visible = true;
                break;
            case 'Average': {
                var previous = data[i - 1] ? (data[i - 1][this.yName] || 0) : 0;
                var next = data[i + 1] ? (data[i + 1][this.yName] || 0) : 0;
                point.y = (Math.abs(previous) + Math.abs(next)) / 2;
                this.sumOfPoints += point.y;
                point.visible = true;
                break;
            }
            default:
                point.visible = false;
                break;
        }
    };
    /**
     * To set visiblity for the point.
     *
     * @private
     * @param {AccPoints} point - The point to set visibility.
     * @param {number} i - The index of the point in the data set.
     *
     * @returns {void}
     */
    AccumulationSeries.prototype.setVisibility = function (point, i) {
        if (this.accumulation.accumulationLegendModule && this.accumulation.accumulationLegendModule.legendCollections &&
            this.accumulation.accumulationLegendModule.legendCollections[i] &&
            !this.accumulation.accumulationLegendModule.legendCollections[i].visible) {
            point.visible = false;
        }
    };
    /**
     * Updates the data source for the series.
     *
     * @function setData
     * @param {Object} data – Updated data source for the series.
     * @param {number} duration – The duration for the animation.
     * @returns {void}
     */
    AccumulationSeries.prototype.setData = function (data, duration) {
        if (!data) {
            return null;
        }
        var samePoints = false;
        if (this.dataSource.length === data.length) {
            samePoints = true;
            for (var i = 0; i < data.length; i++) {
                if (this.dataSource[i][this.xName] === data[i][this.xName]) {
                    var point = this.points[i];
                    var existingPoint = this.dataSource[i];
                    if ((existingPoint[this.yName] !== data[i][this.yName])) {
                        point.y = data[i][this.yName];
                        this.dataSource[i] = data[i];
                    }
                }
                else {
                    samePoints = false;
                    break;
                }
            }
        }
        if (!samePoints) {
            this.dataSource = data;
        }
        else {
            this.sumOfPoints = 0;
            var visiblePoints = [];
            for (var i = 0; i < this.resultData.length; i++) {
                if (this.points[i] && this.points[i].visible) {
                    visiblePoints.push(this.resultData[i]);
                }
            }
            this.findSumOfPoints(visiblePoints);
            this.accumulation.redraw = this.borderRadius ? false : this.accumulation.enableAnimation;
            this.accumulation.animateSeries = false;
            var chartDuration = this.accumulation.duration;
            this.accumulation.duration = isNullOrUndefined(duration) ? 500 : duration;
            this.accumulation[(firstToLowerCase(this.type) + 'SeriesModule')].initProperties(this.accumulation, this);
            this.renderPoints(this.accumulation, getElement(this.accumulation.element.id + '_Series_' + this.index), this.accumulation.redraw, null, null, true);
            if (this.accumulation.centerLabel.text) {
                this.accumulation.renderCenterLabel(true, true);
            }
            if (this.accumulation.annotationModule) {
                this.accumulation.annotationModule.renderAnnotations(getElement(this.accumulation.element.id + '_Secondary_Element'));
            }
            if (this.accumulation.accumulationDataLabelModule && this.dataLabel.visible) {
                this.renderDataLabel(this.accumulation, getElement(this.accumulation.element.id + '_datalabel_Series_' + this.index), this.accumulation.redraw);
            }
            this.accumulation.redraw = false;
            this.accumulation.duration = chartDuration;
        }
    };
    /**
     * Adds a data point to the data source for the series.
     *
     * @function addPoint
     * @param {Object} dataPoint - The data point to be added.
     * @param {number} duration – The duration for the animation.
     * @returns {void}
     */
    AccumulationSeries.prototype.addPoint = function (dataPoint, duration) {
        var maxWidth;
        if (this.accumulation.series[0].dataLabel.visible) {
            maxWidth = this.findMaxLabelWidth();
        }
        this.dataSource.push(dataPoint);
        this.resultData = this.dataSource;
        this.sumOfPoints = 0;
        var visiblepoints = [];
        for (var i = 0; i < this.resultData.length; i++) {
            if (this.points[i] && this.points[i].visible) {
                visiblepoints.push(this.resultData[i]);
            }
            else if (i === this.resultData.length - 1) {
                visiblepoints.push(this.resultData[i]);
            }
        }
        var pointIndex = this.points.length === 0 ? 0 : this.points[this.points.length - 1].index + 1;
        var colors = this.palettes.length ? this.palettes : getSeriesColor(this.accumulation.theme);
        var point = this.setPoints(this.dataSource, pointIndex, colors, this.accumulation);
        this.pushPoints(point, colors);
        this.findSumOfPoints(visiblepoints);
        this.accumulation.redraw = this.borderRadius ? false : this.accumulation.enableAnimation;
        var chartDuration = this.accumulation.duration;
        this.accumulation.duration = isNullOrUndefined(duration) ? 500 : duration;
        this.updateSeries(getElement(this.accumulation.element.id + '_Series_' + this.index), maxWidth, 'addPoint');
        this.accumulation.redraw = false;
        this.accumulation.duration = chartDuration;
    };
    /**
     * Removes a data point from the series data source at the specified index.
     *
     * @function removePoint
     * @param {number} index – The index of the data point to be removed from the series.
     * @param {number} duration – The duration for the animation.
     * @returns {void}
     */
    AccumulationSeries.prototype.removePoint = function (index, duration) {
        var dataSource = extend([], this.dataSource, null, true);
        var chartDuration = this.accumulation.duration;
        if (dataSource.length > 0 && index >= 0 && index < dataSource.length) {
            this.sumOfPoints = 0;
            var removepoints = [];
            for (var i = 0; i < this.dataSource.length; i++) {
                if (i !== index && this.points[i] && this.points[i].visible) {
                    removepoints.push(this.dataSource[i]);
                }
            }
            dataSource.splice(index, 1);
            this.dataSource.splice(index, 1);
            this.accumulation.redraw = this.borderRadius ? false : this.accumulation.enableAnimation;
            this.accumulation.duration = isNullOrUndefined(duration) ? 500 : duration;
            this.points.splice(index, 1);
            for (var i = index; i < this.points.length; i++) {
                var point = this.points[i];
                point.index = i;
                point.y = this.points[i].y;
            }
            this.findSumOfPoints(removepoints);
            var element = getElement(this.accumulation.element.id + '_Series_0_Point_' + (this.points.length));
            if (element) {
                element.parentNode.removeChild(element);
            }
            this.updateSeries(getElement(this.accumulation.element.id + '_Series_' + this.index), undefined, 'removePoint', index);
            this.accumulation.redraw = false;
            this.accumulation.duration = chartDuration;
        }
    };
    /**
     * Update the series based on addPoint and removePoint function.
     *
     * @param {Element} seriesGroup - Series group needs to be update.
     * @param {number} maxLabelWidth - Specifies the maximum label width.
     * @param {string} updatePoint - Specifies remove or add point.
     * @param {number} index - specifies point index to remove.
     * @returns {void}
     */
    AccumulationSeries.prototype.updateSeries = function (seriesGroup, maxLabelWidth, updatePoint, index) {
        var previousRadius = this.accumulation[(firstToLowerCase(this.type) + 'SeriesModule')].radius;
        var previousCenter = this.accumulation[(firstToLowerCase(this.type) + 'SeriesModule')].center;
        var previousLegendBounds;
        if (this.accumulation.legendSettings.visible) {
            if (updatePoint === 'addPoint') {
                this.accumulation.accumulationLegendModule.
                    legendCollections.push(new LegendOptions(this.points[this.points.length - 1].x.toString(), this.points[this.points.length - 1].color, this.legendShape, this.points[this.points.length - 1].visible, this.type, this.points[this.points.length - 1].legendImageUrl, null, null, this.points[this.points.length - 1].index, this.index));
            }
            else {
                this.accumulation.accumulationLegendModule.legendCollections.splice(index, 1);
                for (var i = index; i < this.accumulation.accumulationLegendModule.legendCollections.length; i++) {
                    this.accumulation.accumulationLegendModule.legendCollections[i].pointIndex = i;
                }
            }
            if (this.accumulation.accumulationLegendModule.legendCollections.length >= 1) {
                previousLegendBounds = this.accumulation.accumulationLegendModule.legendBounds;
                this.accumulation.accumulationLegendModule.calculateLegendBounds(this.accumulation.initialClipRect, this.accumulation.availableSize, null, previousLegendBounds, true);
                if (this.dataLabel && this.dataLabel.position === 'Outside' && (this.accumulation.legendSettings.position === 'Bottom' || (this.accumulation.legendSettings.position === 'Top')) ? (previousLegendBounds.height !== this.accumulation.accumulationLegendModule.legendBounds.height) : (previousLegendBounds.width !== this.accumulation.accumulationLegendModule.legendBounds.width)) {
                    var titleHeight = (this.accumulation.title ? measureText(this.accumulation.title, this.accumulation.titleStyle, this.accumulation.themeStyle.chartTitleFont).height *
                        this.accumulation.titleCollection.length : 0);
                    var subTitleHeight = (this.accumulation.subTitle ?
                        (measureText(this.accumulation.subTitle, this.accumulation.subTitleStyle, this.accumulation.themeStyle.chartSubTitleFont).height *
                            this.accumulation.subTitleCollection.length) : 0);
                    this.accumulation.initialClipRect = new Rect(this.accumulation.margin.left, this.accumulation.margin.top, this.accumulation.availableSize.width, this.accumulation.availableSize.height);
                    subtractRect(this.accumulation.initialClipRect, new Rect(0, (subTitleHeight
                        + titleHeight), this.accumulation.margin.right +
                        this.accumulation.margin.left, this.accumulation.margin.bottom + this.accumulation.margin.top));
                    this.accumulation.accumulationLegendModule.calculateLegendBounds(this.accumulation.initialClipRect, this.accumulation.availableSize, null);
                }
            }
        }
        this.accumulation[(firstToLowerCase(this.type) + 'SeriesModule')].initProperties(this.accumulation, this);
        this.renderPoints(this.accumulation, seriesGroup, this.accumulation.redraw, previousRadius, previousCenter, true);
        if (previousLegendBounds && ((this.accumulation.legendSettings.position === 'Bottom' || (this.accumulation.legendSettings.position === 'Top')) ? (previousLegendBounds.height !== this.accumulation.accumulationLegendModule.legendBounds.height) : (previousLegendBounds.width !== this.accumulation.accumulationLegendModule.legendBounds.width)) && this.accumulation.centerLabel.text) {
            this.accumulation.renderCenterLabel(true, true);
        }
        if (this.accumulation.annotationModule) {
            this.accumulation.annotationModule.renderAnnotations(getElement(this.accumulation.element.id + '_Secondary_Element'));
        }
        if (this.accumulation.accumulationDataLabelModule && this.dataLabel.visible) {
            var datalabelGroup = this.accumulation.renderer.createGroup({ id: this.accumulation.element.id + '_datalabel_Series_' + this.index });
            this.renderDataLabel(this.accumulation, datalabelGroup, this.accumulation.redraw);
        }
        if (this.accumulation.legendSettings.visible) {
            if (this.type === 'Pie') {
                if (this.dataLabel.visible && this.points[this.points.length - 1] && this.points[this.points.length - 1].textSize.width > maxLabelWidth && this.accumulation.legendSettings.position !== 'Top' && this.accumulation.legendSettings.position !== 'Bottom') {
                    this.accumulation.visibleSeries[0].findMaxBounds(this.accumulation.visibleSeries[0].labelBound, this.points[this.points.length - 1].labelRegion);
                    this.findMaxBounds(this.labelBound, this.accumulationBound);
                    this.labelBound.x -= this.accumulation.explodeDistance;
                    this.labelBound.y -= this.accumulation.explodeDistance;
                    this.labelBound.height += (this.accumulation.explodeDistance - this.labelBound.y);
                    this.labelBound.width += (this.accumulation.explodeDistance - this.labelBound.x);
                }
                this.accumulation.accumulationLegendModule.getSmartLegendLocation(this.accumulation.visibleSeries[0].labelBound, this.accumulation.accumulationLegendModule.legendBounds, this.accumulation.margin);
            }
            this.accumulation.accumulationLegendModule.renderLegend(this.accumulation, this.accumulation.legendSettings, this.accumulation.accumulationLegendModule.legendBounds, this.accumulation.redraw, true);
        }
    };
    /**
     * To find point is empty.
     *
     * @param {AccPoints} point - The point to check.
     * @returns {boolean} - True if the point is empty, otherwise false.
     */
    AccumulationSeries.prototype.isEmpty = function (point) {
        return point.color === this.emptyPointSettings.fill;
    };
    __decorate([
        Property('')
    ], AccumulationSeries.prototype, "dataSource", void 0);
    __decorate([
        Property()
    ], AccumulationSeries.prototype, "query", void 0);
    __decorate([
        Property('')
    ], AccumulationSeries.prototype, "xName", void 0);
    __decorate([
        Property('')
    ], AccumulationSeries.prototype, "name", void 0);
    __decorate([
        Property('')
    ], AccumulationSeries.prototype, "tooltipMappingName", void 0);
    __decorate([
        Property('')
    ], AccumulationSeries.prototype, "yName", void 0);
    __decorate([
        Property(true)
    ], AccumulationSeries.prototype, "visible", void 0);
    __decorate([
        Complex({ color: null, width: 0 }, Border)
    ], AccumulationSeries.prototype, "border", void 0);
    __decorate([
        Complex(null, Animation)
    ], AccumulationSeries.prototype, "animation", void 0);
    __decorate([
        Property('SeriesType')
    ], AccumulationSeries.prototype, "legendShape", void 0);
    __decorate([
        Property('')
    ], AccumulationSeries.prototype, "legendImageUrl", void 0);
    __decorate([
        Property('')
    ], AccumulationSeries.prototype, "pointColorMapping", void 0);
    __decorate([
        Property(false)
    ], AccumulationSeries.prototype, "applyPattern", void 0);
    __decorate([
        Property(null)
    ], AccumulationSeries.prototype, "selectionStyle", void 0);
    __decorate([
        Property(null)
    ], AccumulationSeries.prototype, "groupTo", void 0);
    __decorate([
        Property('Value')
    ], AccumulationSeries.prototype, "groupMode", void 0);
    __decorate([
        Complex({}, AccumulationDataLabelSettings)
    ], AccumulationSeries.prototype, "dataLabel", void 0);
    __decorate([
        Property([])
    ], AccumulationSeries.prototype, "palettes", void 0);
    __decorate([
        Property(0)
    ], AccumulationSeries.prototype, "startAngle", void 0);
    __decorate([
        Property(null)
    ], AccumulationSeries.prototype, "endAngle", void 0);
    __decorate([
        Property(null)
    ], AccumulationSeries.prototype, "radius", void 0);
    __decorate([
        Property('0')
    ], AccumulationSeries.prototype, "innerRadius", void 0);
    __decorate([
        Property('Pie')
    ], AccumulationSeries.prototype, "type", void 0);
    __decorate([
        Property(true)
    ], AccumulationSeries.prototype, "enableTooltip", void 0);
    __decorate([
        Property(false)
    ], AccumulationSeries.prototype, "explode", void 0);
    __decorate([
        Property('30%')
    ], AccumulationSeries.prototype, "explodeOffset", void 0);
    __decorate([
        Property(false)
    ], AccumulationSeries.prototype, "explodeAll", void 0);
    __decorate([
        Property(null)
    ], AccumulationSeries.prototype, "explodeIndex", void 0);
    __decorate([
        Complex({ mode: 'Drop' }, EmptyPointSettings)
    ], AccumulationSeries.prototype, "emptyPointSettings", void 0);
    __decorate([
        Property(0)
    ], AccumulationSeries.prototype, "gapRatio", void 0);
    __decorate([
        Property('80%')
    ], AccumulationSeries.prototype, "width", void 0);
    __decorate([
        Property('80%')
    ], AccumulationSeries.prototype, "height", void 0);
    __decorate([
        Property('20%')
    ], AccumulationSeries.prototype, "neckWidth", void 0);
    __decorate([
        Property('20%')
    ], AccumulationSeries.prototype, "neckHeight", void 0);
    __decorate([
        Property('Linear')
    ], AccumulationSeries.prototype, "pyramidMode", void 0);
    __decorate([
        Property('Standard')
    ], AccumulationSeries.prototype, "funnelMode", void 0);
    __decorate([
        Property(1)
    ], AccumulationSeries.prototype, "opacity", void 0);
    __decorate([
        Property('0')
    ], AccumulationSeries.prototype, "dashArray", void 0);
    __decorate([
        Complex({}, Accessibility)
    ], AccumulationSeries.prototype, "accessibility", void 0);
    __decorate([
        Property(0)
    ], AccumulationSeries.prototype, "borderRadius", void 0);
    return AccumulationSeries;
}(ChildProperty));
export { AccumulationSeries };
/**
 * method to get series from index.
 *
 * @private
 * @param {number} index - The index of the series to retrieve.
 * @param {AccumulationSeries[]} visibleSeries - The array of visible series in the chart.
 * @returns {AccumulationSeries} - The series retrieved from the specified index.
 */
export function getSeriesFromIndex(index, visibleSeries) {
    for (var _i = 0, visibleSeries_1 = visibleSeries; _i < visibleSeries_1.length; _i++) {
        var series = visibleSeries_1[_i];
        if (index === series.index) {
            return series;
        }
    }
    return visibleSeries[0];
}
/**
 * method to get point from index.
 *
 * @private
 * @param {number} index - The index of the point to retrieve.
 * @param {AccPoints[]} points - The array of points in the data set.
 * @returns {AccPoints} - The point retrieved from the specified index.
 */
export function pointByIndex(index, points) {
    for (var _i = 0, points_1 = points; _i < points_1.length; _i++) {
        var point = points_1[_i];
        if (point.index === index) {
            return point;
        }
    }
    return null;
}
