"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.computeLegend = computeLegend;
const common_1 = require("../../../utils/common");
const geometry_1 = require("../../../utils/geometry");
const utils_1 = require("../rendering/utils");
const get_legend_values_1 = require("../state/utils/get_legend_values");
const spec_1 = require("../state/utils/spec");
const tooltip_1 = require("../tooltip/tooltip");
const axis_utils_1 = require("../utils/axis_utils");
const default_series_sort_fn_1 = require("../utils/default_series_sort_fn");
const group_data_series_1 = require("../utils/group_data_series");
const series_1 = require("../utils/series");
const specs_1 = require("../utils/specs");
function getPostfix(spec) {
    if ((0, specs_1.isAreaSeriesSpec)(spec) || (0, specs_1.isBarSeriesSpec)(spec)) {
        const { y0AccessorFormat = tooltip_1.Y0_ACCESSOR_POSTFIX, y1AccessorFormat = tooltip_1.Y1_ACCESSOR_POSTFIX } = spec;
        return { y0AccessorFormat, y1AccessorFormat };
    }
    return {};
}
function getBandedLegendItemLabel(name, yAccessor, postfixes) {
    return yAccessor === geometry_1.BandedAccessorType.Y1
        ? `${name}${postfixes.y1AccessorFormat}`
        : `${name}${postfixes.y0AccessorFormat}`;
}
function getPointStyle(spec, theme) {
    if ((0, specs_1.isBubbleSeriesSpec)(spec)) {
        return (0, common_1.mergePartial)(theme.bubbleSeriesStyle.point, spec.bubbleSeriesStyle?.point);
    }
    else if ((0, specs_1.isLineSeriesSpec)(spec)) {
        return (0, common_1.mergePartial)(theme.lineSeriesStyle.point, spec.lineSeriesStyle?.point);
    }
    else if ((0, specs_1.isAreaSeriesSpec)(spec)) {
        return (0, common_1.mergePartial)(theme.areaSeriesStyle.point, spec.areaSeriesStyle?.point);
    }
}
const y1Accessor = (stackMode) => (d) => {
    if ((0, utils_1.isDatumFilled)(d)) {
        return null;
    }
    return stackMode === specs_1.StackMode.Percentage ? (d.y1 === null || d.y0 === null ? null : d.y1 - d.y0) : d.initialY1;
};
const y0Accessor = (stackMode) => (d) => {
    if ((0, utils_1.isDatumFilled)(d)) {
        return null;
    }
    return stackMode === specs_1.StackMode.Percentage ? d.y0 : d.initialY0;
};
function computeLegend(xDomain, dataSeries, seriesColors, specs, axesSpecs, settingsSpec, seriesIdentifierDataSeriesMap, theme, deselectedDataSeries = []) {
    const legendItems = [];
    const defaultColor = theme.colors.defaultVizColor;
    const legendValues = settingsSpec.legendValues ?? [];
    dataSeries.forEach((series) => {
        const { specId, yAccessor } = series;
        const banded = (0, series_1.isBandedSpec)(series.spec);
        const spec = (0, spec_1.getSpecsById)(specs, specId);
        const dataSeriesKey = (0, series_1.getSeriesKey)({
            specId: series.specId,
            yAccessor: series.yAccessor,
            splitAccessors: series.splitAccessors,
        }, series.groupId);
        const color = seriesColors.get(dataSeriesKey) || defaultColor;
        const hasSingleSeries = dataSeries.length === 1;
        const name = (0, series_1.getSeriesName)(series, hasSingleSeries, false, spec);
        const isSeriesHidden = deselectedDataSeries && (0, series_1.getSeriesIndex)(deselectedDataSeries, series) >= 0;
        if (name === '' || !spec)
            return;
        const postFixes = getPostfix(spec);
        const { yAxis } = (0, spec_1.getAxesSpecForSpecId)(axesSpecs, spec.groupId, settingsSpec.rotation);
        const formatter = spec.tickFormat ?? yAxis?.tickFormat ?? axis_utils_1.defaultTickFormatter;
        const { hideInLegend } = spec;
        const seriesIdentifier = (0, series_1.getSeriesIdentifierFromDataSeries)(series);
        const pointStyle = getPointStyle(spec, theme);
        const legendValuesItems = (0, get_legend_values_1.getLegendValues)(series, xDomain, legendValues, y1Accessor(series.stackMode), formatter);
        legendItems.push({
            depth: 0,
            color,
            label: banded ? getBandedLegendItemLabel(name, geometry_1.BandedAccessorType.Y1, postFixes) : name,
            seriesIdentifiers: [seriesIdentifier],
            childId: geometry_1.BandedAccessorType.Y1,
            isSeriesHidden,
            isItemHidden: hideInLegend,
            isToggleable: true,
            values: legendValuesItems,
            path: [{ index: 0, value: seriesIdentifier.key }],
            keys: [specId, spec.groupId, yAccessor, ...series.splitAccessors.values()],
            pointStyle,
        });
        if (banded) {
            const bandedLegendValuesItems = (0, get_legend_values_1.getLegendValues)(series, xDomain, legendValues, y0Accessor(series.stackMode), formatter);
            const labelY0 = getBandedLegendItemLabel(name, geometry_1.BandedAccessorType.Y0, postFixes);
            legendItems.push({
                depth: 0,
                color,
                label: labelY0,
                seriesIdentifiers: [seriesIdentifier],
                childId: geometry_1.BandedAccessorType.Y0,
                isSeriesHidden,
                isItemHidden: hideInLegend,
                isToggleable: true,
                values: bandedLegendValuesItems,
                path: [{ index: 0, value: seriesIdentifier.key }],
                keys: [specId, spec.groupId, yAccessor, ...series.splitAccessors.values()],
                pointStyle,
            });
        }
    });
    const baseLegendSortFn = (a, b) => {
        const aDs = seriesIdentifierDataSeriesMap[a.key];
        const bDs = seriesIdentifierDataSeriesMap[b.key];
        return (0, default_series_sort_fn_1.defaultXYLegendSeriesSort)(aDs, bDs);
    };
    const legendSort = settingsSpec.legendSort ?? baseLegendSortFn;
    return (0, group_data_series_1.groupBy)(legendItems.sort((a, b) => a.seriesIdentifiers[0] && b.seriesIdentifiers[0] ? legendSort(a.seriesIdentifiers[0], b.seriesIdentifiers[0]) : 0), ({ keys, childId }) => {
        return [...keys, childId].join('__');
    }, true)
        .map((d) => {
        if (!d[0])
            return;
        return {
            ...d[0],
            seriesIdentifiers: d.map(({ seriesIdentifiers: [s] }) => s).filter(common_1.isDefined),
            path: d.map(({ path: [p] }) => p).filter(common_1.isDefined),
        };
    })
        .filter(common_1.isDefined);
}
//# sourceMappingURL=legend.js.map