/**
 * DevExtreme (cjs/__internal/viz/chart_components/m_base_chart.js)
 * Version: 24.1.7-build-24272-1937
 * Build date: Sat Sep 28 2024
 *
 * Copyright (c) 2012 - 2024 Developer Express Inc. ALL RIGHTS RESERVED
 * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
 */
"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.overlapping = exports.BaseChart = void 0;
var _common = require("../../../core/utils/common");
var _extend = require("../../../core/utils/extend");
var _iterator = require("../../../core/utils/iterator");
var _type = require("../../../core/utils/type");
var _events_engine = _interopRequireDefault(require("../../../events/core/events_engine"));
var _index = require("../../../events/utils/index");
var _layout_manager = require("../../../viz/chart_components/layout_manager");
var trackerModule = _interopRequireWildcard(require("../../../viz/chart_components/tracker"));
var _chart_theme_manager = require("../../../viz/components/chart_theme_manager");
var _data_validator = require("../../../viz/components/data_validator");
var _legend = require("../../../viz/components/legend");
var _data_source = require("../../../viz/core/data_source");
var _export = require("../../../viz/core/export");
var _loading_indicator = require("../../../viz/core/loading_indicator");
var _title = require("../../../viz/core/title");
var _tooltip = require("../../../viz/core/tooltip");
var _utils = require("../../../viz/core/utils");
var _base_series = require("../../../viz/series/base_series");
var _m_base_widget = _interopRequireDefault(require("../core/m_base_widget"));
var _rolling_stock = require("./rolling_stock");

function _getRequireWildcardCache(e) {
    if ("function" != typeof WeakMap) {
        return null
    }
    var r = new WeakMap,
        t = new WeakMap;
    return (_getRequireWildcardCache = function(e) {
        return e ? t : r
    })(e)
}

function _interopRequireWildcard(e, r) {
    if (!r && e && e.__esModule) {
        return e
    }
    if (null === e || "object" != typeof e && "function" != typeof e) {
        return {
            default: e
        }
    }
    var t = _getRequireWildcardCache(r);
    if (t && t.has(e)) {
        return t.get(e)
    }
    var n = {
            __proto__: null
        },
        a = Object.defineProperty && Object.getOwnPropertyDescriptor;
    for (var u in e) {
        if ("default" !== u && {}.hasOwnProperty.call(e, u)) {
            var i = a ? Object.getOwnPropertyDescriptor(e, u) : null;
            i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]
        }
    }
    return n.default = e, t && t.set(e, n), n
}

function _interopRequireDefault(obj) {
    return obj && obj.__esModule ? obj : {
        default: obj
    }
}
const {
    isArray: isArray
} = Array;
const REINIT_REFRESH_ACTION = "_reinit";
const REINIT_DATA_SOURCE_REFRESH_ACTION = "_updateDataSource";
const DATA_INIT_REFRESH_ACTION = "_dataInit";
const FORCE_RENDER_REFRESH_ACTION = "_forceRender";
const RESIZE_REFRESH_ACTION = "_resize";
const ACTIONS_BY_PRIORITY = ["_reinit", "_updateDataSource", "_dataInit", "_forceRender", "_resize"];
const DEFAULT_OPACITY = .3;
const REFRESH_SERIES_DATA_INIT_ACTION_OPTIONS = ["series", "commonSeriesSettings", "dataPrepareSettings", "seriesSelectionMode", "pointSelectionMode", "synchronizeMultiAxes", "resolveLabelsOverlapping"];
const REFRESH_SERIES_FAMILIES_ACTION_OPTIONS = ["minBubbleSize", "maxBubbleSize", "barGroupPadding", "barGroupWidth", "negativesAsZeroes", "negativesAsZeros"];
const FORCE_RENDER_REFRESH_ACTION_OPTIONS = ["adaptiveLayout", "crosshair", "resolveLabelOverlapping", "adjustOnZoom", "stickyHovering"];
const FONT = "font";

function checkHeightRollingStock(rollingStocks, stubCanvas) {
    const canvasSize = stubCanvas.end - stubCanvas.start;
    let size = 0;
    rollingStocks.forEach((rollingStock => {
        size += rollingStock.getBoundingRect().width
    }));
    while (canvasSize < size) {
        size -= findAndKillSmallValue(rollingStocks)
    }
}

function findAndKillSmallValue(rollingStocks) {
    const smallestObject = rollingStocks.reduce(((prev, rollingStock, index) => {
        if (!rollingStock) {
            return prev
        }
        const value = rollingStock.value();
        return value < prev.value ? {
            value: value,
            rollingStock: rollingStock,
            index: index
        } : prev
    }), {
        rollingStock: void 0,
        value: 1 / 0,
        index: void 0
    });
    smallestObject.rollingStock.getLabels()[0].draw(false);
    const {
        width: width
    } = smallestObject.rollingStock.getBoundingRect();
    rollingStocks[smallestObject.index] = null;
    return width
}

function checkStackOverlap(rollingStocks) {
    let i;
    let j;
    let iLength;
    let jLength;
    let overlap = false;
    for (i = 0, iLength = rollingStocks.length - 1; i < iLength; i++) {
        for (j = i + 1, jLength = rollingStocks.length; j < jLength; j++) {
            if (i !== j && checkStacksOverlapping(rollingStocks[i], rollingStocks[j], true)) {
                overlap = true;
                break
            }
        }
        if (overlap) {
            break
        }
    }
    return overlap
}

