/**
 * DevExtreme (cjs/viz/series/base_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.Series = Series;
exports.mixins = void 0;
var _type = require("../../core/utils/type");
var _extend2 = require("../../core/utils/extend");
var _iterator = require("../../core/utils/iterator");
var _base_point = require("./points/base_point");
var _utils = require("../core/utils");
var _common = require("../../core/utils/common");
var _consts = _interopRequireDefault(require("../components/consts"));
var _range_data_calculator = _interopRequireDefault(require("./helpers/range_data_calculator"));
var scatterSeries = _interopRequireWildcard(require("./scatter_series"));
var lineSeries = _interopRequireWildcard(require("./line_series"));
var areaSeries = _interopRequireWildcard(require("./area_series"));
var barSeries = _interopRequireWildcard(require("./bar_series"));
var _range_series = require("./range_series");
var _bubble_series = require("./bubble_series");
var pieSeries = _interopRequireWildcard(require("./pie_series"));
var financialSeries = _interopRequireWildcard(require("./financial_series"));
var stackedSeries = _interopRequireWildcard(require("./stacked_series"));

function _getRequireWildcardCache(nodeInterop) {
    if ("function" !== typeof WeakMap) {
        return null
    }
    var cacheBabelInterop = new WeakMap;
    var cacheNodeInterop = new WeakMap;
    return (_getRequireWildcardCache = function(nodeInterop) {
        return nodeInterop ? cacheNodeInterop : cacheBabelInterop
    })(nodeInterop)
}

function _interopRequireWildcard(obj, nodeInterop) {
    if (!nodeInterop && obj && obj.__esModule) {
        return obj
    }
    if (null === obj || "object" !== typeof obj && "function" !== typeof obj) {
        return {
            default: obj
        }
    }
    var cache = _getRequireWildcardCache(nodeInterop);
    if (cache && cache.has(obj)) {
        return cache.get(obj)
    }
    var newObj = {};
    var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
    for (var key in obj) {
        if ("default" !== key && Object.prototype.hasOwnProperty.call(obj, key)) {
            var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
            if (desc && (desc.get || desc.set)) {
                Object.defineProperty(newObj, key, desc)
            } else {
                newObj[key] = obj[key]
            }
        }
    }
    newObj.default = obj;
    if (cache) {
        cache.set(obj, newObj)
    }
    return newObj
}

function _interopRequireDefault(obj) {
    return obj && obj.__esModule ? obj : {
        default: obj
    }
}
const seriesNS = {};
const states = _consts.default.states;
const DISCRETE = "discrete";
const SELECTED_STATE = states.selectedMark;
const HOVER_STATE = states.hoverMark;
const HOVER = states.hover;
const NORMAL = states.normal;
const SELECTION = states.selection;
const APPLY_SELECTED = states.applySelected;
const APPLY_HOVER = states.applyHover;
const RESET_ITEM = states.resetItem;
const NONE_MODE = "none";
const INCLUDE_POINTS = "includepoints";
const NEAREST_POINT = "nearestpoint";
const SERIES_SELECTION_CHANGED = "seriesSelectionChanged";
const POINT_SELECTION_CHANGED = "pointSelectionChanged";
const SERIES_HOVER_CHANGED = "seriesHoverChanged";
const POINT_HOVER_CHANGED = "pointHoverChanged";
const ALL_SERIES_POINTS = "allseriespoints";
const ALL_ARGUMENT_POINTS = "allargumentpoints";
const POINT_HOVER = "pointHover";
const CLEAR_POINT_HOVER = "clearPointHover";
const SERIES_SELECT = "seriesSelect";
const POINT_SELECT = "pointSelect";
const POINT_DESELECT = "pointDeselect";
const getEmptyBusinessRange = function() {
    return {
        arg: {},
        val: {}
    }
};

function triggerEvent(element, event, point) {
    element && element.trigger(event, point)
}
seriesNS.mixins = {
    chart: {},
    pie: {},
    polar: {}
};
seriesNS.mixins.chart.scatter = scatterSeries.chart;
seriesNS.mixins.polar.scatter = scatterSeries.polar;
(0, _extend2.extend)(seriesNS.mixins.pie, pieSeries);
(0, _extend2.extend)(seriesNS.mixins.chart, lineSeries.chart, areaSeries.chart, barSeries.chart, _range_series.chart, _bubble_series.chart, financialSeries, stackedSeries.chart);
(0, _extend2.extend)(seriesNS.mixins.polar, lineSeries.polar, areaSeries.polar, barSeries.polar, stackedSeries.polar);

function includePointsMode(mode) {
    mode = (0, _utils.normalizeEnum)(mode);
    return mode === INCLUDE_POINTS || "allseriespoints" === mode
}

function getLabelOptions(labelOptions, defaultColor) {
    const opt = labelOptions || {};
    const labelFont = (0, _extend2.extend)({}, opt.font) || {};
    const labelBorder = opt.border || {};
    const labelConnector = opt.connector || {};
    const backgroundAttr = {
        fill: opt.backgroundColor || defaultColor,
        "stroke-width": labelBorder.visible ? labelBorder.width || 0 : 0,
        stroke: labelBorder.visible && labelBorder.width ? labelBorder.color : "none",
        dashStyle: labelBorder.dashStyle
    };
    const connectorAttr = {
        stroke: labelConnector.visible && labelConnector.width ? labelConnector.color || defaultColor : "none",
        "stroke-width": labelConnector.visible ? labelConnector.width || 0 : 0
    };
    labelFont.color = "none" === opt.backgroundColor && "#ffffff" === (0, _utils.normalizeEnum)(labelFont.color) && "inside" !== opt.position ? defaultColor : labelFont.color;
    return {
        alignment: opt.alignment,
        format: opt.format,
        argumentFormat: opt.argumentFormat,
        customizeText: (0, _type.isFunction)(opt.customizeText) ? opt.customizeText : void 0,
        attributes: {
            font: labelFont
        },
        visible: 0 !== labelFont.size ? opt.visible : false,
        showForZeroValues: opt.showForZeroValues,
        horizontalOffset: opt.horizontalOffset,
        verticalOffset: opt.verticalOffset,
        radialOffset: opt.radialOffset,
        background: backgroundAttr,
        position: opt.position,
        connector: connectorAttr,
        rotationAngle: opt.rotationAngle,
        wordWrap: opt.wordWrap,
        textOverflow: opt.textOverflow,
        cssClass: opt.cssClass,
        displayFormat: opt.displayFormat
    }
}

function setPointHoverState(point, legendCallback) {
    point.fullState |= HOVER_STATE;
    point.applyView(legendCallback)
}

function releasePointHoverState(point, legendCallback) {
    point.fullState &= ~HOVER_STATE;
    point.applyView(legendCallback);
    point.releaseHoverState()
}

function setPointSelectedState(point, legendCallback) {
    point.fullState |= SELECTED_STATE;
    point.applyView(legendCallback)
}

function releasePointSelectedState(point, legendCallback) {
    point.fullState &= ~SELECTED_STATE;
    point.applyView(legendCallback)
}

function mergePointOptionsCore(base, extra) {
    const options = (0, _extend2.extend)({}, base, extra);
    options.border = (0, _extend2.extend)({}, base && base.border, extra && extra.border);
    return options
}

function mergePointOptions(base, extra) {
    const options = mergePointOptionsCore(base, extra);
    options.image = (0, _extend2.extend)(true, {}, base.image, extra.image);
    options.selectionStyle = mergePointOptionsCore(base.selectionStyle, extra.selectionStyle);
    options.hoverStyle = mergePointOptionsCore(base.hoverStyle, extra.hoverStyle);
    return options
}

function Series(settings, options) {
    this.fullState = 0;
    this._extGroups = settings;
    this._renderer = settings.renderer;
    this._group = settings.renderer.g().attr({
        class: "dxc-series"
    });
    this._eventTrigger = settings.eventTrigger;
    this._eventPipe = settings.eventPipe;
    this._incidentOccurred = settings.incidentOccurred;
    this._legendCallback = _common.noop;
    this.updateOptions(options, settings)
}

function getData(pointData) {
    return pointData.data
}

function getValueChecker(axisType, axis) {
    if (!axis || "logarithmic" !== axisType || false !== axis.getOptions().allowNegatives) {
        return () => true
    } else {
        return value => value > 0
    }
}
Series.prototype = {
    constructor: Series,
    _createLegendState: _common.noop,
    getLegendStyles: function() {
        return this._styles.legendStyles
    },
    _createStyles: function(options) {
        const that = this;
        const mainSeriesColor = options.mainSeriesColor;
        const colorId = this._getColorId(options);
        const hoverStyle = options.hoverStyle || {};
        const selectionStyle = options.selectionStyle || {};
        if (colorId) {
            that._turnOffHatching(hoverStyle, selectionStyle)
        }
        that._styles = {
            labelColor: mainSeriesColor,
            normal: that._parseStyle(options, mainSeriesColor, mainSeriesColor),
            hover: that._parseStyle(hoverStyle, colorId || mainSeriesColor, mainSeriesColor),
            selection: that._parseStyle(selectionStyle, colorId || mainSeriesColor, mainSeriesColor),
            legendStyles: {
                normal: that._createLegendState(options, colorId || mainSeriesColor),
                hover: that._createLegendState(hoverStyle, colorId || mainSeriesColor),
                selection: that._createLegendState(selectionStyle, colorId || mainSeriesColor)
            }
        }
    },
    setClippingParams(baseId, wideId, forceClipping) {
        let clipLabels = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : true;
        this._paneClipRectID = baseId;
        this._widePaneClipRectID = wideId;
        this._forceClipping = forceClipping;
        this._clipLabels = clipLabels
    },
    applyClip: function() {
        this._group.attr({
            "clip-path": this._paneClipRectID
        })
    },
    resetClip: function() {
        this._group.attr({
            "clip-path": null
        })
    },
    getTagField: function() {
        return this._options.tagField || "tag"
    },
    getValueFields: _common.noop,
    getSizeField: _common.noop,
    getArgumentField: _common.noop,
    getPoints: function() {
        return this._points
    },
    getPointsInViewPort: function() {
        return _range_data_calculator.default.getPointsInViewPort(this)
    },
    _createPoint: function(data, index, oldPoint) {
        data.index = index;
        const that = this;
        const pointsByArgument = that.pointsByArgument;
        const options = that._getCreatingPointOptions(data);
        const arg = data.argument.valueOf();
        let point = oldPoint;
        if (point) {
            point.update(data, options)
        } else {
            point = new _base_point.Point(that, data, options);
            if (that.isSelected() && includePointsMode(that.lastSelectionMode)) {
                point.setView(SELECTION)
            }
        }
        const pointByArgument = pointsByArgument[arg];
        if (pointByArgument) {
            pointByArgument.push(point)
        } else {
            pointsByArgument[arg] = [point]
        }
        if (point.hasValue()) {
            that.customizePoint(point, data)
        }
        return point
    },
    getRangeData: function() {
        return this._visible ? this._getRangeData() : {
            arg: {},
            val: {}
        }
    },
    getArgumentRange: function() {
        return this._visible ? _range_data_calculator.default.getArgumentRange(this) : {
            arg: {},
            val: {}
        }
    },
    getViewport: function() {
        return _range_data_calculator.default.getViewport(this)
    },
    _deleteGroup: function(groupName) {
        const group = this[groupName];
        if (group) {
            group.dispose();
            this[groupName] = null
        }
    },
    updateOptions(newOptions, settings) {
        const that = this;
        const widgetType = newOptions.widgetType;
        const oldType = that.type;
        const newType = newOptions.type;
        that.type = newType && (0, _utils.normalizeEnum)(newType.toString());
        if (!that._checkType(widgetType) || that._checkPolarBarType(widgetType, newOptions)) {
            that.dispose();
            that.isUpdated = false;
            return
        }
        if (oldType !== that.type) {
            that._firstDrawing = true;
            that._resetType(oldType, widgetType);
            that._setType(that.type, widgetType)
        } else {
            that._defineDrawingState()
        }
        that._options = newOptions;
        that._pointOptions = null;
        that.name = newOptions.name;
        that.pane = newOptions.pane;
        that.tag = newOptions.tag;
        if (settings) {
            that._seriesModes = settings.commonSeriesModes || that._seriesModes;
            that._valueAxis = settings.valueAxis || that._valueAxis;
            that.axis = that._valueAxis && that._valueAxis.name;
            that._argumentAxis = settings.argumentAxis || that._argumentAxis
        }
        that._createStyles(newOptions);
        that._stackName = null;
        that._updateOptions(newOptions);
        that._visible = newOptions.visible;
        that.isUpdated = true;
        that.stack = newOptions.stack;
        that.barOverlapGroup = newOptions.barOverlapGroup;
        that._createGroups();
        that._processEmptyValue = newOptions.ignoreEmptyPoints ? x => null === x ? void 0 : x : x => x
    },
    _defineDrawingState() {
        this._firstDrawing = true
    },
    _disposePoints: function(points) {
        (0, _iterator.each)(points || [], (function(_, p) {
            p.dispose()
        }))
    },
    updateDataType: function(settings) {
        this.argumentType = settings.argumentType;
        this.valueType = settings.valueType;
        this.argumentAxisType = settings.argumentAxisType;
        this.valueAxisType = settings.valueAxisType;
        this.showZero = settings.showZero;
        this._argumentChecker = getValueChecker(settings.argumentAxisType, this.getArgumentAxis());
        this._valueChecker = getValueChecker(settings.valueAxisType, this.getValueAxis());
        return this
    },
    _argumentChecker: function() {
        return true
    },
    _valueChecker: function() {
        return true
    },
    getOptions: function() {
        return this._options
    },
    _getOldPoint: function(data, oldPointsByArgument, index) {
        const arg = data.argument && data.argument.valueOf();
        const point = (oldPointsByArgument[arg] || [])[0];
        if (point) {
            oldPointsByArgument[arg].splice(0, 1)
        }
        return point
    },
    updateData: function(data) {
        const that = this;
        const options = that._options;
        const nameField = options.nameField;
        data = data || [];
        if (data.length) {
            that._canRenderCompleteHandle = true
        }
        const dataSelector = this._getPointDataSelector();
        let itemsWithoutArgument = 0;
        that._data = data.reduce((data, dataItem, index) => {
            const pointDataItem = dataSelector(dataItem);
            if ((0, _type.isDefined)(pointDataItem.argument)) {
                if (!nameField || dataItem[nameField] === options.nameFieldValue) {
                    pointDataItem.index = index;
                    data.push(pointDataItem)
                }
            } else {
                itemsWithoutArgument++
            }
            return data
        }, []);
        if (itemsWithoutArgument && itemsWithoutArgument === data.length) {
            that._incidentOccurred("W2002", [that.name, that.getArgumentField()])
        }
        that._endUpdateData()
    },
    _getData() {
        let data = this._data || [];
        if (this.useAggregation()) {
            const argumentRange = this.argumentAxisType !== DISCRETE ? this.getArgumentRange() : {};
            const aggregationInfo = this.getArgumentAxis().getAggregationInfo(this._useAllAggregatedPoints, argumentRange);
            data = this._resample(aggregationInfo, data)
        }
        return data
    },
    useAggregation: function() {
        const aggregation = this.getOptions().aggregation;
        return aggregation && aggregation.enabled
    },
    autoHidePointMarkersEnabled: _common.noop,
    usePointsToDefineAutoHiding: _common.noop,
    createPoints(useAllAggregatedPoints) {
        this._normalizeUsingAllAggregatedPoints(useAllAggregatedPoints);
        this._createPoints()
    },
    _normalizeUsingAllAggregatedPoints: function(useAllAggregatedPoints) {
        this._useAllAggregatedPoints = this.useAggregation() && (this.argumentAxisType === DISCRETE || (this._data || []).length > 1 && !!useAllAggregatedPoints)
    },
    _createPoints: function() {
        const that = this;
        const oldPointsByArgument = that.pointsByArgument || {};
        const data = that._getData();
        that.pointsByArgument = {};
        that._calculateErrorBars(data);
        const skippedFields = {};
        const points = data.reduce((points, pointDataItem) => {
            if (that._checkData(pointDataItem, skippedFields)) {
                const pointIndex = points.length;
                const oldPoint = that._getOldPoint(pointDataItem, oldPointsByArgument, pointIndex);
                const point = that._createPoint(pointDataItem, pointIndex, oldPoint);
                points.push(point)
            }
            return points
        }, []);
        for (const field in skippedFields) {
            if (skippedFields[field] === data.length) {
                that._incidentOccurred("W2002", [that.name, field])
            }
        }
        Object.keys(oldPointsByArgument).forEach(key => that._disposePoints(oldPointsByArgument[key]));
        that._points = points
    },
    _removeOldSegments: function() {
        const that = this;
        const startIndex = that._segments.length;
        (0, _iterator.each)(that._graphics.splice(startIndex, that._graphics.length) || [], (function(_, elem) {
            that._removeElement(elem)
        }));
        if (that._trackers) {
            (0, _iterator.each)(that._trackers.splice(startIndex, that._trackers.length) || [], (function(_, elem) {
                elem.remove()
            }))
        }
    },
    _prepareSegmentsPosition() {
        const points = this._points || [];
        const isCloseSegment = points[0] && points[0].hasValue() && this._options.closed;
        const segments = points.reduce((function(segments, p) {
            const segment = segments.at(-1);
            if (!p.translated) {
                p.setDefaultCoords()
            }
            if (p.hasValue() && p.hasCoords()) {
                segment.push(p)
            } else if (!p.hasValue() && segment.length) {
                segments.push([])
            }
            return segments
        }), [
            []
        ]);
        this._drawSegments(segments, isCloseSegment, false)
    },
    _drawElements(animationEnabled, firstDrawing) {
        const that = this;
        const points = that._points || [];
        const isCloseSegment = points[0] && points[0].hasValue() && that._options.closed;
        const groupForPoint = {
            markers: that._markersGroup,
            errorBars: that._errorBarGroup
        };
        that._drawnPoints = [];
        that._graphics = that._graphics || [];
        that._segments = [];
        const segments = points.reduce((function(segments, p) {
            const segment = segments.at(-1);
            if (p.hasValue() && p.hasCoords()) {
                that._drawPoint({
                    point: p,
                    groups: groupForPoint,
                    hasAnimation: animationEnabled,
                    firstDrawing: firstDrawing
                });
                segment.push(p)
            } else if (!p.hasValue()) {
                segment.length && segments.push([])
            } else {
                p.setInvisibility()
            }
            return segments
        }), [
            []
        ]);
        that._drawSegments(segments, isCloseSegment, animationEnabled);
        that._firstDrawing = !points.length;
        that._removeOldSegments();
        animationEnabled && that._animate(firstDrawing)
    },
    _drawSegments(segments, closeSegment, animationEnabled) {
        segments.forEach((segment, index) => {
            if (segment.length) {
                const lastSegment = closeSegment && index === segments.length - 1;
                this._drawSegment(segment, animationEnabled, index, lastSegment)
            }
        })
    },
    draw(animationEnabled, hideLayoutLabels, legendCallback) {
        const that = this;
        const firstDrawing = that._firstDrawing;
        that._legendCallback = legendCallback || that._legendCallback;
        if (!that._visible) {
            that._group.remove();
            return
        }
        that._appendInGroup();
        if (!that._isAllPointsTranslated) {
            that.prepareCoordinatesForPoints()
        }
        that._setGroupsSettings(animationEnabled, firstDrawing);
        !firstDrawing && !that._resetApplyingAnimation && that._prepareSegmentsPosition();
        that._drawElements(animationEnabled, firstDrawing);
        hideLayoutLabels && that.hideLabels();
        if (that.isSelected()) {
            that._changeStyle(that.lastSelectionMode, void 0, true)
        } else if (that.isHovered()) {
            that._changeStyle(that.lastHoverMode, void 0, true)
        } else {
            that._applyStyle(that._styles.normal)
        }
        that._isAllPointsTranslated = false;
        that._resetApplyingAnimation = false
    },
    _translatePoints() {
        var _this$_points;
        const points = null !== (_this$_points = this._points) && void 0 !== _this$_points ? _this$_points : [];
        points.forEach(p => {
            p.translate()
        })
    },
    prepareCoordinatesForPoints() {
        this._applyVisibleArea();
        this._translatePoints();
        this._isAllPointsTranslated = true
    },
    _setLabelGroupSettings: function(animationEnabled) {
        const settings = {
            class: "dxc-labels",
            "pointer-events": "none"
        };
        this._clipLabels && this._applyElementsClipRect(settings);
        this._applyClearingSettings(settings);
        animationEnabled && (settings.opacity = .001);
        this._labelsGroup.attr(settings).append(this._extGroups.labelsGroup)
    },
    _checkType: function(widgetType) {
        return !!seriesNS.mixins[widgetType][this.type]
    },
    _checkPolarBarType: function(widgetType, options) {
        return "polar" === widgetType && options.spiderWidget && -1 !== this.type.indexOf("bar")
    },
    _resetType: function(seriesType, widgetType) {
        let methodName;
        let methods;
        if (seriesType) {
            methods = seriesNS.mixins[widgetType][seriesType];
            for (methodName in methods) {
                delete this[methodName]
            }
        }
    },
    _setType: function(seriesType, widgetType) {
        let methodName;
        const methods = seriesNS.mixins[widgetType][seriesType];
        for (methodName in methods) {
            this[methodName] = methods[methodName]
        }
    },
    _setPointsView: function(view, target) {
        this.getPoints().forEach((function(point) {
            if (target !== point) {
                point.setView(view)
            }
        }))
    },
    _resetPointsView: function(view, target) {
        this.getPoints().forEach((function(point) {
            if (target !== point) {
                point.resetView(view)
            }
        }))
    },
    _resetNearestPoint: function() {
        this._nearestPoint && null !== this._nearestPoint.series && this._nearestPoint.resetView(HOVER);
        this._nearestPoint = null
    },
    _setSelectedState: function(mode) {
        const that = this;
        that.lastSelectionMode = (0, _utils.normalizeEnum)(mode || that._options.selectionMode);
        that.fullState = that.fullState | SELECTED_STATE;
        that._resetNearestPoint();
        that._changeStyle(that.lastSelectionMode);
        if ("none" !== that.lastSelectionMode && that.isHovered() && includePointsMode(that.lastHoverMode)) {
            that._resetPointsView(HOVER)
        }
    },
    _releaseSelectedState: function() {
        const that = this;
        that.fullState = that.fullState & ~SELECTED_STATE;
        that._changeStyle(that.lastSelectionMode, SELECTION);
        if ("none" !== that.lastSelectionMode && that.isHovered() && includePointsMode(that.lastHoverMode)) {
            that._setPointsView(HOVER)
        }
    },
    isFullStackedSeries: function() {
        return 0 === this.type.indexOf("fullstacked")
    },
    isStackedSeries: function() {
        return 0 === this.type.indexOf("stacked")
    },
    resetApplyingAnimation: function(isFirstDrawing) {
        this._resetApplyingAnimation = true;
        if (isFirstDrawing) {
            this._firstDrawing = true
        }
    },
    isFinancialSeries: function() {
        return "stock" === this.type || "candlestick" === this.type
    },
    _canChangeView: function() {
        return !this.isSelected() && "none" !== (0, _utils.normalizeEnum)(this._options.hoverMode)
    },
    _changeStyle: function(mode, resetView, skipPoints) {
        const that = this;
        let state = that.fullState;
        const styles = [NORMAL, HOVER, SELECTION, SELECTION];
        if ("none" === that.lastHoverMode) {
            state &= ~HOVER_STATE
        }
        if ("none" === that.lastSelectionMode) {
            state &= ~SELECTED_STATE
        }
        if (includePointsMode(mode) && !skipPoints) {
            if (!resetView) {
                that._setPointsView(styles[state])
            } else {
                that._resetPointsView(resetView)
            }
        }
        that._legendCallback([RESET_ITEM, APPLY_HOVER, APPLY_SELECTED, APPLY_SELECTED][state]);
        that._applyStyle(that._styles[styles[state]])
    },
    updateHover: function(x, y) {
        const that = this;
        const currentNearestPoint = that._nearestPoint;
        const point = that.isHovered() && that.lastHoverMode === NEAREST_POINT && that.getNeighborPoint(x, y);
        if (point !== currentNearestPoint && !(that.isSelected() && "none" !== that.lastSelectionMode)) {
            that._resetNearestPoint();
            if (point) {
                point.setView(HOVER);
                that._nearestPoint = point
            }
        }
    },
    _getMainAxisName: function() {
        return this._options.rotated ? "X" : "Y"
    },
    areLabelsVisible: function() {
        return !(0, _type.isDefined)(this._options.maxLabelCount) || this._points.length <= this._options.maxLabelCount
    },
    getLabelVisibility: function() {
        return this.areLabelsVisible() && this._options.label && this._options.label.visible
    },
    customizePoint: function(point, pointData) {
        const that = this;
        const options = that._options;
        const customizePoint = options.customizePoint;
        let customizeObject;
        let pointOptions;
        let customLabelOptions;
        let customOptions;
        const customizeLabel = options.customizeLabel;
        let useLabelCustomOptions;
        let usePointCustomOptions;
        if (customizeLabel && customizeLabel.call) {
            customizeObject = (0, _extend2.extend)({
                seriesName: that.name
            }, pointData);
            customizeObject.series = that;
            customLabelOptions = customizeLabel.call(customizeObject, customizeObject);
            useLabelCustomOptions = customLabelOptions && !(0, _type.isEmptyObject)(customLabelOptions);
            customLabelOptions = useLabelCustomOptions ? (0, _extend2.extend)(true, {}, options.label, customLabelOptions) : null
        }
        if (customizePoint && customizePoint.call) {
            customizeObject = customizeObject || (0, _extend2.extend)({
                seriesName: that.name
            }, pointData);
            customizeObject.series = that;
            customOptions = customizePoint.call(customizeObject, customizeObject);
            usePointCustomOptions = customOptions && !(0, _type.isEmptyObject)(customOptions)
        }
        if (useLabelCustomOptions || usePointCustomOptions) {
            pointOptions = that._parsePointOptions(that._preparePointOptions(customOptions), customLabelOptions || options.label, pointData, point);
            pointOptions.styles.useLabelCustomOptions = useLabelCustomOptions;
            pointOptions.styles.usePointCustomOptions = usePointCustomOptions;
            point.updateOptions(pointOptions)
        }
    },
    show: function() {
        if (!this._visible) {
            this._changeVisibility(true)
        }
    },
    hide: function() {
        if (this._visible) {
            this._changeVisibility(false)
        }
    },
    _changeVisibility: function(visibility) {
        this._visible = this._options.visible = visibility;
        this._updatePointsVisibility();
        this.hidePointTooltip();
        this._options.visibilityChanged(this)
    },
    _updatePointsVisibility: _common.noop,
    hideLabels: function() {
        (0, _iterator.each)(this._points, (function(_, point) {
            point._label.draw(false)
        }))
    },
    _turnOffHatching(hoverStyle, selectionStyle) {
        if (hoverStyle.hatching) {
            hoverStyle.hatching.direction = "none"
        }
        if (selectionStyle.hatching) {
            selectionStyle.hatching.direction = "none"
        }
    },
    _parsePointOptions: function(pointOptions, labelOptions, data, point) {
        const options = this._options;
        const styles = this._createPointStyles(pointOptions, data, point);
        const parsedOptions = (0, _extend2.extend)({}, pointOptions, {
            type: options.type,
            rotated: options.rotated,
            styles: styles,
            widgetType: options.widgetType,
            visibilityChanged: options.visibilityChanged
        });
        parsedOptions.label = getLabelOptions(labelOptions, styles.labelColor);
        if (this.areErrorBarsVisible()) {
            parsedOptions.errorBars = options.valueErrorBar
        }
        return parsedOptions
    },
    _preparePointOptions: function(customOptions) {
        const pointOptions = this._getOptionsForPoint();
        return customOptions ? mergePointOptions(pointOptions, customOptions) : pointOptions
    },
    _getMarkerGroupOptions: function() {
        return (0, _extend2.extend)(false, {}, this._getOptionsForPoint(), {
            hoverStyle: {},
            selectionStyle: {}
        })
    },
    _getAggregationMethod: function(isDiscrete, aggregateByCategory) {
        const options = this.getOptions().aggregation;
        const method = (0, _utils.normalizeEnum)(options.method);
        const customAggregator = "custom" === method && options.calculate;
        let aggregator;
        if (isDiscrete && !aggregateByCategory) {
            aggregator = _ref => {
                let {
                    data: data
                } = _ref;
                return data[0]
            }
        } else {
            aggregator = this._aggregators[method] || this._aggregators[this._defaultAggregator]
        }
        return customAggregator || aggregator
    },
    _resample(_ref2, data) {
        let {
            interval: interval,
            ticks: ticks,
            aggregateByCategory: aggregateByCategory
        } = _ref2;
        const that = this;
        const isDiscrete = that.argumentAxisType === DISCRETE || that.valueAxisType === DISCRETE;
        let dataIndex = 0;
        const dataSelector = this._getPointDataSelector();
        const options = that.getOptions();
        const addAggregatedData = (target, data, aggregationInfo) => {
            if (!data) {
                return
            }
            const processData = d => {
                const pointData = d && dataSelector(d, options);
                if (pointData && that._checkData(pointData)) {
                    pointData.aggregationInfo = aggregationInfo;
                    target.push(pointData)
                }
            };
            if (Array.isArray(data)) {
                data.forEach(processData)
            } else {
                processData(data)
            }
        };
        const aggregationMethod = this._getAggregationMethod(isDiscrete, aggregateByCategory);
        if (isDiscrete) {
            if (aggregateByCategory) {
                const categories = this.getArgumentAxis().getTranslator().getBusinessRange().categories;
                const groups = categories.reduce((g, category) => {
                    g[category.valueOf()] = [];
                    return g
                }, {});
                data.forEach(dataItem => {
                    groups[dataItem.argument.valueOf()].push(dataItem)
                });
                return categories.reduce((result, c) => {
                    addAggregatedData(result, aggregationMethod({
                        aggregationInterval: null,
                        intervalStart: c,
                        intervalEnd: c,
                        data: groups[c.valueOf()].map(getData)
                    }, that));
                    return result
                }, [])
            } else {
                return data.reduce((result, dataItem, index, data) => {
                    result[1].push(dataItem);
                    if (index === data.length - 1 || (index + 1) % interval === 0) {
                        const dataInInterval = result[1];
                        const aggregationInfo = {
                            aggregationInterval: interval,
                            data: dataInInterval.map(getData)
                        };
                        addAggregatedData(result[0], aggregationMethod(aggregationInfo, that));
                        result[1] = []
                    }
                    return result
                }, [
                    [],
                    []
                ])[0]
            }
        }
        const aggregatedData = [];
        if (1 === ticks.length) {
            const aggregationInfo = {
                intervalStart: ticks[0],
                intervalEnd: ticks[0],
                aggregationInterval: null,
                data: data.map(getData)
            };
            addAggregatedData(aggregatedData, aggregationMethod(aggregationInfo, that), aggregationInfo)
        } else {
            for (let i = 1; i < ticks.length; i++) {
                const intervalEnd = ticks[i];
                const intervalStart = ticks[i - 1];
                const dataInInterval = [];
                while (data[dataIndex] && data[dataIndex].argument < intervalEnd) {
                    if (data[dataIndex].argument >= intervalStart) {
                        dataInInterval.push(data[dataIndex])
                    }
                    dataIndex++
                }
                const aggregationInfo = {
                    intervalStart: intervalStart,
                    intervalEnd: intervalEnd,
                    aggregationInterval: interval,
                    data: dataInInterval.map(getData)
                };
                addAggregatedData(aggregatedData, aggregationMethod(aggregationInfo, that), aggregationInfo)
            }
        }
        that._endUpdateData();
        return aggregatedData
    },
    canRenderCompleteHandle: function() {
        const result = this._canRenderCompleteHandle;
        delete this._canRenderCompleteHandle;
        return !!result
    },
    isHovered: function() {
        return !!(1 & this.fullState)
    },
    isSelected: function() {
        return !!(2 & this.fullState)
    },
    isVisible: function() {
        return this._visible
    },
    getAllPoints: function() {
        this._createAllAggregatedPoints();
        return (this._points || []).slice()
    },
    getPointByPos: function(pos) {
        this._createAllAggregatedPoints();
        return (this._points || [])[pos]
    },
    getVisiblePoints: function() {
        return (this._drawnPoints || []).slice()
    },
    selectPoint: function(point) {
        if (!point.isSelected()) {
            setPointSelectedState(point, this._legendCallback);
            this._eventPipe({
                action: POINT_SELECT,
                target: point
            });
            this._eventTrigger("pointSelectionChanged", {
                target: point
            })
        }
    },
    deselectPoint: function(point) {
        if (point.isSelected()) {
            releasePointSelectedState(point, this._legendCallback);
            this._eventPipe({
                action: POINT_DESELECT,
                target: point
            });
            this._eventTrigger("pointSelectionChanged", {
                target: point
            })
        }
    },
    hover: function(mode) {
        const eventTrigger = this._eventTrigger;
        if (this.isHovered()) {
            return
        }
        this.lastHoverMode = (0, _utils.normalizeEnum)(mode || this._options.hoverMode);
        this.fullState = this.fullState | HOVER_STATE;
        this._changeStyle(this.lastHoverMode, void 0, this.isSelected() && "none" !== this.lastSelectionMode);
        eventTrigger("seriesHoverChanged", {
            target: this
        })
    },
    clearHover: function() {
        const eventTrigger = this._eventTrigger;
        if (!this.isHovered()) {
            return
        }
        this._resetNearestPoint();
        this.fullState = this.fullState & ~HOVER_STATE;
        this._changeStyle(this.lastHoverMode, HOVER, this.isSelected() && "none" !== this.lastSelectionMode);
        eventTrigger("seriesHoverChanged", {
            target: this
        })
    },
    hoverPoint: function(point) {
        const that = this;
        if (!point.isHovered()) {
            point.clearHover();
            setPointHoverState(point, that._legendCallback);
            that._canChangeView() && that._applyStyle(that._styles.hover);
            that._eventPipe({
                action: POINT_HOVER,
                target: point
            });
            that._eventTrigger("pointHoverChanged", {
                target: point
            })
        }
    },
    clearPointHover: function() {
        const that = this;
        that.getPoints().some((function(currentPoint) {
            if (currentPoint.isHovered()) {
                releasePointHoverState(currentPoint, that._legendCallback);
                that._canChangeView() && that._applyStyle(that._styles.normal);
                that._eventPipe({
                    action: "clearPointHover",
                    target: currentPoint
                });
                that._eventTrigger("pointHoverChanged", {
                    target: currentPoint
                });
                return true
            }
            return false
        }))
    },
    showPointTooltip: function(point) {
        triggerEvent(this._extGroups.seriesGroup, "showpointtooltip", point)
    },
    hidePointTooltip: function(point) {
        triggerEvent(this._extGroups.seriesGroup, "hidepointtooltip", point)
    },
    select: function() {
        const that = this;
        if (!that.isSelected()) {
            that._setSelectedState(that._options.selectionMode);
            that._eventPipe({
                action: SERIES_SELECT,
                target: that
            });
            that._group.toForeground();
            that._eventTrigger("seriesSelectionChanged", {
                target: that
            })
        }
    },
    clearSelection: function() {
        const that = this;
        if (that.isSelected()) {
            that._releaseSelectedState();
            that._eventTrigger("seriesSelectionChanged", {
                target: that
            })
        }
    },
    getPointsByArg: function(arg, skipPointsCreation) {
        const that = this;
        const argValue = arg.valueOf();
        let points = that.pointsByArgument[argValue];
        if (!points && !skipPointsCreation && that._createAllAggregatedPoints()) {
            points = that.pointsByArgument[argValue]
        }
        return points || []
    },
    _createAllAggregatedPoints: function() {
        if (this.useAggregation() && !this._useAllAggregatedPoints) {
            this.createPoints(true);
            return true
        }
        return false
    },
    getPointsByKeys: function(arg) {
        return this.getPointsByArg(arg)
    },
    notify: function(data) {
        const that = this;
        const action = data.action;
        const seriesModes = that._seriesModes;
        const target = data.target;
        const targetOptions = target.getOptions();
        const pointHoverMode = (0, _utils.normalizeEnum)(targetOptions.hoverMode);
        const selectionModeOfPoint = (0, _utils.normalizeEnum)(targetOptions.selectionMode);
        if (action === POINT_HOVER) {
            that._hoverPointHandler(target, pointHoverMode, data.notifyLegend)
        } else if ("clearPointHover" === action) {
            that._clearPointHoverHandler(target, pointHoverMode, data.notifyLegend)
        } else if (action === SERIES_SELECT) {
            target !== that && "single" === seriesModes.seriesSelectionMode && that.clearSelection()
        } else if (action === POINT_SELECT) {
            if ("single" === seriesModes.pointSelectionMode) {
                that.getPoints().some((function(currentPoint) {
                    if (currentPoint !== target && currentPoint.isSelected()) {
                        that.deselectPoint(currentPoint);
                        return true
                    }
                    return false
                }))
            }
            that._selectPointHandler(target, selectionModeOfPoint)
        } else if (action === POINT_DESELECT) {
            that._deselectPointHandler(target, selectionModeOfPoint)
        }
    },
    _selectPointHandler: function(target, mode) {
        const that = this;
        if ("allseriespoints" === mode) {
            target.series === that && that._setPointsView(SELECTION, target)
        } else if ("allargumentpoints" === mode) {
            that.getPointsByKeys(target.argument, target.argumentIndex).forEach((function(currentPoint) {
                currentPoint !== target && currentPoint.setView(SELECTION)
            }))
        }
    },
    _deselectPointHandler: function(target, mode) {
        if ("allseriespoints" === mode) {
            target.series === this && this._resetPointsView(SELECTION, target)
        } else if ("allargumentpoints" === mode) {
            this.getPointsByKeys(target.argument, target.argumentIndex).forEach((function(currentPoint) {
                currentPoint !== target && currentPoint.resetView(SELECTION)
            }))
        }
    },
    _hoverPointHandler: function(target, mode, notifyLegend) {
        const that = this;
        if (target.series !== that && "allargumentpoints" === mode) {
            that.getPointsByKeys(target.argument, target.argumentIndex).forEach((function(currentPoint) {
                currentPoint.setView(HOVER)
            }));
            notifyLegend && that._legendCallback(target)
        } else if ("allseriespoints" === mode && target.series === that) {
            that._setPointsView(HOVER, target)
        }
    },
    _clearPointHoverHandler: function(target, mode, notifyLegend) {
        const that = this;
        if ("allargumentpoints" === mode) {
            target.series !== that && that.getPointsByKeys(target.argument, target.argumentIndex).forEach((function(currentPoint) {
                currentPoint.resetView(HOVER)
            }));
            notifyLegend && that._legendCallback(target)
        } else if ("allseriespoints" === mode && target.series === that) {
            that._resetPointsView(HOVER, target)
        }
    },
    _deletePoints: function() {
        this._disposePoints(this._points);
        this._points = this._drawnPoints = null
    },
    _deleteTrackers: function() {
        (0, _iterator.each)(this._trackers || [], (function(_, tracker) {
            tracker.remove()
        }));
        this._trackersGroup && this._trackersGroup.dispose();
        this._trackers = this._trackersGroup = null
    },
    dispose: function() {
        this._deletePoints();
        this._group.dispose();
        this._labelsGroup && this._labelsGroup.dispose();
        this._errorBarGroup && this._errorBarGroup.dispose();
        this._deleteTrackers();
        this._group = this._extGroups = this._markersGroup = this._elementsGroup = this._bordersGroup = this._labelsGroup = this._errorBarGroup = this._graphics = this._rangeData = this._renderer = this._styles = this._options = this._pointOptions = this._drawnPoints = this.pointsByArgument = this._segments = this._prevSeries = null
    },
    correctPosition: _common.noop,
    drawTrackers: _common.noop,
    getNeighborPoint: _common.noop,
    areErrorBarsVisible: _common.noop,
    _getColorId: _common.noop,
    getMarginOptions: function() {
        return this._patchMarginOptions({
            percentStick: this.isFullStackedSeries()
        })
    },
    getColor: function() {
        return this.getLegendStyles().normal.fill
    },
    getOpacity: function() {
        return this._options.opacity
    },
    getStackName: function() {
        return this._stackName
    },
    getBarOverlapGroup: function() {
        return this._options.barOverlapGroup
    },
    getPointByCoord: function(x, y) {
        const point = this.getNeighborPoint(x, y);
        return null !== point && void 0 !== point && point.coordsIn(x, y) ? point : null
    },
    getValueAxis: function() {
        return this._valueAxis
    },
    getArgumentAxis: function() {
        return this._argumentAxis
    },
    getMarkersGroup() {
        return this._markersGroup
    },
    getRenderer() {
        return this._renderer
    },
    removePointElements() {
        if (this._markersGroup) {
            (0, _iterator.each)(this._points, (_, p) => p.deleteMarker());
            this._markersGroup.dispose();
            this._markersGroup = null
        }
    },
    removeGraphicElements() {
        const that = this;
        if (that._elementsGroup) {
            that._elementsGroup.dispose();
            that._elementsGroup = null
        }(0, _iterator.each)(that._graphics || [], (_, elem) => {
            that._removeElement(elem)
        });
        that._graphics = null
    },
    removeBordersGroup() {
        if (this._bordersGroup) {
            this._bordersGroup.dispose();
            this._bordersGroup = null
        }
    }
};
const mixins = seriesNS.mixins;
exports.mixins = mixins;
