"use strict";
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __read = (this && this.__read) || function (o, n) {
    var m = typeof Symbol === "function" && o[Symbol.iterator];
    if (!m) return o;
    var i = m.call(o), r, ar = [], e;
    try {
        while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
    }
    catch (error) { e = { error: error }; }
    finally {
        try {
            if (r && !r.done && (m = i["return"])) m.call(i);
        }
        finally { if (e) throw e.error; }
    }
    return ar;
};
var __spread = (this && this.__spread) || function () {
    for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
    return ar;
};
var __values = (this && this.__values) || function(o) {
    var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
    if (m) return m.call(o);
    if (o && typeof o.length === "number") return {
        next: function () {
            if (o && i >= o.length) o = void 0;
            return { value: o && o[i++], done: !o };
        }
    };
    throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
Object.defineProperty(exports, "__esModule", { value: true });
var constants_1 = require("../../../../scales/constants");
var commons_1 = require("../../../../utils/commons");
var curves_1 = require("../../../../utils/curves");
var x_domain_1 = require("../../domains/x_domain");
var y_domain_1 = require("../../domains/y_domain");
var rendering_1 = require("../../rendering/rendering");
var axis_utils_1 = require("../../utils/axis_utils");
var fill_series_1 = require("../../utils/fill_series");
var indexed_geometry_map_1 = require("../../utils/indexed_geometry_map");
var scales_1 = require("../../utils/scales");
var series_1 = require("../../utils/series");
var specs_1 = require("../../utils/specs");
var spec_1 = require("./spec");
exports.MAX_ANIMATABLE_BARS = 300;
exports.MAX_ANIMATABLE_LINES_AREA_POINTS = 600;
function updateDeselectedDataSeries(series, target) {
    var seriesIndex = series_1.getSeriesIndex(series, target);
    var updatedSeries = series ? __spread(series) : [];
    if (seriesIndex > -1) {
        updatedSeries.splice(seriesIndex, 1);
    }
    else {
        updatedSeries.push(target);
    }
    return updatedSeries;
}
exports.updateDeselectedDataSeries = updateDeselectedDataSeries;
function getCustomSeriesColors(seriesSpecs, seriesCollection) {
    var updatedCustomSeriesColors = new Map();
    var counters = new Map();
    seriesCollection.forEach(function (_a, seriesKey) {
        var seriesIdentifier = _a.seriesIdentifier;
        var spec = spec_1.getSpecsById(seriesSpecs, seriesIdentifier.specId);
        if (!spec || !spec.color) {
            return;
        }
        var color;
        if (!color && spec.color) {
            if (typeof spec.color === 'string') {
                color = spec.color;
            }
            else {
                var counter = counters.get(seriesIdentifier.specId) || 0;
                color = Array.isArray(spec.color) ? spec.color[counter % spec.color.length] : spec.color(seriesIdentifier);
                counters.set(seriesIdentifier.specId, counter + 1);
            }
        }
        if (color) {
            updatedCustomSeriesColors.set(seriesKey, color);
        }
    });
    return updatedCustomSeriesColors;
}
exports.getCustomSeriesColors = getCustomSeriesColors;
function getLastValues(formattedDataSeries, xDomain) {
    var lastValues = new Map();
    if (xDomain.scaleType === constants_1.ScaleType.Ordinal) {
        return lastValues;
    }
    formattedDataSeries.stacked.forEach(function (_a) {
        var dataSeries = _a.dataSeries, stackMode = _a.stackMode;
        dataSeries.forEach(function (series) {
            if (series.data.length === 0) {
                return;
            }
            var last = series.data[series.data.length - 1];
            if (!last) {
                return;
            }
            if (rendering_1.isDatumFilled(last)) {
                return;
            }
            if (last.x !== xDomain.domain[xDomain.domain.length - 1]) {
                return;
            }
            var y0 = last.y0, y1 = last.y1, initialY0 = last.initialY0, initialY1 = last.initialY1;
            var seriesKey = series_1.getSeriesKey(series);
            if (stackMode === specs_1.StackMode.Percentage) {
                var y1InPercentage = y1 === null || y0 === null ? null : y1 - y0;
                lastValues.set(seriesKey, { y0: y0, y1: y1InPercentage });
                return;
            }
            if (initialY0 !== null || initialY1 !== null) {
                lastValues.set(seriesKey, { y0: initialY0, y1: initialY1 });
            }
        });
    });
    formattedDataSeries.nonStacked.forEach(function (_a) {
        var dataSeries = _a.dataSeries;
        dataSeries.forEach(function (series) {
            if (series.data.length === 0) {
                return;
            }
            var last = series.data[series.data.length - 1];
            if (!last) {
                return;
            }
            if (rendering_1.isDatumFilled(last)) {
                return;
            }
            if (last.x !== xDomain.domain[xDomain.domain.length - 1]) {
                return;
            }
            var initialY1 = last.initialY1, initialY0 = last.initialY0;
            var seriesKey = series_1.getSeriesKey(series);
            lastValues.set(seriesKey, { y0: initialY0, y1: initialY1 });
        });
    });
    return lastValues;
}
function computeSeriesDomains(seriesSpecs, customYDomainsByGroupId, deselectedDataSeries, customXDomain, orderOrdinalBinsBy, enableVislibSeriesSort) {
    if (customYDomainsByGroupId === void 0) { customYDomainsByGroupId = new Map(); }
    if (deselectedDataSeries === void 0) { deselectedDataSeries = []; }
    var _a = series_1.getDataSeriesBySpecId(seriesSpecs, deselectedDataSeries, orderOrdinalBinsBy, enableVislibSeriesSort), dataSeriesBySpecId = _a.dataSeriesBySpecId, xValues = _a.xValues, seriesCollection = _a.seriesCollection, fallbackScale = _a.fallbackScale;
    var xDomain = x_domain_1.mergeXDomain(seriesSpecs, xValues, customXDomain, fallbackScale);
    var specsByGroupIds = y_domain_1.splitSpecsByGroupId(seriesSpecs);
    var filledDataSeriesBySpecId = fill_series_1.fillSeries(dataSeriesBySpecId, xValues, seriesSpecs, xDomain.scaleType, specsByGroupIds);
    var formattedDataSeries = series_1.getFormattedDataseries(filledDataSeriesBySpecId, xValues, xDomain.scaleType, seriesSpecs, specsByGroupIds);
    var yDomain = y_domain_1.mergeYDomain(formattedDataSeries, seriesSpecs, customYDomainsByGroupId);
    var lastValues = getLastValues(formattedDataSeries, xDomain);
    var updatedSeriesCollection = new Map();
    seriesCollection.forEach(function (value, key) {
        var lastValue = lastValues.get(key);
        var updatedColorSet = __assign(__assign({}, value), { lastValue: lastValue });
        updatedSeriesCollection.set(key, updatedColorSet);
    });
    return {
        xDomain: xDomain,
        yDomain: yDomain,
        formattedDataSeries: formattedDataSeries,
        seriesCollection: updatedSeriesCollection,
    };
}
exports.computeSeriesDomains = computeSeriesDomains;
function computeSeriesGeometries(seriesSpecs, xDomain, yDomain, formattedDataSeries, seriesColorMap, chartTheme, chartDims, chartRotation, axesSpecs, enableHistogramMode) {
    var chartColors = chartTheme.colors;
    var barsPadding = enableHistogramMode ? chartTheme.scales.histogramPadding : chartTheme.scales.barsPadding;
    var width = [0, 180].includes(chartRotation) ? chartDims.width : chartDims.height;
    var height = [0, 180].includes(chartRotation) ? chartDims.height : chartDims.width;
    var stacked = formattedDataSeries.stacked, nonStacked = formattedDataSeries.nonStacked;
    var _a = scales_1.countBarsInCluster(stacked, nonStacked), stackedBarsInCluster = _a.stackedBarsInCluster, totalBarsInCluster = _a.totalBarsInCluster;
    var xScale = scales_1.computeXScale({
        xDomain: xDomain,
        totalBarsInCluster: totalBarsInCluster,
        range: [0, width],
        barsPadding: barsPadding,
        enableHistogramMode: enableHistogramMode,
    });
    var yScales = scales_1.computeYScales({ yDomains: yDomain, range: [height, 0] });
    var points = [];
    var areas = [];
    var bars = [];
    var lines = [];
    var bubbles = [];
    var geometriesIndex = new indexed_geometry_map_1.IndexedGeometryMap();
    var orderIndex = 0;
    var geometriesCounts = {
        points: 0,
        bars: 0,
        areas: 0,
        areasPoints: 0,
        lines: 0,
        linePoints: 0,
        bubbles: 0,
        bubblePoints: 0,
    };
    formattedDataSeries.stacked.forEach(function (dataSeriesGroup) {
        var groupId = dataSeriesGroup.groupId, dataSeries = dataSeriesGroup.dataSeries, counts = dataSeriesGroup.counts, stackMode = dataSeriesGroup.stackMode;
        var yScale = yScales.get(groupId);
        if (!yScale) {
            return;
        }
        var geometries = renderGeometries(orderIndex, totalBarsInCluster, true, dataSeries, xScale, yScale, seriesSpecs, seriesColorMap, chartColors.defaultVizColor, axesSpecs, chartTheme, enableHistogramMode, stackMode);
        orderIndex = counts[specs_1.SeriesTypes.Bar] > 0 ? orderIndex + 1 : orderIndex;
        areas.push.apply(areas, __spread(geometries.areas));
        lines.push.apply(lines, __spread(geometries.lines));
        bars.push.apply(bars, __spread(geometries.bars));
        bubbles.push.apply(bubbles, __spread(geometries.bubbles));
        points.push.apply(points, __spread(geometries.points));
        geometriesIndex.merge(geometries.indexedGeometryMap);
        geometriesCounts.points += geometries.geometriesCounts.points;
        geometriesCounts.bars += geometries.geometriesCounts.bars;
        geometriesCounts.areas += geometries.geometriesCounts.areas;
        geometriesCounts.areasPoints += geometries.geometriesCounts.areasPoints;
        geometriesCounts.lines += geometries.geometriesCounts.lines;
        geometriesCounts.linePoints += geometries.geometriesCounts.linePoints;
        geometriesCounts.bubbles += geometries.geometriesCounts.bubbles;
        geometriesCounts.bubblePoints += geometries.geometriesCounts.bubblePoints;
    });
    orderIndex = 0;
    formattedDataSeries.nonStacked.forEach(function (dataSeriesGroup) {
        var groupId = dataSeriesGroup.groupId, dataSeries = dataSeriesGroup.dataSeries, counts = dataSeriesGroup.counts;
        var yScale = yScales.get(groupId);
        if (!yScale) {
            return;
        }
        var geometries = renderGeometries(stackedBarsInCluster + orderIndex, totalBarsInCluster, false, dataSeries, xScale, yScale, seriesSpecs, seriesColorMap, chartColors.defaultVizColor, axesSpecs, chartTheme, enableHistogramMode);
        orderIndex = counts[specs_1.SeriesTypes.Bar] > 0 ? orderIndex + counts[specs_1.SeriesTypes.Bar] : orderIndex;
        areas.push.apply(areas, __spread(geometries.areas));
        lines.push.apply(lines, __spread(geometries.lines));
        bars.push.apply(bars, __spread(geometries.bars));
        bubbles.push.apply(bubbles, __spread(geometries.bubbles));
        points.push.apply(points, __spread(geometries.points));
        geometriesIndex.merge(geometries.indexedGeometryMap);
        geometriesCounts.points += geometries.geometriesCounts.points;
        geometriesCounts.bars += geometries.geometriesCounts.bars;
        geometriesCounts.areas += geometries.geometriesCounts.areas;
        geometriesCounts.areasPoints += geometries.geometriesCounts.areasPoints;
        geometriesCounts.lines += geometries.geometriesCounts.lines;
        geometriesCounts.linePoints += geometries.geometriesCounts.linePoints;
        geometriesCounts.bubbles += geometries.geometriesCounts.bubbles;
        geometriesCounts.bubblePoints += geometries.geometriesCounts.bubblePoints;
    });
    return {
        scales: {
            xScale: xScale,
            yScales: yScales,
        },
        geometries: {
            points: points,
            areas: areas,
            bars: bars,
            lines: lines,
            bubbles: bubbles,
        },
        geometriesIndex: geometriesIndex,
        geometriesCounts: geometriesCounts,
    };
}
exports.computeSeriesGeometries = computeSeriesGeometries;
function setBarSeriesAccessors(isHistogramMode, seriesSpecs) {
    var e_1, _a;
    if (!isHistogramMode) {
        return;
    }
    try {
        for (var seriesSpecs_1 = __values(seriesSpecs), seriesSpecs_1_1 = seriesSpecs_1.next(); !seriesSpecs_1_1.done; seriesSpecs_1_1 = seriesSpecs_1.next()) {
            var _b = __read(seriesSpecs_1_1.value, 2), spec = _b[1];
            if (specs_1.isBarSeriesSpec(spec)) {
                var stackAccessors = spec.stackAccessors ? __spread(spec.stackAccessors) : spec.yAccessors;
                if (spec.splitSeriesAccessors) {
                    stackAccessors = __spread(stackAccessors, spec.splitSeriesAccessors);
                }
                spec.stackAccessors = stackAccessors;
            }
        }
    }
    catch (e_1_1) { e_1 = { error: e_1_1 }; }
    finally {
        try {
            if (seriesSpecs_1_1 && !seriesSpecs_1_1.done && (_a = seriesSpecs_1.return)) _a.call(seriesSpecs_1);
        }
        finally { if (e_1) throw e_1.error; }
    }
}
exports.setBarSeriesAccessors = setBarSeriesAccessors;
function isHistogramModeEnabled(seriesSpecs) {
    return seriesSpecs.some(function (spec) { return specs_1.isBarSeriesSpec(spec) && spec.enableHistogramMode; });
}
exports.isHistogramModeEnabled = isHistogramModeEnabled;
function computeXScaleOffset(xScale, enableHistogramMode, histogramModeAlignment) {
    if (histogramModeAlignment === void 0) { histogramModeAlignment = specs_1.HistogramModeAlignments.Start; }
    if (!enableHistogramMode) {
        return 0;
    }
    var bandwidth = xScale.bandwidth, barsPadding = xScale.barsPadding;
    var band = bandwidth / (1 - barsPadding);
    var halfPadding = (band - bandwidth) / 2;
    var startAlignmentOffset = bandwidth / 2 + halfPadding;
    switch (histogramModeAlignment) {
        case specs_1.HistogramModeAlignments.Center:
            return 0;
        case specs_1.HistogramModeAlignments.End:
            return -startAlignmentOffset;
        default:
            return startAlignmentOffset;
    }
}
exports.computeXScaleOffset = computeXScaleOffset;
function renderGeometries(indexOffset, clusteredCount, isStacked, dataSeries, xScale, yScale, seriesSpecs, seriesColorsMap, defaultColor, axesSpecs, chartTheme, enableHistogramMode, stackMode) {
    var _a, _b, _c, _d;
    var len = dataSeries.length;
    var i;
    var points = [];
    var bars = [];
    var areas = [];
    var lines = [];
    var bubbles = [];
    var indexedGeometryMap = new indexed_geometry_map_1.IndexedGeometryMap();
    var isMixedChart = commons_1.isUniqueArray(seriesSpecs, function (_a) {
        var seriesType = _a.seriesType;
        return seriesType;
    }) && seriesSpecs.length > 1;
    var fallBackTickFormatter = (_b = (_a = seriesSpecs.find(function (_a) {
        var tickFormat = _a.tickFormat;
        return tickFormat;
    })) === null || _a === void 0 ? void 0 : _a.tickFormat, (_b !== null && _b !== void 0 ? _b : axis_utils_1.defaultTickFormatter));
    var geometriesCounts = {
        points: 0,
        bars: 0,
        areas: 0,
        areasPoints: 0,
        lines: 0,
        linePoints: 0,
        bubbles: 0,
        bubblePoints: 0,
    };
    var barIndexOffset = 0;
    for (i = 0; i < len; i++) {
        var ds = dataSeries[i];
        var spec = spec_1.getSpecsById(seriesSpecs, ds.specId);
        if (spec === undefined) {
            continue;
        }
        var color = seriesColorsMap.get(series_1.getSeriesKey(ds)) || defaultColor;
        if (specs_1.isBarSeriesSpec(spec)) {
            var shift = isStacked ? indexOffset : indexOffset + barIndexOffset;
            var barSeriesStyle = commons_1.mergePartial(chartTheme.barSeriesStyle, spec.barSeriesStyle, {
                mergeOptionalPartialValues: true,
            });
            var yAxis = spec_1.getAxesSpecForSpecId(axesSpecs, spec.groupId).yAxis;
            var valueFormatter = (_d = (_c = yAxis) === null || _c === void 0 ? void 0 : _c.tickFormat, (_d !== null && _d !== void 0 ? _d : fallBackTickFormatter));
            var displayValueSettings = spec.displayValueSettings
                ? __assign({ valueFormatter: valueFormatter }, spec.displayValueSettings) : undefined;
            var renderedBars = rendering_1.renderBars(shift, ds, xScale, yScale, color, barSeriesStyle, displayValueSettings, spec.styleAccessor, spec.minBarHeight, stackMode);
            indexedGeometryMap.merge(renderedBars.indexedGeometryMap);
            bars.push.apply(bars, __spread(renderedBars.barGeometries));
            geometriesCounts.bars += renderedBars.barGeometries.length;
            barIndexOffset += 1;
        }
        else if (specs_1.isBubbleSeriesSpec(spec)) {
            var bubbleShift = clusteredCount > 0 ? clusteredCount : 1;
            var bubbleSeriesStyle = spec.bubbleSeriesStyle
                ? commons_1.mergePartial(chartTheme.bubbleSeriesStyle, spec.bubbleSeriesStyle, { mergeOptionalPartialValues: true })
                : chartTheme.bubbleSeriesStyle;
            var renderedBubbles = rendering_1.renderBubble((xScale.bandwidth * bubbleShift) / 2, ds, xScale, yScale, color, specs_1.isBandedSpec(spec.y0Accessors), bubbleSeriesStyle, {
                enabled: spec.markSizeAccessor !== undefined,
                ratio: chartTheme.markSizeRatio,
            }, isMixedChart, spec.pointStyleAccessor);
            indexedGeometryMap.merge(renderedBubbles.indexedGeometryMap);
            bubbles.push(renderedBubbles.bubbleGeometry);
            geometriesCounts.bubblePoints += renderedBubbles.bubbleGeometry.points.length;
            geometriesCounts.bubbles += 1;
        }
        else if (specs_1.isLineSeriesSpec(spec)) {
            var lineShift = clusteredCount > 0 ? clusteredCount : 1;
            var lineSeriesStyle = spec.lineSeriesStyle
                ? commons_1.mergePartial(chartTheme.lineSeriesStyle, spec.lineSeriesStyle, { mergeOptionalPartialValues: true })
                : chartTheme.lineSeriesStyle;
            var xScaleOffset = computeXScaleOffset(xScale, enableHistogramMode, spec.histogramModeAlignment);
            var renderedLines = rendering_1.renderLine((xScale.bandwidth * lineShift) / 2, ds, xScale, yScale, color, spec.curve || curves_1.CurveType.LINEAR, specs_1.isBandedSpec(spec.y0Accessors), xScaleOffset, lineSeriesStyle, {
                enabled: spec.markSizeAccessor !== undefined,
                ratio: chartTheme.markSizeRatio,
            }, spec.pointStyleAccessor, hasFitFnConfigured(spec.fit));
            indexedGeometryMap.merge(renderedLines.indexedGeometryMap);
            lines.push(renderedLines.lineGeometry);
            geometriesCounts.linePoints += renderedLines.lineGeometry.points.length;
            geometriesCounts.lines += 1;
        }
        else if (specs_1.isAreaSeriesSpec(spec)) {
            var areaShift = clusteredCount > 0 ? clusteredCount : 1;
            var areaSeriesStyle = spec.areaSeriesStyle
                ? commons_1.mergePartial(chartTheme.areaSeriesStyle, spec.areaSeriesStyle, { mergeOptionalPartialValues: true })
                : chartTheme.areaSeriesStyle;
            var xScaleOffset = computeXScaleOffset(xScale, enableHistogramMode, spec.histogramModeAlignment);
            var renderedAreas = rendering_1.renderArea((xScale.bandwidth * areaShift) / 2, ds, xScale, yScale, color, spec.curve || curves_1.CurveType.LINEAR, specs_1.isBandedSpec(spec.y0Accessors), xScaleOffset, areaSeriesStyle, {
                enabled: spec.markSizeAccessor !== undefined,
                ratio: chartTheme.markSizeRatio,
            }, isStacked, spec.pointStyleAccessor, hasFitFnConfigured(spec.fit), stackMode);
            indexedGeometryMap.merge(renderedAreas.indexedGeometryMap);
            areas.push(renderedAreas.areaGeometry);
            geometriesCounts.areasPoints += renderedAreas.areaGeometry.points.length;
            geometriesCounts.areas += 1;
        }
    }
    return {
        points: points,
        bars: bars,
        areas: areas,
        lines: lines,
        bubbles: bubbles,
        indexedGeometryMap: indexedGeometryMap,
        geometriesCounts: geometriesCounts,
    };
}
function computeChartTransform(chartDimensions, chartRotation) {
    if (chartRotation === 90) {
        return {
            x: chartDimensions.width,
            y: 0,
            rotate: 90,
        };
    }
    if (chartRotation === -90) {
        return {
            x: 0,
            y: chartDimensions.height,
            rotate: -90,
        };
    }
    if (chartRotation === 180) {
        return {
            x: chartDimensions.width,
            y: chartDimensions.height,
            rotate: 180,
        };
    }
    return {
        x: 0,
        y: 0,
        rotate: 0,
    };
}
exports.computeChartTransform = computeChartTransform;
function hasFitFnConfigured(fit) {
    return Boolean(fit && (fit.type || fit) !== specs_1.Fit.None);
}
//# sourceMappingURL=utils.js.map