function resolveLabelOverlappingInOneDirection(points, canvas, isRotated, isInverted, shiftFunction) {
    let customSorting = arguments.length > 5 && void 0 !== arguments[5] ? arguments[5] : () => 0;
    const rollingStocks = [];
    const stubCanvas = {
        start: isRotated ? canvas.left : canvas.top,
        end: isRotated ? canvas.width - canvas.right : canvas.height - canvas.bottom
    };
    let hasStackedSeries = false;
    let sortRollingStocks;
    points.forEach((p => {
        if (!p) {
            return
        }
        hasStackedSeries = hasStackedSeries || p.series.isStackedSeries() || p.series.isFullStackedSeries();
        p.getLabels().forEach((l => {
            if (l.isVisible()) {
                rollingStocks.push(new _rolling_stock.RollingStock(l, isRotated, shiftFunction))
            }
        }))
    }));
    if (hasStackedSeries) {
        if (Number(!isRotated) ^ Number(isInverted)) {
            rollingStocks.reverse()
        }
        sortRollingStocks = isInverted ? rollingStocks : sortRollingStocksByValue(rollingStocks)
    } else {
        const rollingStocksTmp = rollingStocks.slice();
        sortRollingStocks = rollingStocks.sort(((a, b) => customSorting(a, b) || a.getInitialPosition() - b.getInitialPosition() || rollingStocksTmp.indexOf(a) - rollingStocksTmp.indexOf(b)))
    }
    if (!checkStackOverlap(sortRollingStocks)) {
        return false
    }
    checkHeightRollingStock(sortRollingStocks, stubCanvas);
    prepareOverlapStacks(sortRollingStocks);
    sortRollingStocks.reverse();
    moveRollingStock(sortRollingStocks, stubCanvas);
    return true
}

function checkStacksOverlapping(firstRolling, secondRolling, inTwoSides) {
    if (!firstRolling || !secondRolling) {
        return
    }
    const firstRect = firstRolling.getBoundingRect();
    const secondRect = secondRolling.getBoundingRect();
    const oppositeOverlapping = inTwoSides ? firstRect.oppositeStart <= secondRect.oppositeStart && firstRect.oppositeEnd > secondRect.oppositeStart || secondRect.oppositeStart <= firstRect.oppositeStart && secondRect.oppositeEnd > firstRect.oppositeStart : true;
    return firstRect.end > secondRect.start && oppositeOverlapping
}

function sortRollingStocksByValue(rollingStocks) {
    const positiveRollingStocks = [];
    const negativeRollingStocks = [];
    rollingStocks.forEach((stock => {
        if (stock.value() > 0) {
            positiveRollingStocks.push(stock)
        } else {
            negativeRollingStocks.unshift(stock)
        }
    }));
    return positiveRollingStocks.concat(negativeRollingStocks)
}

function prepareOverlapStacks(rollingStocks) {
    let root;
    for (let i = 0; i < rollingStocks.length - 1; i += 1) {
        const currentRollingStock = root || rollingStocks[i];
        if (checkStacksOverlapping(currentRollingStock, rollingStocks[i + 1])) {
            currentRollingStock.toChain(rollingStocks[i + 1]);
            rollingStocks[i + 1] = null;
            root = currentRollingStock
        } else {
            root = rollingStocks[i + 1] || currentRollingStock
        }
    }
}

function rollingStocksIsOut(rollingStock, canvas) {
    return rollingStock.getBoundingRect().end > canvas.end
}

function moveRollingStock(rollingStocks, canvas) {
    for (let i = 0; i < rollingStocks.length; i += 1) {
        const currentRollingStock = rollingStocks[i];
        let shouldSetCanvas = true;
        if (null !== currentRollingStock && rollingStocksIsOut(currentRollingStock, canvas)) {
            const currentBBox = currentRollingStock.getBoundingRect();
            for (let j = i + 1; j < rollingStocks.length; j += 1) {
                const nextRollingStock = rollingStocks[j];
                if (nextRollingStock) {
                    const nextBBox = nextRollingStock.getBoundingRect();
                    if (nextBBox.end > currentBBox.start - (currentBBox.end - canvas.end)) {
                        nextRollingStock.toChain(currentRollingStock);
                        shouldSetCanvas = false;
                        break
                    }
                }
            }
        }
        if (shouldSetCanvas) {
            null === currentRollingStock || void 0 === currentRollingStock || currentRollingStock.setRollingStockInCanvas(canvas)
        }
    }
}

function getLegendFields(name) {
    return {
        nameField: `${name}Name`,
        colorField: `${name}Color`,
        indexField: `${name}Index`
    }
}

function getLegendSettings(legendDataField) {
    const formatObjectFields = getLegendFields(legendDataField);
    return {
        getFormatObject(data) {
            const res = {};
            res[formatObjectFields.indexField] = data.id;
            res[formatObjectFields.colorField] = data.states.normal.fill;
            res[formatObjectFields.nameField] = data.text;
            return res
        },
        textField: formatObjectFields.nameField
    }
}

