import { color as d3Color } from 'd3-color';
import { isArrayOrTypedArray } from '@fluentui/chart-utilities';
import { areArraysEqual } from '../../utilities/utilities';
import { DataVizPalette, getColorFromToken, getNextColor } from '../../utilities/colors';
import { scaleLinear as d3ScaleLinear } from 'd3-scale';
const DEFAULT_PLOTLY_COLORWAY = [
    '#636efa',
    '#ef553b',
    '#00cc96',
    '#ab63fa',
    '#ffa15a',
    '#19d3f3',
    '#ff6692',
    '#b6e880',
    '#ff97ff',
    '#fecb52'
];
// Default D3 qualitative colorway (Category10), matching Plotly Express px.colors.qualitative.D3
// Source: https://plotly.com/python/discrete-color/#:~:text=Join%20now.-,Color%20Sequences%20in%20Plotly%20Express,-By%20default%2C%20Plotly
export const DEFAULT_D3_COLORWAY = [
    '#1f77b4',
    '#ff7f0e',
    '#2ca02c',
    '#d62728',
    '#9467bd',
    '#8c564b',
    '#e377c2',
    '#7f7f7f',
    '#bcbd22',
    '#17becf'
];
const PLOTLY_FLUENTVIZ_COLORWAY_MAPPING = [
    DataVizPalette.color1,
    DataVizPalette.warning,
    DataVizPalette.color8,
    DataVizPalette.color4,
    DataVizPalette.color7,
    DataVizPalette.color6,
    DataVizPalette.color2,
    DataVizPalette.color5,
    DataVizPalette.color9,
    DataVizPalette.color10
];
// Mapping from D3 Category10 order to Fluent DataViz tokens (light/dark handled via getColorFromToken)
// D3: [blue, orange, green, red, purple, brown, pink, gray, olive, cyan]
export const D3_FLUENTVIZ_COLORWAY_MAPPING = [
    DataVizPalette.color26,
    DataVizPalette.warning,
    DataVizPalette.color5,
    DataVizPalette.error,
    DataVizPalette.color4,
    DataVizPalette.color17,
    DataVizPalette.color22,
    DataVizPalette.disabled,
    DataVizPalette.color10,
    DataVizPalette.color3
];
function getPlotlyColorway(colorway, isDonut = false) {
    if (!colorway || !isArrayOrTypedArray(colorway)) {
        return 'others';
    }
    const lower = colorway.map((c)=>c.toLowerCase());
    if (isDonut && areArraysEqual(lower, D3_FLUENTVIZ_COLORWAY_MAPPING)) {
        return 'd3';
    }
    if (areArraysEqual(lower, DEFAULT_PLOTLY_COLORWAY)) {
        return 'plotly';
    }
    return 'others';
}
function tryMapFluentDataViz(hexColor, templateColorway, isDarkTheme, isDonut) {
    if (templateColorway !== 'plotly') {
        return hexColor;
    }
    let defaultColorway = DEFAULT_PLOTLY_COLORWAY;
    let defaultMapping = PLOTLY_FLUENTVIZ_COLORWAY_MAPPING;
    if (isDonut) {
        defaultColorway = templateColorway === 'plotly' ? DEFAULT_PLOTLY_COLORWAY : DEFAULT_D3_COLORWAY;
        defaultMapping = templateColorway === 'plotly' ? PLOTLY_FLUENTVIZ_COLORWAY_MAPPING : D3_FLUENTVIZ_COLORWAY_MAPPING;
    }
    const idx = defaultColorway.indexOf(hexColor.toLowerCase());
    if (idx !== -1) {
        return getColorFromToken(defaultMapping[idx], !!isDarkTheme);
    }
    return hexColor;
}
export const getColor = (legendLabel, colorMap, templateColorway, isDarkTheme, isDonut)=>{
    if (!colorMap.current.has(legendLabel)) {
        let nextColor;
        const defaultColorMapping = isDonut ? templateColorway === 'plotly' ? PLOTLY_FLUENTVIZ_COLORWAY_MAPPING : D3_FLUENTVIZ_COLORWAY_MAPPING : PLOTLY_FLUENTVIZ_COLORWAY_MAPPING;
        if (colorMap.current.size < defaultColorMapping.length) {
            // Get first 10 colors from plotly-fluentviz colorway mapping
            nextColor = getColorFromToken(defaultColorMapping[colorMap.current.size], isDarkTheme);
        } else {
            nextColor = getNextColor(colorMap.current.size, 0, isDarkTheme);
        }
        colorMap.current.set(legendLabel, nextColor);
        return nextColor;
    }
    return colorMap.current.get(legendLabel);
};
export const getSchemaColors = (colorway, colors, colorMap, isDarkTheme, isDonut)=>{
    const hexColors = [];
    if (!colors) {
        return undefined;
    }
    const templateColorway = getPlotlyColorway(colorway, isDonut);
    if (isArrayOrTypedArray(colors)) {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        colors.forEach((element, index)=>{
            const colorString = element === null || element === void 0 ? void 0 : element.toString().trim();
            const nextFluentColor = getColor(`Label_${index}`, colorMap, templateColorway, isDarkTheme, isDonut);
            if (colorString) {
                const parsedColor = d3Color(colorString);
                hexColors.push(parsedColor ? tryMapFluentDataViz(parsedColor.formatHex(), templateColorway, isDarkTheme) : nextFluentColor);
            } else {
                hexColors.push(nextFluentColor);
            }
        });
    } else if (typeof colors === 'string') {
        const parsedColor = d3Color(colors);
        return parsedColor ? tryMapFluentDataViz(parsedColor.formatHex(), templateColorway, isDarkTheme) : getColor('Label_0', colorMap, templateColorway, isDarkTheme, isDonut);
    }
    return hexColors;
};
export const extractColor = (colorway, colorwayType, colors, colorMap, isDarkTheme, isDonut)=>{
    return colorwayType === 'default' && colors ? getSchemaColors(colorway, colors, colorMap, isDarkTheme, isDonut) : undefined;
};
export const resolveColor = (extractedColors, index, legend, colorMap, colorway, isDarkTheme, isDonut)=>{
    let color = '';
    const templateColorway = getPlotlyColorway(colorway, isDonut);
    if (extractedColors && isArrayOrTypedArray(extractedColors) && extractedColors.length > 0) {
        color = extractedColors[index % extractedColors.length];
    } else if (typeof extractedColors === 'string') {
        color = extractedColors;
    } else {
        color = getColor(legend, colorMap, templateColorway, isDarkTheme, isDonut);
    }
    return color;
};
export const getOpacity = (series, index)=>{
    var _series_marker, _series_marker1, _series_marker2, _series_marker3, _series_marker4;
    var _series_opacity;
    return ((_series_marker = series.marker) === null || _series_marker === void 0 ? void 0 : _series_marker.opacity) ? isArrayOrTypedArray((_series_marker1 = series.marker) === null || _series_marker1 === void 0 ? void 0 : _series_marker1.opacity) ? ((_series_marker2 = series.marker) === null || _series_marker2 === void 0 ? void 0 : _series_marker2.opacity)[index % ((_series_marker3 = series.marker) === null || _series_marker3 === void 0 ? void 0 : _series_marker3.opacity).length] : (_series_marker4 = series.marker) === null || _series_marker4 === void 0 ? void 0 : _series_marker4.opacity : (_series_opacity = series.opacity) !== null && _series_opacity !== void 0 ? _series_opacity : 1;
};
export const createColorScale = (layout, series, currentColorScale)=>{
    var _layout_coloraxis_colorscale, _layout_coloraxis, _series_marker, _series_marker1, _series_marker_color, _series_marker2;
    if ((layout === null || layout === void 0 ? void 0 : (_layout_coloraxis = layout.coloraxis) === null || _layout_coloraxis === void 0 ? void 0 : (_layout_coloraxis_colorscale = _layout_coloraxis.colorscale) === null || _layout_coloraxis_colorscale === void 0 ? void 0 : _layout_coloraxis_colorscale.length) && isArrayOrTypedArray((_series_marker = series.marker) === null || _series_marker === void 0 ? void 0 : _series_marker.color) && ((_series_marker1 = series.marker) === null || _series_marker1 === void 0 ? void 0 : _series_marker1.color).length > 0 && typeof ((_series_marker2 = series.marker) === null || _series_marker2 === void 0 ? void 0 : (_series_marker_color = _series_marker2.color) === null || _series_marker_color === void 0 ? void 0 : _series_marker_color[0]) === 'number') {
        var _layout_coloraxis1, _series_marker3, _layout_coloraxis2, _layout_coloraxis3;
        const scale = layout === null || layout === void 0 ? void 0 : (_layout_coloraxis1 = layout.coloraxis) === null || _layout_coloraxis1 === void 0 ? void 0 : _layout_coloraxis1.colorscale;
        const colorValues = (_series_marker3 = series.marker) === null || _series_marker3 === void 0 ? void 0 : _series_marker3.color;
        var _layout_coloraxis_cmin, _layout_coloraxis_cmax;
        const [dMin, dMax] = [
            (_layout_coloraxis_cmin = layout === null || layout === void 0 ? void 0 : (_layout_coloraxis2 = layout.coloraxis) === null || _layout_coloraxis2 === void 0 ? void 0 : _layout_coloraxis2.cmin) !== null && _layout_coloraxis_cmin !== void 0 ? _layout_coloraxis_cmin : Math.min(...colorValues),
            (_layout_coloraxis_cmax = layout === null || layout === void 0 ? void 0 : (_layout_coloraxis3 = layout.coloraxis) === null || _layout_coloraxis3 === void 0 ? void 0 : _layout_coloraxis3.cmax) !== null && _layout_coloraxis_cmax !== void 0 ? _layout_coloraxis_cmax : Math.max(...colorValues)
        ];
        // Normalize colorscale domain to actual data domain
        const scaleDomain = scale.map(([pos])=>dMin + pos * (dMax - dMin));
        const scaleColors = scale.map((item)=>item[1]);
        return d3ScaleLinear().domain(scaleDomain).range(scaleColors);
    }
    return currentColorScale;
};
