"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 __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
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 specs_1 = require("../../../specs");
var accessor_1 = require("../../../utils/accessor");
var logger_1 = require("../../../utils/logger");
var fit_function_utils_1 = require("./fit_function_utils");
var specs_2 = require("./specs");
var stacked_series_utils_1 = require("./stacked_series_utils");
exports.SERIES_DELIMITER = ' - ';
function getSeriesIndex(series, target) {
    if (!series) {
        return -1;
    }
    return series.findIndex(function (_a) {
        var key = _a.key;
        return target.key === key;
    });
}
exports.getSeriesIndex = getSeriesIndex;
function splitSeriesDataByAccessors(_a, xValueSums, enableVislibSeriesSort) {
    var specId = _a.id, data = _a.data, xAccessor = _a.xAccessor, yAccessors = _a.yAccessors, y0Accessors = _a.y0Accessors, markSizeAccessor = _a.markSizeAccessor, _b = _a.splitSeriesAccessors, splitSeriesAccessors = _b === void 0 ? [] : _b;
    if (enableVislibSeriesSort === void 0) { enableVislibSeriesSort = false; }
    var dataSeries = new Map();
    var xValues = [];
    var nonNumericValues = [];
    if (enableVislibSeriesSort) {
        yAccessors.forEach(function (accessor, index) {
            data.forEach(function (datum) {
                var _a, _b;
                var splitAccessors = getSplitAccessors(datum, splitSeriesAccessors);
                if (splitSeriesAccessors.length > 0 && splitAccessors.size < 1) {
                    return;
                }
                if (typeof datum !== 'object' || datum === null) {
                    return;
                }
                var x = accessor_1.getAccessorValue(datum, xAccessor);
                if (typeof x !== 'string' && typeof x !== 'number') {
                    return;
                }
                xValues.push(x);
                var sum = (_a = xValueSums.get(x), (_a !== null && _a !== void 0 ? _a : 0));
                var cleanedDatum = extractYandMarkFromDatum(datum, accessor, nonNumericValues, y0Accessors && y0Accessors[index], markSizeAccessor);
                var seriesKeys = __spread(splitAccessors.values(), [accessor]);
                var seriesKey = getSeriesKey({
                    specId: specId,
                    yAccessor: accessor,
                    splitAccessors: splitAccessors,
                });
                sum += (_b = cleanedDatum.y1, (_b !== null && _b !== void 0 ? _b : 0));
                var newDatum = __assign({ x: x }, cleanedDatum);
                var series = dataSeries.get(seriesKey);
                if (series) {
                    series.data.push(newDatum);
                }
                else {
                    dataSeries.set(seriesKey, {
                        specId: specId,
                        yAccessor: accessor,
                        splitAccessors: splitAccessors,
                        data: [newDatum],
                        key: seriesKey,
                        seriesKeys: seriesKeys,
                    });
                }
                xValueSums.set(x, sum);
            });
        });
    }
    else {
        data.forEach(function (datum) {
            var _a;
            var splitAccessors = getSplitAccessors(datum, splitSeriesAccessors);
            if (splitSeriesAccessors.length > 0 && splitAccessors.size < 1) {
                return;
            }
            if (typeof datum !== 'object' || datum === null) {
                return;
            }
            var x = accessor_1.getAccessorValue(datum, xAccessor);
            if (typeof x !== 'string' && typeof x !== 'number') {
                return;
            }
            xValues.push(x);
            var sum = (_a = xValueSums.get(x), (_a !== null && _a !== void 0 ? _a : 0));
            yAccessors.forEach(function (accessor, index) {
                var _a;
                var cleanedDatum = extractYandMarkFromDatum(datum, accessor, nonNumericValues, y0Accessors && y0Accessors[index], markSizeAccessor);
                var seriesKeys = __spread(splitAccessors.values(), [accessor]);
                var seriesKey = getSeriesKey({
                    specId: specId,
                    yAccessor: accessor,
                    splitAccessors: splitAccessors,
                });
                sum += (_a = cleanedDatum.y1, (_a !== null && _a !== void 0 ? _a : 0));
                var newDatum = __assign({ x: x }, cleanedDatum);
                var series = dataSeries.get(seriesKey);
                if (series) {
                    series.data.push(newDatum);
                }
                else {
                    dataSeries.set(seriesKey, {
                        specId: specId,
                        yAccessor: accessor,
                        splitAccessors: splitAccessors,
                        data: [newDatum],
                        key: seriesKey,
                        seriesKeys: seriesKeys,
                    });
                }
            });
            xValueSums.set(x, sum);
        });
    }
    if (nonNumericValues.length > 0) {
        logger_1.Logger.warn("Found non-numeric y value" + (nonNumericValues.length > 1 ? 's' : '') + " in dataset for spec \"" + specId + "\"", "(" + nonNumericValues.map(function (v) { return JSON.stringify(v); }).join(', ') + ")");
    }
    return {
        dataSeries: dataSeries,
        xValues: xValues,
    };
}
exports.splitSeriesDataByAccessors = splitSeriesDataByAccessors;
function getSeriesKey(_a) {
    var specId = _a.specId, yAccessor = _a.yAccessor, splitAccessors = _a.splitAccessors;
    var joinedAccessors = __spread(splitAccessors.entries()).sort(function (_a, _b) {
        var _c = __read(_a, 1), a = _c[0];
        var _d = __read(_b, 1), b = _d[0];
        return (a > b ? 1 : -1);
    })
        .map(function (_a) {
        var _b = __read(_a, 2), key = _b[0], value = _b[1];
        return key + "-" + value;
    })
        .join('|');
    return "spec{" + specId + "}yAccessor{" + yAccessor + "}splitAccessors{" + joinedAccessors + "}";
}
exports.getSeriesKey = getSeriesKey;
function getSplitAccessors(datum, accessors) {
    if (accessors === void 0) { accessors = []; }
    var splitAccessors = new Map();
    if (typeof datum === 'object' && datum !== null) {
        accessors.forEach(function (accessor) {
            var value = datum[accessor];
            if (typeof value === 'string' || typeof value === 'number') {
                splitAccessors.set(accessor, value);
            }
        });
    }
    return splitAccessors;
}
function extractYandMarkFromDatum(datum, yAccessor, nonNumericValues, y0Accessor, markSizeAccessor) {
    var mark = markSizeAccessor === undefined ? null : castToNumber(accessor_1.getAccessorValue(datum, markSizeAccessor), nonNumericValues);
    var y1 = castToNumber(datum[yAccessor], nonNumericValues);
    var y0 = y0Accessor ? castToNumber(datum[y0Accessor], nonNumericValues) : null;
    return { y1: y1, datum: datum, y0: y0, mark: mark, initialY0: y0, initialY1: y1 };
}
exports.extractYandMarkFromDatum = extractYandMarkFromDatum;
function castToNumber(value, nonNumericValues) {
    if (value === null || value === undefined) {
        return null;
    }
    var num = Number(value);
    if (isNaN(num)) {
        nonNumericValues.push(value);
        return null;
    }
    return num;
}
var getSortedDataSeries = function (dataSeries, xValues, xScaleType) {
    return dataSeries.map(function (_a) {
        var data = _a.data, rest = __rest(_a, ["data"]);
        return (__assign(__assign({}, rest), { data: data.sort(stacked_series_utils_1.datumXSortPredicate(xScaleType, __spread(xValues.values()))) }));
    });
};
function getFormattedDataseries(availableDataSeries, xValues, xScaleType, seriesSpecs, specsByGroupIdsEntries) {
    var stackedFormattedDataSeries = [];
    var nonStackedFormattedDataSeries = [];
    __spread(specsByGroupIdsEntries.entries()).forEach(function (_a) {
        var _b = __read(_a, 2), groupId = _b[0], groupSpecs = _b[1];
        var stackMode = groupSpecs.stackMode;
        var stackedDataSeries = getDataSeriesBySpecGroup(groupSpecs.stacked, availableDataSeries);
        var fittedStackedDataSeries = fit_function_utils_1.applyFitFunctionToDataSeries(getSortedDataSeries(stackedDataSeries.dataSeries, xValues, xScaleType), seriesSpecs, xScaleType);
        var fittedAndStackedDataSeries = stacked_series_utils_1.formatStackedDataSeriesValues(fittedStackedDataSeries, xValues, stackMode);
        stackedFormattedDataSeries.push({
            groupId: groupId,
            counts: stackedDataSeries.counts,
            dataSeries: fittedAndStackedDataSeries,
            stackMode: stackMode,
        });
        var nonStackedDataSeries = getDataSeriesBySpecGroup(groupSpecs.nonStacked, availableDataSeries);
        var fittedNonStackedDataSeries = fit_function_utils_1.applyFitFunctionToDataSeries(getSortedDataSeries(nonStackedDataSeries.dataSeries, xValues, xScaleType), seriesSpecs, xScaleType);
        nonStackedFormattedDataSeries.push({
            groupId: groupId,
            counts: nonStackedDataSeries.counts,
            dataSeries: fittedNonStackedDataSeries,
        });
    });
    return {
        stacked: stackedFormattedDataSeries.filter(function (ds) { return ds.dataSeries.length > 0; }),
        nonStacked: nonStackedFormattedDataSeries.filter(function (ds) { return ds.dataSeries.length > 0; }),
    };
}
exports.getFormattedDataseries = getFormattedDataseries;
function getDataSeriesBySpecGroup(seriesSpecs, dataSeries) {
    var _a;
    return seriesSpecs.reduce(function (acc, _a) {
        var _b;
        var id = _a.id, seriesType = _a.seriesType;
        var ds = dataSeries.get(id);
        if (!ds) {
            return acc;
        }
        (_b = acc.dataSeries).push.apply(_b, __spread(ds));
        acc.counts[seriesType] += ds.length;
        return acc;
    }, {
        dataSeries: [],
        counts: (_a = {},
            _a[specs_2.SeriesTypes.Bar] = 0,
            _a[specs_2.SeriesTypes.Area] = 0,
            _a[specs_2.SeriesTypes.Line] = 0,
            _a[specs_2.SeriesTypes.Bubble] = 0,
            _a),
    });
}
function getDataSeriesBySpecId(seriesSpecs, deselectedDataSeries, orderOrdinalBinsBy, enableVislibSeriesSort) {
    var e_1, _a;
    if (deselectedDataSeries === void 0) { deselectedDataSeries = []; }
    var dataSeriesBySpecId = new Map();
    var seriesCollection = new Map();
    var mutatedXValueSums = new Map();
    var globalXValues = new Set();
    var isNumberArray = true;
    var isOrdinalScale = false;
    var _loop_1 = function (spec) {
        var e_2, _a;
        if (spec.xScaleType === constants_1.ScaleType.Ordinal) {
            isOrdinalScale = true;
        }
        var _b = splitSeriesDataByAccessors(spec, mutatedXValueSums, enableVislibSeriesSort), dataSeries = _b.dataSeries, xValues_2 = _b.xValues;
        var filteredDataSeries = __spread(dataSeries.values());
        if (deselectedDataSeries.length > 0) {
            filteredDataSeries = filteredDataSeries.filter(function (_a) {
                var key = _a.key;
                return !deselectedDataSeries.some(function (_a) {
                    var deselectedKey = _a.key;
                    return key === deselectedKey;
                });
            });
        }
        dataSeriesBySpecId.set(spec.id, filteredDataSeries);
        var banded = spec.y0Accessors && spec.y0Accessors.length > 0;
        dataSeries.forEach(function (series, key) {
            var data = series.data, seriesIdentifier = __rest(series, ["data"]);
            seriesCollection.set(key, {
                banded: banded,
                specSortIndex: spec.sortIndex,
                seriesIdentifier: seriesIdentifier,
            });
        });
        try {
            for (var xValues_1 = (e_2 = void 0, __values(xValues_2)), xValues_1_1 = xValues_1.next(); !xValues_1_1.done; xValues_1_1 = xValues_1.next()) {
                var xValue = xValues_1_1.value;
                if (isNumberArray && typeof xValue !== 'number') {
                    isNumberArray = false;
                }
                globalXValues.add(xValue);
            }
        }
        catch (e_2_1) { e_2 = { error: e_2_1 }; }
        finally {
            try {
                if (xValues_1_1 && !xValues_1_1.done && (_a = xValues_1.return)) _a.call(xValues_1);
            }
            finally { if (e_2) throw e_2.error; }
        }
    };
    try {
        for (var seriesSpecs_1 = __values(seriesSpecs), seriesSpecs_1_1 = seriesSpecs_1.next(); !seriesSpecs_1_1.done; seriesSpecs_1_1 = seriesSpecs_1.next()) {
            var spec = seriesSpecs_1_1.value;
            _loop_1(spec);
        }
    }
    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; }
    }
    var xValues = isOrdinalScale || !isNumberArray
        ? getSortedOrdinalXValues(globalXValues, mutatedXValueSums, orderOrdinalBinsBy)
        : new Set(__spread(globalXValues).sort(function (a, b) {
            if (typeof a === 'string' || typeof b === 'string') {
                return 0;
            }
            return a - b;
        }));
    return {
        dataSeriesBySpecId: dataSeriesBySpecId,
        seriesCollection: seriesCollection,
        xValues: xValues,
        fallbackScale: !isOrdinalScale && !isNumberArray ? constants_1.ScaleType.Ordinal : undefined,
    };
}
exports.getDataSeriesBySpecId = getDataSeriesBySpecId;
function getSortedOrdinalXValues(xValues, xValueSums, orderOrdinalBinsBy) {
    var _a;
    if (!orderOrdinalBinsBy) {
        return xValues;
    }
    switch ((_a = orderOrdinalBinsBy) === null || _a === void 0 ? void 0 : _a.binAgg) {
        case specs_1.BinAgg.None:
            return xValues;
        case specs_1.BinAgg.Sum:
        default:
            return new Set(__spread(xValues).sort(function (v1, v2) {
                var _a, _b;
                return ((orderOrdinalBinsBy.direction === specs_1.Direction.Ascending ? 1 : -1) *
                    ((_a = xValueSums.get(v1), (_a !== null && _a !== void 0 ? _a : 0)) - (_b = xValueSums.get(v2), (_b !== null && _b !== void 0 ? _b : 0))));
            }));
    }
}
function getSeriesNameFromOptions(options, _a, delimiter) {
    var yAccessor = _a.yAccessor, splitAccessors = _a.splitAccessors;
    if (!options.names) {
        return null;
    }
    return (options.names
        .slice()
        .sort(function (_a, _b) {
        var _c = _a.sortIndex, a = _c === void 0 ? Infinity : _c;
        var _d = _b.sortIndex, b = _d === void 0 ? Infinity : _d;
        return a - b;
    })
        .map(function (_a) {
        var accessor = _a.accessor, value = _a.value, name = _a.name;
        var _b;
        var accessorValue = (_b = splitAccessors.get(accessor), (_b !== null && _b !== void 0 ? _b : null));
        if (accessorValue === value) {
            return (name !== null && name !== void 0 ? name : value);
        }
        if (yAccessor === accessor) {
            return (name !== null && name !== void 0 ? name : accessor);
        }
        return null;
    })
        .filter(function (d) { return Boolean(d) || d === 0; })
        .join(delimiter) || null);
}
function getSeriesName(seriesIdentifier, hasSingleSeries, isTooltip, spec) {
    var _a;
    var delimiter = exports.SERIES_DELIMITER;
    if (spec && spec.name && typeof spec.name !== 'string') {
        var customLabel = null;
        if (typeof spec.name === 'function') {
            customLabel = spec.name(seriesIdentifier, isTooltip);
        }
        else {
            delimiter = (_a = spec.name.delimiter, (_a !== null && _a !== void 0 ? _a : delimiter));
            customLabel = getSeriesNameFromOptions(spec.name, seriesIdentifier, delimiter);
        }
        if (customLabel !== null) {
            return customLabel.toString();
        }
    }
    var name = '';
    var nameKeys = spec && spec.yAccessors.length > 1 ? seriesIdentifier.seriesKeys : seriesIdentifier.seriesKeys.slice(0, -1);
    if (hasSingleSeries || nameKeys.length === 0 || nameKeys[0] == null) {
        if (!spec) {
            return '';
        }
        if (spec.splitSeriesAccessors && nameKeys.length > 0 && nameKeys[0] != null) {
            name = nameKeys.join(delimiter);
        }
        else {
            name = typeof spec.name === 'string' ? spec.name : "" + spec.id;
        }
    }
    else {
        name = nameKeys.join(delimiter);
    }
    return name;
}
exports.getSeriesName = getSeriesName;
function getSortIndex(_a, total) {
    var specSortIndex = _a.specSortIndex;
    return specSortIndex != null ? specSortIndex : total;
}
function getSortedDataSeriesColorsValuesMap(seriesCollection) {
    var seriesColorsArray = __spread(seriesCollection);
    seriesColorsArray.sort(function (_a, _b) {
        var _c = __read(_a, 2), specA = _c[1];
        var _d = __read(_b, 2), specB = _d[1];
        return getSortIndex(specA, seriesCollection.size) - getSortIndex(specB, seriesCollection.size);
    });
    return new Map(__spread(seriesColorsArray));
}
exports.getSortedDataSeriesColorsValuesMap = getSortedDataSeriesColorsValuesMap;
function getHighestOverride(key, customColors, overrides) {
    var color = overrides.temporary[key];
    if (color) {
        return color;
    }
    color = customColors.get(key);
    if (color) {
        return color;
    }
    return overrides.persisted[key];
}
function getSeriesColors(seriesCollection, chartColors, customColors, overrides) {
    var seriesColorMap = new Map();
    var counter = 0;
    seriesCollection.forEach(function (_, seriesKey) {
        var colorOverride = getHighestOverride(seriesKey, customColors, overrides);
        var color = colorOverride || chartColors.vizColors[counter % chartColors.vizColors.length];
        seriesColorMap.set(seriesKey, color);
        counter++;
    });
    return seriesColorMap;
}
exports.getSeriesColors = getSeriesColors;
//# sourceMappingURL=series.js.map