import { __assign } from "tslib";
/* eslint-disable @typescript-eslint/naming-convention */
import * as React from 'react';
import { useTheme } from '@fluentui/react';
import { DonutChart } from '../DonutChart/index';
import { VerticalStackedBarChart } from '../VerticalStackedBarChart/index';
import { decodeBase64Fields } from '@fluentui/chart-utilities';
import { isArrayOrTypedArray, isDateArray, isNumberArray, mapFluentChart, sanitizeJson, } from '@fluentui/chart-utilities';
import { isMonthArray, correctYearMonth, transformPlotlyJsonToDonutProps, transformPlotlyJsonToVSBCProps, transformPlotlyJsonToScatterChartProps, transformPlotlyJsonToHorizontalBarWithAxisProps, transformPlotlyJsonToHeatmapProps, transformPlotlyJsonToSankeyProps, transformPlotlyJsonToGaugeProps, transformPlotlyJsonToGVBCProps, transformPlotlyJsonToVBCProps, projectPolarToCartesian, } from './PlotlySchemaAdapter';
import { LineChart } from '../LineChart/index';
import { HorizontalBarChartWithAxis } from '../HorizontalBarChartWithAxis/index';
import { AreaChart } from '../AreaChart/index';
import { HeatMapChart } from '../HeatMapChart/index';
import { SankeyChart } from '../SankeyChart/SankeyChart';
import { GaugeChart } from '../GaugeChart/index';
import { GroupedVerticalBarChart } from '../GroupedVerticalBarChart/index';
import { VerticalBarChart } from '../VerticalBarChart/index';
import { withResponsiveContainer } from '../ResponsiveContainer/withResponsiveContainer';
var ResponsiveDonutChart = withResponsiveContainer(DonutChart);
var ResponsiveVerticalStackedBarChart = withResponsiveContainer(VerticalStackedBarChart);
var ResponsiveLineChart = withResponsiveContainer(LineChart);
var ResponsiveHorizontalBarChartWithAxis = withResponsiveContainer(HorizontalBarChartWithAxis);
var ResponsiveAreaChart = withResponsiveContainer(AreaChart);
var ResponsiveHeatMapChart = withResponsiveContainer(HeatMapChart);
var ResponsiveSankeyChart = withResponsiveContainer(SankeyChart);
var ResponsiveGaugeChart = withResponsiveContainer(GaugeChart);
var ResponsiveGroupedVerticalBarChart = withResponsiveContainer(GroupedVerticalBarChart);
var ResponsiveVerticalBarChart = withResponsiveContainer(VerticalBarChart);
var useColorMapping = function () {
    var colorMap = React.useRef(new Map());
    return colorMap;
};
/**
 * DeclarativeChart component.
 * {@docCategory DeclarativeChart}
 */