function checkOverlapping(firstRect, secondRect) {
    return (firstRect.x <= secondRect.x && secondRect.x <= firstRect.x + firstRect.width || firstRect.x >= secondRect.x && firstRect.x <= secondRect.x + secondRect.width) && (firstRect.y <= secondRect.y && secondRect.y <= firstRect.y + firstRect.height || firstRect.y >= secondRect.y && firstRect.y <= secondRect.y + secondRect.height)
}
const overlapping = exports.overlapping = {
    resolveLabelOverlappingInOneDirection: resolveLabelOverlappingInOneDirection
};
const BaseChart = exports.BaseChart = _m_base_widget.default.inherit({
    _eventsMap: {
        onSeriesClick: {
            name: "seriesClick"
        },
        onPointClick: {
            name: "pointClick"
        },
        onArgumentAxisClick: {
            name: "argumentAxisClick"
        },
        onLegendClick: {
            name: "legendClick"
        },
        onSeriesSelectionChanged: {
            name: "seriesSelectionChanged"
        },
        onPointSelectionChanged: {
            name: "pointSelectionChanged"
        },
        onSeriesHoverChanged: {
            name: "seriesHoverChanged"
        },
        onPointHoverChanged: {
            name: "pointHoverChanged"
        },
        onDone: {
            name: "done",
            actionSettings: {
                excludeValidators: ["disabled"]
            }
        },
        onZoomStart: {
            name: "zoomStart"
        },
        onZoomEnd: {
            name: "zoomEnd"
        }
    },
    _fontFields: [`legend.${FONT}`, `legend.title.${FONT}`, `legend.title.subtitle.${FONT}`, `commonSeriesSettings.label.${FONT}`],
    _rootClassPrefix: "dxc",
    _rootClass: "dxc-chart",
    _initialChanges: ["INIT"],
    _themeDependentChanges: ["REFRESH_SERIES_REINIT"],
    _getThemeManagerOptions() {
        const themeOptions = this.callBase.apply(this, arguments);
        themeOptions.options = this.option();
        return themeOptions
    },
    _createThemeManager() {
        const chartOption = this.option();
        const themeManager = new _chart_theme_manager.ThemeManager(this._getThemeManagerOptions());
        themeManager.setTheme(chartOption.theme, chartOption.rtlEnabled);
        return themeManager
    },
    _initCore() {
        this._canvasClipRect = this._renderer.clipRect();
        this._createHtmlStructure();
        this._createLegend();
        this._createTracker();
        this._needHandleRenderComplete = true;
        this.layoutManager = new _layout_manager.LayoutManager;
        this._createScrollBar();
        _events_engine.default.on(this._$element, "contextmenu", (event => {
            if ((0, _index.isTouchEvent)(event) || (0, _index.isPointerEvent)(event)) {
                event.preventDefault()
            }
        }));
        _events_engine.default.on(this._$element, "MSHoldVisual", (event => {
            event.preventDefault()
        }))
    },
    _getLayoutItems: _common.noop,
    _layoutManagerOptions() {
        return this._themeManager.getOptions("adaptiveLayout")
    },
    _reinit() {
        (0, _utils.setCanvasValues)(this._canvas);
        this._reinitAxes();
        this._requestChange(["DATA_SOURCE", "DATA_INIT", "CORRECT_AXIS", "FULL_RENDER"])
    },
    _correctAxes: _common.noop,
    _createHtmlStructure() {
        const renderer = this._renderer;
        const {
            root: root
        } = renderer;
        const createConstantLinesGroup = function() {
            return renderer.g().attr({
                class: "dxc-constant-lines-group"
            }).linkOn(root, "constant-lines")
        };
        this._constantLinesGroup = {
            dispose() {
                this.under.dispose();
                this.above.dispose()
            },
            linkOff() {
                this.under.linkOff();
                this.above.linkOff()
            },
            clear() {
                this.under.linkRemove().clear();
                this.above.linkRemove().clear()
            },
            linkAppend() {
                this.under.linkAppend();
                this.above.linkAppend()
            }
        };
        this._labelsAxesGroup = renderer.g().attr({
            class: "dxc-elements-axes-group"
        });
        const appendLabelsAxesGroup = () => {
            this._labelsAxesGroup.linkOn(root, "elements")
        };
        this._backgroundRect = renderer.rect().attr({
            fill: "gray",
            opacity: 1e-4
        }).append(root);
        this._panesBackgroundGroup = renderer.g().attr({
            class: "dxc-background"
        }).append(root);
        this._stripsGroup = renderer.g().attr({
            class: "dxc-strips-group"
        }).linkOn(root, "strips");
        this._gridGroup = renderer.g().attr({
            class: "dxc-grids-group"
        }).linkOn(root, "grids");
        this._panesBorderGroup = renderer.g().attr({
            class: "dxc-border"
        }).linkOn(root, "border");
        this._axesGroup = renderer.g().attr({
            class: "dxc-axes-group"
        }).linkOn(root, "axes");
        this._executeAppendBeforeSeries(appendLabelsAxesGroup);
        this._stripLabelAxesGroup = renderer.g().attr({
            class: "dxc-strips-labels-group"
        }).linkOn(root, "strips-labels");
        this._constantLinesGroup.under = createConstantLinesGroup();
        this._seriesGroup = renderer.g().attr({
            class: "dxc-series-group"
        }).linkOn(root, "series");
        this._executeAppendAfterSeries(appendLabelsAxesGroup);
        this._constantLinesGroup.above = createConstantLinesGroup();
        this._scaleBreaksGroup = renderer.g().attr({
            class: "dxc-scale-breaks"
        }).linkOn(root, "scale-breaks");
        this._labelsGroup = renderer.g().attr({
            class: "dxc-labels-group"
        }).linkOn(root, "labels");
        this._crosshairCursorGroup = renderer.g().attr({
            class: "dxc-crosshair-cursor"
        }).linkOn(root, "crosshair");
        this._legendGroup = renderer.g().attr({
            class: "dxc-legend",
            "clip-path": this._getCanvasClipRectID()
        }).linkOn(root, "legend").linkAppend(root).enableLinks();
        this._scrollBarGroup = renderer.g().attr({
            class: "dxc-scroll-bar"
        }).linkOn(root, "scroll-bar")
    },
    _executeAppendBeforeSeries() {},
    _executeAppendAfterSeries() {},
    _disposeObjectsInArray(propName, fieldNames) {
        (this[propName] || []).forEach((item => {
            if (fieldNames && item) {
                fieldNames.forEach((field => {
                    var _item$field;
                    null === (_item$field = item[field]) || void 0 === _item$field || _item$field.dispose()
                }))
            } else {
                null === item || void 0 === item || item.dispose()
            }
        }));
        this[propName] = null
    },
    _disposeCore() {
        const disposeObject = propName => {
            if (this[propName]) {
                this[propName].dispose();
                this[propName] = null
            }
        };
        const unlinkGroup = name => {
            this[name].linkOff()
        };
        const disposeObjectsInArray = this._disposeObjectsInArray;
        this._renderer.stopAllAnimations();
        disposeObjectsInArray.call(this, "series");
        disposeObject("_tracker");
        disposeObject("_crosshair");
        this.layoutManager = this._userOptions = this._canvas = this._groupsData = null;
        unlinkGroup("_stripsGroup");
        unlinkGroup("_gridGroup");
        unlinkGroup("_axesGroup");
        unlinkGroup("_constantLinesGroup");
        unlinkGroup("_stripLabelAxesGroup");
        unlinkGroup("_panesBorderGroup");
        unlinkGroup("_seriesGroup");
        unlinkGroup("_labelsGroup");
        unlinkGroup("_crosshairCursorGroup");
        unlinkGroup("_legendGroup");
        unlinkGroup("_scrollBarGroup");
        unlinkGroup("_scaleBreaksGroup");
        disposeObject("_canvasClipRect");
        disposeObject("_panesBackgroundGroup");
        disposeObject("_backgroundRect");
        disposeObject("_stripsGroup");
        disposeObject("_gridGroup");
        disposeObject("_axesGroup");
        disposeObject("_constantLinesGroup");
        disposeObject("_stripLabelAxesGroup");
        disposeObject("_panesBorderGroup");
        disposeObject("_seriesGroup");
        disposeObject("_labelsGroup");
        disposeObject("_crosshairCursorGroup");
        disposeObject("_legendGroup");
        disposeObject("_scrollBarGroup");
        disposeObject("_scaleBreaksGroup")
    },
    _getAnimationOptions() {
        return this._themeManager.getOptions("animation")
    },
    _getDefaultSize: () => ({
        width: 400,
        height: 400
    }),
    _getOption(name) {
        return this._themeManager.getOptions(name)
    },
    _applySize(rect) {
        this._rect = rect.slice();
        if (!this._changes.has("FULL_RENDER")) {
            this._processRefreshData("_resize")
        }
    },
    _resize() {
        this._doRender(this.__renderOptions || {
            animate: false,
            isResize: true
        })
    },
    _trackerType: "ChartTracker",
    _createTracker() {
        this._tracker = new trackerModule[this._trackerType]({
            seriesGroup: this._seriesGroup,
            renderer: this._renderer,
            tooltip: this._tooltip,
            legend: this._legend,
            eventTrigger: this._eventTrigger
        })
    },
    _getTrackerSettings() {
        return (0, _extend.extend)({
            chart: this
        }, this._getSelectionModes())
    },
    _getSelectionModes() {
        const themeManager = this._themeManager;
        return {
            seriesSelectionMode: themeManager.getOptions("seriesSelectionMode"),
            pointSelectionMode: themeManager.getOptions("pointSelectionMode")
        }
    },
    _updateTracker(trackerCanvases) {
        this._tracker.update(this._getTrackerSettings());
        this._tracker.setCanvases({
            left: 0,
            right: this._canvas.width,
            top: 0,
            bottom: this._canvas.height
        }, trackerCanvases)
    },
    _createCanvasFromRect(rect) {
        const currentCanvas = this._canvas;
        return (0, _utils.setCanvasValues)({
            left: rect[0],
            top: rect[1],
            right: currentCanvas.width - rect[2],
            bottom: currentCanvas.height - rect[3],
            width: currentCanvas.width,
            height: currentCanvas.height
        })
    },
    _doRender(_options) {
        if (0 === this._canvas.width && 0 === this._canvas.height) {
            return
        }
        this._resetIsReady();
        const drawOptions = this._prepareDrawOptions(_options);
        const {
            recreateCanvas: recreateCanvas
        } = drawOptions;
        this._preserveOriginalCanvas();
        if (recreateCanvas) {
            this.__currentCanvas = this._canvas
        } else {
            this._canvas = this.__currentCanvas
        }
        recreateCanvas && this._updateCanvasClipRect(this._canvas);
        this._canvas = this._createCanvasFromRect(this._rect);
        this._renderer.stopAllAnimations(true);
        this._cleanGroups();
        const startTime = new Date;
        this._renderElements(drawOptions);
        this._lastRenderingTime = Number(new Date) - Number(startTime)
    },
    _preserveOriginalCanvas() {
        this.__originalCanvas = this._canvas;
        this._canvas = (0, _extend.extend)({}, this._canvas)
    },
    _layoutAxes: _common.noop,
    _renderElements(drawOptions) {
        const preparedOptions = this._prepareToRender(drawOptions);
        const isRotated = this._isRotated();
        const isLegendInside = this._isLegendInside();
        const trackerCanvases = [];
        (0, _extend.extend)({}, this._canvas);
        let argBusinessRange;
        let zoomMinArg;
        let zoomMaxArg;
        this._renderer.lock();
        if (drawOptions.drawLegend && this._legend) {
            this._legendGroup.linkAppend()
        }
        this.layoutManager.setOptions(this._layoutManagerOptions());
        const layoutTargets = this._getLayoutTargets();
        this._layoutAxes((needSpace => {
            const axisDrawOptions = needSpace ? (0, _extend.extend)({}, drawOptions, {
                animate: false,
                recreateCanvas: true
            }) : drawOptions;
            const canvas = this._renderAxes(axisDrawOptions, preparedOptions);
            this._shrinkAxes(needSpace, canvas)
        }));
        this._applyClipRects(preparedOptions);
        this._appendSeriesGroups();
        this._createCrosshairCursor();
        layoutTargets.forEach((_ref => {
            let {
                canvas: canvas
            } = _ref;
            trackerCanvases.push({
                left: canvas.left,
                right: canvas.width - canvas.right,
                top: canvas.top,
                bottom: canvas.height - canvas.bottom
            })
        }));
        if (this._scrollBar) {
            argBusinessRange = this._argumentAxes[0].getTranslator().getBusinessRange();
            if ("discrete" === argBusinessRange.axisType && argBusinessRange.categories && argBusinessRange.categories.length <= 1 || "discrete" !== argBusinessRange.axisType && argBusinessRange.min === argBusinessRange.max) {
                zoomMinArg = zoomMaxArg = void 0
            } else {
                zoomMinArg = argBusinessRange.minVisible;
                zoomMaxArg = argBusinessRange.maxVisible
            }
            this._scrollBar.init(argBusinessRange, !this._argumentAxes[0].getOptions().valueMarginsEnabled).setPosition(zoomMinArg, zoomMaxArg)
        }
        this._updateTracker(trackerCanvases);
        this._updateLegendPosition(drawOptions, isLegendInside);
        this._applyPointMarkersAutoHiding();
        this._renderSeries(drawOptions, isRotated, isLegendInside);
        this._renderGraphicObjects();
        this._renderer.unlock()
    },
    _updateLegendPosition: _common.noop,
    _createCrosshairCursor: _common.noop,
    _appendSeriesGroups() {
        this._seriesGroup.linkAppend();
        this._labelsGroup.linkAppend();
        this._appendAdditionalSeriesGroups()
    },
    _renderSeries(drawOptions, isRotated, isLegendInside) {
        this._calculateSeriesLayout(drawOptions, isRotated);
        this._renderSeriesElements(drawOptions, isLegendInside)
    },
    _calculateSeriesLayout(drawOptions, isRotated) {
        drawOptions.hideLayoutLabels = this.layoutManager.needMoreSpaceForPanesCanvas(this._getLayoutTargets(), isRotated) && !this._themeManager.getOptions("adaptiveLayout").keepLabels;
        this._updateSeriesDimensions(drawOptions)
    },
    _getArgFilter: () => () => true,
    _getValFilter: () => () => true,
    _getPointsToAnimation(series) {
        const argViewPortFilter = this._getArgFilter();
        return series.map((s => {
            const valViewPortFilter = this._getValFilter(s);
            return s.getPoints().filter((p => p.getOptions().visible && argViewPortFilter(p.argument) && (valViewPortFilter(p.getMinValue(true)) || valViewPortFilter(p.getMaxValue(true))))).length
        }))
    },
    _renderSeriesElements(drawOptions, isLegendInside) {
        const {
            series: series
        } = this;
        const resolveLabelOverlapping = this._themeManager.getOptions("resolveLabelOverlapping");
        const pointsToAnimation = this._getPointsToAnimation(series);
        series.forEach(((singleSeries, index) => {
            this._applyExtraSettings(singleSeries, drawOptions);
            const animationEnabled = drawOptions.animate && pointsToAnimation[index] <= drawOptions.animationPointsLimit && this._renderer.animationEnabled();
            singleSeries.draw(animationEnabled, drawOptions.hideLayoutLabels, this._getLegendCallBack(singleSeries))
        }));
        if ("none" === resolveLabelOverlapping) {
            this._adjustSeriesLabels(false)
        } else {
            this._locateLabels(resolveLabelOverlapping)
        }
        this._renderTrackers(isLegendInside);
        this._tracker.repairTooltip();
        this._renderExtraElements();
        this._clearCanvas();
        this._seriesElementsDrawn = true
    },
    _changesApplied() {
        if (this._seriesElementsDrawn) {
            this._seriesElementsDrawn = false;
            this._drawn();
            this._renderCompleteHandler()
        }
    },
    _locateLabels(resolveLabelOverlapping) {
        this._resolveLabelOverlapping(resolveLabelOverlapping)
    },
    _renderExtraElements() {},
    _clearCanvas() {
        this._canvas = this.__originalCanvas
    },
    _resolveLabelOverlapping(resolveLabelOverlapping) {
        let func;
        switch (resolveLabelOverlapping) {
            case "stack":
                func = this._resolveLabelOverlappingStack;
                break;
            case "hide":
                func = this._resolveLabelOverlappingHide;
                break;
            case "shift":
                func = this._resolveLabelOverlappingShift
        }
        return (0, _type.isFunction)(func) && func.call(this)
    },
    _getVisibleSeries() {
        return (0, _common.grep)(this.getAllSeries(), (series => series.isVisible()))
    },
    _resolveLabelOverlappingHide() {
        const labels = [];
        let currentLabel;
        let nextLabel;
        let currentLabelRect;
        let nextLabelRect;
        let i;
        let j;
        let points;
        const series = this._getVisibleSeries();
        for (i = 0; i < series.length; i++) {
            points = series[i].getVisiblePoints();
            for (j = 0; j < points.length; j++) {
                labels.push.apply(labels, points[j].getLabels())
            }
        }
        for (i = 0; i < labels.length; i++) {
            currentLabel = labels[i];
            if (!currentLabel.isVisible()) {
                continue
            }
            currentLabelRect = currentLabel.getBoundingRect();
            for (j = i + 1; j < labels.length; j++) {
                nextLabel = labels[j];
                nextLabelRect = nextLabel.getBoundingRect();
                if (checkOverlapping(currentLabelRect, nextLabelRect)) {
                    nextLabel.draw(false)
                }
            }
        }
    },
    _cleanGroups() {
        this._stripsGroup.linkRemove().clear();
        this._gridGroup.linkRemove().clear();
        this._axesGroup.linkRemove().clear();
        this._constantLinesGroup.clear();
        this._stripLabelAxesGroup.linkRemove().clear();
        this._labelsGroup.linkRemove().clear();
        this._crosshairCursorGroup.linkRemove().clear();
        this._scaleBreaksGroup.linkRemove().clear()
    },
    _allowLegendInsidePosition: () => false,
    _createLegend() {
        const legendSettings = getLegendSettings(this._legendDataField);
        this._legend = new _legend.Legend({
            renderer: this._renderer,
            widget: this,
            group: this._legendGroup,
            backgroundClass: "dxc-border",
            itemGroupClass: "dxc-item",
            titleGroupClass: "dxc-title",
            textField: legendSettings.textField,
            getFormatObject: legendSettings.getFormatObject,
            allowInsidePosition: this._allowLegendInsidePosition()
        });
        this._updateLegend();
        this._layout.add(this._legend)
    },
    _updateLegend() {
        const themeManager = this._themeManager;
        const legendOptions = themeManager.getOptions("legend");
        const legendData = this._getLegendData();
        legendOptions.containerBackgroundColor = themeManager.getOptions("containerBackgroundColor");
        legendOptions._incidentOccurred = this._incidentOccurred;
        this._legend.update(legendData, legendOptions, themeManager.theme("legend").title);
        this._change(["LAYOUT"])
    },
    _prepareDrawOptions(drawOptions) {
        const animationOptions = this._getAnimationOptions();
        const options = (0, _extend.extend)({}, {
            force: false,
            adjustAxes: true,
            drawLegend: true,
            drawTitle: true,
            animate: animationOptions.enabled,
            animationPointsLimit: animationOptions.maxPointCountSupported
        }, drawOptions, this.__renderOptions);
        if (!(0, _type.isDefined)(options.recreateCanvas)) {
            options.recreateCanvas = options.adjustAxes && options.drawLegend && options.drawTitle
        }
        return options
    },
    _processRefreshData(newRefreshAction) {
        const currentRefreshActionPosition = ACTIONS_BY_PRIORITY.indexOf(this._currentRefreshData);
        const newRefreshActionPosition = ACTIONS_BY_PRIORITY.indexOf(newRefreshAction);
        if (!this._currentRefreshData || currentRefreshActionPosition >= 0 && newRefreshActionPosition < currentRefreshActionPosition) {
            this._currentRefreshData = newRefreshAction
        }
        this._requestChange(["REFRESH"])
    },
    _getLegendData() {
        return (0, _utils.map)(this._getLegendTargets(), (item => {
            const {
                legendData: legendData
            } = item;
            const style = item.getLegendStyles;
            let {
                opacity: opacity
            } = style.normal;
            if (!item.visible) {
                if (!(0, _type.isDefined)(opacity) || opacity > .3) {
                    opacity = .3
                }
                legendData.textOpacity = .3
            }
            const opacityStyle = {
                opacity: opacity
            };
            legendData.states = {
                hover: (0, _extend.extend)({}, style.hover, opacityStyle),
                selection: (0, _extend.extend)({}, style.selection, opacityStyle),
                normal: (0, _extend.extend)({}, style.normal, opacityStyle)
            };
            return legendData
        }))
    },
    _getLegendOptions(item) {
        return {
            legendData: {
                text: item[this._legendItemTextField],
                id: item.index,
                visible: true
            },
            getLegendStyles: item.getLegendStyles(),
            visible: item.isVisible()
        }
    },
    _disposeSeries(seriesIndex) {
        var _this$series;
        if (this.series) {
            if ((0, _type.isDefined)(seriesIndex)) {
                this.series[seriesIndex].dispose();
                this.series.splice(seriesIndex, 1)
            } else {
                this.series.forEach((s => s.dispose()));
                this.series.length = 0
            }
        }
        if (!(null !== (_this$series = this.series) && void 0 !== _this$series && _this$series.length)) {
            this.series = []
        }
    },
    _disposeSeriesFamilies() {
        (this.seriesFamilies || []).forEach((family => {
            family.dispose()
        }));
        this.seriesFamilies = null;
        this._needHandleRenderComplete = true
    },
    _optionChanged(arg) {
        this._themeManager.resetOptions(arg.name);
        this.callBase.apply(this, arguments)
    },
    _applyChanges() {
        this._themeManager.update(this._options.silent());
        this.callBase(...arguments)
    },
    _optionChangesMap: {
        animation: "ANIMATION",
        dataSource: "DATA_SOURCE",
        palette: "PALETTE",
        paletteExtensionMode: "PALETTE",
        legend: "FORCE_DATA_INIT",
        seriesTemplate: "FORCE_DATA_INIT",
        export: "FORCE_RENDER",
        valueAxis: "AXES_AND_PANES",
        argumentAxis: "AXES_AND_PANES",
        commonAxisSettings: "AXES_AND_PANES",
        panes: "AXES_AND_PANES",
        commonPaneSettings: "AXES_AND_PANES",
        defaultPane: "AXES_AND_PANES",
        containerBackgroundColor: "AXES_AND_PANES",
        rotated: "ROTATED",
        autoHidePointMarkers: "REFRESH_SERIES_REINIT",
        customizePoint: "REFRESH_SERIES_REINIT",
        customizeLabel: "REFRESH_SERIES_REINIT",
        scrollBar: "SCROLL_BAR"
    },
    _optionChangesOrder: ["ROTATED", "PALETTE", "REFRESH_SERIES_REINIT", "USE_SPIDER_WEB", "AXES_AND_PANES", "INIT", "REINIT", "DATA_SOURCE", "REFRESH_SERIES_DATA_INIT", "DATA_INIT", "FORCE_DATA_INIT", "REFRESH_AXES", "CORRECT_AXIS"],
    _customChangesOrder: ["ANIMATION", "REFRESH_SERIES_FAMILIES", "FORCE_FIRST_DRAWING", "FORCE_DRAWING", "FORCE_RENDER", "VISUAL_RANGE", "SCROLL_BAR", "REINIT", "REFRESH", "FULL_RENDER"],
    _change_ANIMATION() {
        this._renderer.updateAnimationOptions(this._getAnimationOptions())
    },
    _change_DATA_SOURCE() {
        this._needHandleRenderComplete = true;
        this._updateDataSource()
    },
    _change_PALETTE() {
        this._themeManager.updatePalette();
        this._refreshSeries("DATA_INIT")
    },
    _change_REFRESH_SERIES_DATA_INIT() {
        this._refreshSeries("DATA_INIT")
    },
    _change_DATA_INIT() {
        if ((!this.series || this.needToPopulateSeries) && !this._changes.has("FORCE_DATA_INIT")) {
            this._dataInit()
        }
    },
    _change_FORCE_DATA_INIT() {
        this._dataInit()
    },
    _change_REFRESH_SERIES_FAMILIES() {
        this._processSeriesFamilies();
        this._populateBusinessRange();
        this._processRefreshData("_forceRender")
    },
    _change_FORCE_RENDER() {
        this._processRefreshData("_forceRender")
    },
    _change_AXES_AND_PANES() {
        this._refreshSeries("INIT")
    },
    _change_ROTATED() {
        this._createScrollBar();
        this._refreshSeries("INIT")
    },
    _change_REFRESH_SERIES_REINIT() {
        this._refreshSeries("INIT")
    },
    _change_REFRESH_AXES() {
        (0, _utils.setCanvasValues)(this._canvas);
        this._reinitAxes();
        this._requestChange(["CORRECT_AXIS", "FULL_RENDER"])
    },
    _change_SCROLL_BAR() {
        this._createScrollBar();
        this._processRefreshData("_forceRender")
    },
    _change_REINIT() {
        this._processRefreshData("_reinit")
    },
    _change_FORCE_DRAWING() {
        this._resetComponentsAnimation()
    },
    _change_FORCE_FIRST_DRAWING() {
        this._resetComponentsAnimation(true)
    },
    _resetComponentsAnimation(isFirstDrawing) {
        this.series.forEach((s => {
            s.resetApplyingAnimation(isFirstDrawing)
        }));
        this._resetAxesAnimation(isFirstDrawing)
    },
    _resetAxesAnimation: _common.noop,
    _refreshSeries(actionName) {
        this.needToPopulateSeries = true;
        this._requestChange([actionName])
    },
    _change_CORRECT_AXIS() {
        this._correctAxes()
    },
    _doRefresh() {
        const methodName = this._currentRefreshData;
        if (methodName) {
            this._currentRefreshData = null;
            this._renderer.stopAllAnimations(true);
            this[methodName]()
        }
    },
    _updateCanvasClipRect(canvas) {
        const width = Math.max(canvas.width - canvas.left - canvas.right, 0);
        const height = Math.max(canvas.height - canvas.top - canvas.bottom, 0);
        this._canvasClipRect.attr({
            x: canvas.left,
            y: canvas.top,
            width: width,
            height: height
        });
        this._backgroundRect.attr({
            x: canvas.left,
            y: canvas.top,
            width: width,
            height: height
        })
    },
    _getCanvasClipRectID() {
        return this._canvasClipRect.id
    },
    _dataSourceChangedHandler() {
        if (this._changes.has("INIT")) {
            this._requestChange(["DATA_INIT"])
        } else {
            this._requestChange(["FORCE_DATA_INIT"])
        }
    },
    _dataInit() {
        this._dataSpecificInit(true)
    },
    _processSingleSeries(singleSeries) {
        singleSeries.createPoints(false)
    },
    _handleSeriesDataUpdated() {
        if (this._getVisibleSeries().some((s => s.useAggregation()))) {
            this._populateMarginOptions()
        }
        this.series.forEach((s => this._processSingleSeries(s)), this)
    },
    _dataSpecificInit(needRedraw) {
        if (!this.series || this.needToPopulateSeries) {
            this.series = this._populateSeries()
        }
        this._repopulateSeries();
        this._seriesPopulatedHandlerCore();
        this._populateBusinessRange();
        this._tracker.updateSeries(this.series, this._changes.has("INIT"));
        this._updateLegend();
        if (needRedraw) {
            this._requestChange(["FULL_RENDER"])
        }
    },
    _forceRender() {
        this._doRender({
            force: true
        })
    },
    _repopulateSeries() {
        const themeManager = this._themeManager;
        const data = this._dataSourceItems();
        const dataValidatorOptions = themeManager.getOptions("dataPrepareSettings");
        const seriesTemplate = themeManager.getOptions("seriesTemplate");
        if (seriesTemplate) {
            this._populateSeries(data)
        }
        this._groupSeries();
        const parsedData = (0, _data_validator.validateData)(data, this._groupsData, this._incidentOccurred, dataValidatorOptions);
        themeManager.resetPalette();
        this.series.forEach((singleSeries => {
            singleSeries.updateData(parsedData[singleSeries.getArgumentField()])
        }));
        this._handleSeriesDataUpdated()
    },
    _renderCompleteHandler() {
        let allSeriesInited = true;
        if (this._needHandleRenderComplete) {
            this.series.forEach((s => {
                allSeriesInited = allSeriesInited && s.canRenderCompleteHandle()
            }));
            if (allSeriesInited) {
                this._needHandleRenderComplete = false;
                this._eventTrigger("done", {
                    target: this
                })
            }
        }
    },
    _dataIsReady() {
        return (0, _type.isDefined)(this.option("dataSource")) && this._dataIsLoaded()
    },
    _populateSeriesOptions(data) {
        const themeManager = this._themeManager;
        const seriesTemplate = themeManager.getOptions("seriesTemplate");
        const seriesOptions = seriesTemplate ? (0, _utils.processSeriesTemplate)(seriesTemplate, data || []) : this.option("series");
        const allSeriesOptions = isArray(seriesOptions) ? seriesOptions : seriesOptions ? [seriesOptions] : [];
        const extraOptions = this._getExtraOptions();
        let particularSeriesOptions;
        let seriesTheme;
        const seriesThemes = [];
        const seriesVisibilityChanged = target => {
            this._specialProcessSeries();
            this._populateBusinessRange(target && target.getValueAxis(), true);
            this._renderer.stopAllAnimations(true);
            this._updateLegend();
            this._requestChange(["FULL_RENDER"])
        };
        for (let i = 0; i < allSeriesOptions.length; i++) {
            particularSeriesOptions = (0, _extend.extend)(true, {}, allSeriesOptions[i], extraOptions);
            if (!(0, _type.isDefined)(particularSeriesOptions.name) || "" === particularSeriesOptions.name) {
                particularSeriesOptions.name = `Series ${(i+1).toString()}`
            }
            particularSeriesOptions.rotated = this._isRotated();
            particularSeriesOptions.customizePoint = themeManager.getOptions("customizePoint");
            particularSeriesOptions.customizeLabel = themeManager.getOptions("customizeLabel");
            particularSeriesOptions.visibilityChanged = seriesVisibilityChanged;
            particularSeriesOptions.incidentOccurred = this._incidentOccurred;
            seriesTheme = themeManager.getOptions("series", particularSeriesOptions, allSeriesOptions.length);
            if (this._checkPaneName(seriesTheme)) {
                seriesThemes.push(seriesTheme)
            }
        }
        return seriesThemes
    },
    _populateSeries(data) {
        var _this$series3;
        const seriesBasis = [];
        const incidentOccurred = this._incidentOccurred;
        const seriesThemes = this._populateSeriesOptions(data);
        let particularSeries;
        let disposeSeriesFamilies = false;
        this.needToPopulateSeries = false;
        seriesThemes.forEach((theme => {
            var _this$series2;
            const curSeries = null === (_this$series2 = this.series) || void 0 === _this$series2 ? void 0 : _this$series2.find((s => s.name === theme.name && !seriesBasis.map((sb => sb.series)).includes(s)));
            if (curSeries && curSeries.type === theme.type) {
                seriesBasis.push({
                    series: curSeries,
                    options: theme
                })
            } else {
                seriesBasis.push({
                    options: theme
                });
                disposeSeriesFamilies = true
            }
        }));
        0 !== (null === (_this$series3 = this.series) || void 0 === _this$series3 ? void 0 : _this$series3.length) && this._tracker.clearHover();
        (0, _iterator.reverseEach)(this.series, ((index, series) => {
            if (!seriesBasis.some((s => series === s.series))) {
                this._disposeSeries(index);
                disposeSeriesFamilies = true
            }
        }));
        !disposeSeriesFamilies && (disposeSeriesFamilies = seriesBasis.some((sb => sb.series.name !== seriesThemes[sb.series.index].name)));
        this.series = [];
        disposeSeriesFamilies && this._disposeSeriesFamilies();
        this._themeManager.resetPalette();
        const eventPipe = data => {
            this.series.forEach((currentSeries => {
                currentSeries.notify(data)
            }))
        };
        seriesBasis.forEach((basis => {
            var _this$_argumentAxes;
            const seriesTheme = basis.options;
            const argumentAxis = (null === (_this$_argumentAxes = this._argumentAxes) || void 0 === _this$_argumentAxes ? void 0 : _this$_argumentAxes.filter((a => a.pane === seriesTheme.pane))[0]) ?? this.getArgumentAxis();
            const renderSettings = {
                commonSeriesModes: this._getSelectionModes(),
                argumentAxis: argumentAxis,
                valueAxis: this._getValueAxis(seriesTheme.pane, seriesTheme.axis)
            };
            if (basis.series) {
                particularSeries = basis.series;
                particularSeries.updateOptions(seriesTheme, renderSettings)
            } else {
                particularSeries = new _base_series.Series((0, _extend.extend)({
                    renderer: this._renderer,
                    seriesGroup: this._seriesGroup,
                    labelsGroup: this._labelsGroup,
                    eventTrigger: this._eventTrigger,
                    eventPipe: eventPipe,
                    incidentOccurred: incidentOccurred
                }, renderSettings), seriesTheme)
            }
            if (!particularSeries.isUpdated) {
                incidentOccurred("E2101", [seriesTheme.type])
            } else {
                particularSeries.index = this.series.length;
                this.series.push(particularSeries)
            }
        }));
        return this.series
    },
    getStackedPoints(point) {
        const stackName = point.series.getStackName();
        return this._getVisibleSeries().reduce(((stackPoints, series) => {
            if (!(0, _type.isDefined)(series.getStackName()) || !(0, _type.isDefined)(stackName) || stackName === series.getStackName()) {
                stackPoints = stackPoints.concat(series.getPointsByArg(point.argument))
            }
            return stackPoints
        }), [])
    },
    getAllSeries: function() {
        return (this.series || []).slice()
    },
    getSeriesByName: function(name) {
        const found = (this.series || []).find((singleSeries => singleSeries.name === name));
        return found || null
    },
    getSeriesByPos: function(pos) {
        return (this.series || [])[pos]
    },
    clearSelection: function() {
        this._tracker.clearSelection()
    },
    hideTooltip() {
        this._tracker._hideTooltip()
    },
    clearHover() {
        this._tracker.clearHover()
    },
    render(renderOptions) {
        this.__renderOptions = renderOptions;
        this.__forceRender = renderOptions && renderOptions.force;
        this.callBase.apply(this, arguments);
        this.__renderOptions = this.__forceRender = null;
        return this
    },
    refresh() {
        this._disposeSeries();
        this._disposeSeriesFamilies();
        this._requestChange(["CONTAINER_SIZE", "REFRESH_SERIES_REINIT"])
    },
    _getMinSize() {
        const adaptiveLayout = this._layoutManagerOptions();
        return [adaptiveLayout.width, adaptiveLayout.height]
    },
    _change_REFRESH() {
        if (!this._changes.has("INIT")) {
            this._doRefresh()
        } else {
            this._currentRefreshData = null
        }
    },
    _change_FULL_RENDER() {
        this._forceRender()
    },
    _change_INIT() {
        this._reinit()
    },
    _stopCurrentHandling() {
        if (this._disposed) {
            return
        }
        this._tracker.stopCurrentHandling()
    }
});
REFRESH_SERIES_DATA_INIT_ACTION_OPTIONS.forEach((name => {
    BaseChart.prototype._optionChangesMap[name] = "REFRESH_SERIES_DATA_INIT"
}));
FORCE_RENDER_REFRESH_ACTION_OPTIONS.forEach((name => {
    BaseChart.prototype._optionChangesMap[name] = "FORCE_RENDER"
}));
REFRESH_SERIES_FAMILIES_ACTION_OPTIONS.forEach((name => {
    BaseChart.prototype._optionChangesMap[name] = "REFRESH_SERIES_FAMILIES"
}));
BaseChart.addPlugin(_export.plugin);
BaseChart.addPlugin(_title.plugin);
BaseChart.addPlugin(_data_source.plugin);
BaseChart.addPlugin(_tooltip.plugin);
BaseChart.addPlugin(_loading_indicator.plugin);
const {
    _change_TITLE: _change_TITLE
} = BaseChart.prototype;
BaseChart.prototype._change_TITLE = function() {
    _change_TITLE.apply(this, arguments);
    this._change(["FORCE_RENDER"])
};