export var DeclarativeChart = React.forwardRef(function (props, forwardedRef) {
    var _a, _b;
    var plotlySchema = sanitizeJson(props.chartSchema).plotlySchema;
    var chart = mapFluentChart(plotlySchema);
    if (!chart.isValid) {
        throw new Error("Invalid chart schema: ".concat(chart.errorMessage));
    }
    var plotlyInput = plotlySchema;
    try {
        plotlyInput = decodeBase64Fields(plotlyInput);
    }
    catch (error) {
        throw new Error("Failed to decode plotly schema: ".concat(error));
    }
    var plotlyInputWithValidData = __assign(__assign({}, plotlyInput), { data: chart.validTracesInfo.map(function (trace) { return plotlyInput.data[trace[0]]; }) });
    var selectedLegends = plotlySchema.selectedLegends;
    var colorMap = useColorMapping();
    var theme = useTheme();
    var isDarkTheme = (_a = theme === null || theme === void 0 ? void 0 : theme.isInverted) !== null && _a !== void 0 ? _a : false;
    var chartRef = React.useRef(null);
    if (!isArrayOrTypedArray(selectedLegends)) {
        selectedLegends = [];
    }
    var _c = React.useState(selectedLegends), activeLegends = _c[0], setActiveLegends = _c[1];
    var onActiveLegendsChange = function (keys) {
        setActiveLegends(keys);
        if (props.onSchemaChange) {
            props.onSchemaChange({ plotlySchema: { plotlyInput: plotlyInput, selectedLegends: keys } });
        }
    };
    React.useEffect(function () {
        // eslint-disable-next-line @typescript-eslint/no-shadow
        var plotlySchema = sanitizeJson(props.chartSchema).plotlySchema;
        // eslint-disable-next-line @typescript-eslint/no-shadow
        var selectedLegends = plotlySchema.selectedLegends;
        setActiveLegends(selectedLegends !== null && selectedLegends !== void 0 ? selectedLegends : []);
    }, [props.chartSchema]);
    var multiSelectLegendProps = {
        canSelectMultipleLegends: true,
        onChange: onActiveLegendsChange,
        selectedLegends: activeLegends,
    };
    var commonProps = {
        legendProps: multiSelectLegendProps,
        componentRef: chartRef,
        calloutProps: { layerProps: { eventBubblingEnabled: true } },
    };
    var renderLineArea = function (plotlyData, isAreaChart) {
        var _a;
        var isScatterMarkers = ((_a = plotlyData[0]) === null || _a === void 0 ? void 0 : _a.mode) === 'markers';
        var chartProps = __assign(__assign({}, transformPlotlyJsonToScatterChartProps({ data: plotlyData, layout: plotlyInput.layout }, isAreaChart, colorMap, isDarkTheme)), commonProps);
        if (isAreaChart) {
            return React.createElement(ResponsiveAreaChart, __assign({}, chartProps));
        }
        return React.createElement(ResponsiveLineChart, __assign({}, chartProps, { lineMode: isScatterMarkers ? 'scatter' : 'default' }));
    };
    var checkAndRenderChart = function (isAreaChart) {
        if (isAreaChart === void 0) { isAreaChart = false; }
        var fallbackVSBC = false;
        var xValues = plotlyInputWithValidData.data[0].x;
        var isXDate = isDateArray(xValues);
        var isXNumber = isNumberArray(xValues);
        var isXMonth = isMonthArray(xValues);
        if (isXDate || isXNumber) {
            return renderLineArea(plotlyInputWithValidData.data, isAreaChart);
        }
        else if (isXMonth) {
            var updatedData = plotlyInputWithValidData.data.map(function (dataPoint) { return (__assign(__assign({}, dataPoint), { x: correctYearMonth(dataPoint.x) })); });
            return renderLineArea(updatedData, isAreaChart);
        }
        // Unsupported schema, render as VerticalStackedBarChart
        fallbackVSBC = true;
        return (React.createElement(ResponsiveVerticalStackedBarChart, __assign({}, transformPlotlyJsonToVSBCProps(plotlyInputWithValidData, colorMap, isDarkTheme, fallbackVSBC), commonProps)));
    };
    var exportAsImage = React.useCallback(function (opts) {
        return new Promise(function (resolve, reject) {
            if (!chartRef.current || typeof chartRef.current.toImage !== 'function') {
                return reject(Error('Chart cannot be exported as image'));
            }
            chartRef.current
                .toImage(__assign({ background: theme.semanticColors.bodyBackground, scale: 5 }, opts))
                .then(resolve)
                .catch(reject);
        });
    }, [theme]);
    React.useImperativeHandle(props.componentRef, function () { return ({
        exportAsImage: exportAsImage,
    }); }, [exportAsImage]);
    switch (chart.type) {
        case 'donut':
            return (React.createElement(ResponsiveDonutChart, __assign({}, transformPlotlyJsonToDonutProps(plotlyInputWithValidData, colorMap, isDarkTheme), commonProps)));
        case 'horizontalbar':
            return (React.createElement(ResponsiveHorizontalBarChartWithAxis, __assign({}, transformPlotlyJsonToHorizontalBarWithAxisProps(plotlyInputWithValidData, colorMap, isDarkTheme), commonProps)));
        case 'groupedverticalbar':
            return (React.createElement(ResponsiveGroupedVerticalBarChart, __assign({}, transformPlotlyJsonToGVBCProps(plotlyInputWithValidData, colorMap, isDarkTheme), commonProps)));
        case 'verticalstackedbar':
            return (React.createElement(ResponsiveVerticalStackedBarChart, __assign({}, transformPlotlyJsonToVSBCProps(plotlyInputWithValidData, colorMap, isDarkTheme), commonProps)));
        case 'heatmap':
            return (React.createElement(ResponsiveHeatMapChart, __assign({}, transformPlotlyJsonToHeatmapProps(plotlyInputWithValidData), commonProps, { legendProps: {} })));
        case 'sankey':
            return (React.createElement(ResponsiveSankeyChart, __assign({}, transformPlotlyJsonToSankeyProps(plotlyInputWithValidData, colorMap, isDarkTheme), commonProps)));
        case 'gauge':
            return (React.createElement(ResponsiveGaugeChart, __assign({}, transformPlotlyJsonToGaugeProps(plotlyInputWithValidData, colorMap, isDarkTheme), commonProps)));
        case 'verticalbar':
            return (React.createElement(ResponsiveVerticalBarChart, __assign({}, transformPlotlyJsonToVBCProps(plotlyInputWithValidData, colorMap, isDarkTheme), commonProps)));
        case 'area':
        case 'line':
        case 'fallback':
        case 'scatterpolar':
            if (chart.type === 'scatterpolar') {
                var cartesianProjection = projectPolarToCartesian(plotlyInputWithValidData);
                plotlyInputWithValidData.data = cartesianProjection.data;
            }
            // Need recheck for area chart as we don't have ability to check for valid months in previous step
            var isAreaChart = plotlyInputWithValidData.data.some(function (series) { return series.fill === 'tonexty' || series.fill === 'tozeroy' || !!series.stackgroup; });
            return checkAndRenderChart(isAreaChart);
        default:
            throw new Error("Unsupported chart type :".concat((_b = plotlyInputWithValidData.data[0]) === null || _b === void 0 ? void 0 : _b.type));
    }
});
DeclarativeChart.displayName = 'DeclarativeChart';
//# sourceMappingURL=DeclarativeChart.js.map