import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { granularityFor, minGranularityForIntervals, isPredefinedGranularity, } from '@cubejs-client/core';
import { Skeleton, Tag, tasty } from '@cube-dev/ui-kit';
import { memo, useCallback, useMemo } from 'react';
import { Col, Row, Statistic, Table } from 'antd';
import { Area, AreaChart, Bar, BarChart, CartesianGrid, Cell, Legend, Line, LineChart, Pie, PieChart, ResponsiveContainer, Tooltip, XAxis, YAxis, } from 'recharts';
import styled from 'styled-components';
import { CHART_COLORS, getChartColorByIndex, getChartSolidColorByIndex, } from '../utils/chart-colors';
import { formatDateByGranularity, formatDateByPattern } from '../utils/index';
import { LocalError } from './LocalError';
function CustomDot(props) {
    const { cx, cy, fill } = props;
    return (_jsx("svg", { x: cx - 5, y: cy - 5, width: 20, height: 20, fill: fill, children: _jsx("circle", { cx: 5, cy: 5, r: 2.5 }) }));
}
const intlNumberFormatter = Intl.NumberFormat('en', { notation: 'compact' });
const numberFormatter = (item) => typeof item === 'number' ? intlNumberFormatter.format(item) : item;
const StyledStatistic = styled(Statistic) `
  .ant-statistic-content {
    font-size: 40px;
  }
`;
const LegendTextElement = tasty({
    as: 'span',
    styles: {
        color: '#dark',
        preset: 't3',
    },
});
function isValidISOTimestamp(timestamp) {
    try {
        return new Date(timestamp + 'Z').toISOString() === timestamp + 'Z';
    }
    catch (e) {
        return false;
    }
}
function CartesianChart({ dataTransformer, pivotConfig, dateFormat, resultSet, children, ChartComponent, height, domain, grid, syncId, yAxisFormatter = numberFormatter, tooltipFormatter = numberFormatter, tooltipCursor = false, extra, }) {
    const legendFormatter = useCallback((value) => _jsx(LegendTextElement, { children: value }), []);
    const granularityField = Object.keys(resultSet?.loadResponse.results[0].data[0] || {}).find((key) => {
        return key.split('.').length === 3;
    });
    let granularity = granularityField?.split('.')[2];
    if (!isPredefinedGranularity(granularity)) {
        const granularityInfo = resultSet?.loadResponse.results[0]?.annotation.timeDimensions[granularityField]?.granularity;
        if (granularityInfo) {
            granularity = minGranularityForIntervals(granularityInfo.interval, granularityInfo.offset || granularityFor(granularityInfo.origin));
        }
    }
    const formatDate = useMemo(() => {
        if (dateFormat) {
            return (item) => isValidISOTimestamp(item) ? formatDateByPattern(new Date(item), dateFormat) : item;
        }
        return granularity
            ? (item) => isValidISOTimestamp(item)
                ? formatDateByGranularity(new Date(item), granularity)
                : item
            : (item) => item;
    }, [dateFormat]);
    const dateFormatter = useCallback((item) => {
        try {
            return formatDate(item);
        }
        catch (e) {
            return item;
        }
    }, [formatDate]);
    const chartPivot = useMemo(() => {
        let chartPivot = resultSet.chartPivot(pivotConfig);
        if (dataTransformer) {
            chartPivot = dataTransformer(chartPivot, { granularity });
        }
        return chartPivot.map((series) => {
            series.x = series.xValues
                .map((value) => {
                return formatDate(value);
            })
                .join(',');
            return series;
        });
    }, [resultSet, pivotConfig, dataTransformer, formatDate]);
    return (_jsx(ResponsiveContainer, { width: "100%", height: height, children: _jsxs(ChartComponent, { margin: { left: -10, top: 10 }, data: chartPivot, syncId: syncId, children: [_jsx(XAxis, { axisLine: false, tickLine: false, tickFormatter: dateFormatter, dataKey: "x", minTickGap: 20 }), _jsx(YAxis, { domain: domain, axisLine: false, tickLine: false, tickCount: domain ? 5 : undefined, tickFormatter: yAxisFormatter, scale: domain ? 'linear' : undefined, width: 80 }), _jsx(CartesianGrid, { vertical: grid === 'vertical' || grid === 'both', horizontal: grid === 'horizontal' || grid === 'both', stroke: "#f5f5f5" }), children, _jsx(Legend, { formatter: legendFormatter, iconType: "square", iconSize: 10 }), _jsx(Tooltip, { labelStyle: {
                        fontSize: 'var(--h6-font-size)',
                        lineHeight: 'var(--h6-line-height)',
                        fontWeight: 600,
                        color: 'var(--dark-color)',
                    }, itemStyle: {
                        fontSize: 'var(--t4-font-size)',
                        lineHeight: 'var(--t4-line-height)',
                        fontWeight: 600,
                        padding: 0,
                    }, labelFormatter: dateFormatter, formatter: tooltipFormatter, cursor: tooltipCursor }), extra ? extra() : null] }) }));
}
const TypeToChartComponent = {
    line: ({ resultSet, height, fill, stroke, dot, grid, domain, nameTransform, yAxisFormatter, tooltipFormatter, pivotConfig, dateFormat, dataTransformer, syncId, tooltipCursor, extra, }) => {
        let seriesNames = resultSet.seriesNames(pivotConfig);
        if (nameTransform) {
            nameTransform(seriesNames);
        }
        return (_jsx(CartesianChart, { dataTransformer: dataTransformer, pivotConfig: pivotConfig, dateFormat: dateFormat, resultSet: resultSet, height: height, domain: domain, syncId: syncId, grid: grid ?? 'horizontal', ChartComponent: LineChart, yAxisFormatter: yAxisFormatter, tooltipFormatter: tooltipFormatter, tooltipCursor: tooltipCursor, extra: extra, children: seriesNames.map((series, i) => (_jsx(Line, { type: "monotone", dataKey: series.key, name: series.title, dot: dot ?? CustomDot, stroke: stroke?.[series.shortTitle] ?? stroke?.[i] ?? getChartColorByIndex(i), fill: fill?.[series.shortTitle] ?? fill?.[i] ?? getChartColorByIndex(i), animationDuration: 150 }, series.key))) }));
    },
    bar: ({ resultSet, domain, nameTransform, height, fill, grid, yAxisFormatter, tooltipFormatter, pivotConfig, dateFormat, dataTransformer, syncId, tooltipCursor, }) => {
        let seriesNames = resultSet.seriesNames(pivotConfig);
        if (nameTransform) {
            nameTransform(seriesNames);
        }
        return (_jsx(CartesianChart, { dataTransformer: dataTransformer, pivotConfig: pivotConfig, resultSet: resultSet, height: height, domain: domain, syncId: syncId, grid: grid ?? 'horizontal', dateFormat: dateFormat, ChartComponent: BarChart, yAxisFormatter: yAxisFormatter, tooltipFormatter: tooltipFormatter, tooltipCursor: tooltipCursor, children: seriesNames.map((series, i) => (_jsx(Bar, { stackId: "a", dataKey: series.key, name: series.title, fill: fill?.[series.shortTitle] ?? fill?.[i] ?? getChartSolidColorByIndex(i), animationDuration: 150 }, series.key))) }));
    },
    area: ({ resultSet, domain, nameTransform, height, stroke, fill, grid, pivotConfig, yAxisFormatter, tooltipFormatter, dateFormat, syncId, tooltipCursor, dataTransformer, }) => {
        let seriesNames = resultSet.seriesNames(pivotConfig);
        if (nameTransform) {
            nameTransform(seriesNames);
        }
        return (_jsx(CartesianChart, { dataTransformer: dataTransformer, pivotConfig: pivotConfig, resultSet: resultSet, height: height, domain: domain, grid: grid ?? 'horizontal', syncId: syncId, dateFormat: dateFormat, ChartComponent: AreaChart, yAxisFormatter: yAxisFormatter, tooltipFormatter: tooltipFormatter, tooltipCursor: tooltipCursor, children: seriesNames.map((series, i) => (_jsx(Area, { stackId: "a", dataKey: series.key, name: series.title, fillOpacity: 0.9, stroke: stroke?.[series.shortTitle] ?? stroke?.[i] ?? getChartSolidColorByIndex(i), fill: fill?.[series.shortTitle] ?? fill?.[i] ?? getChartSolidColorByIndex(i), strokeWidth: 0, animationDuration: 150, type: "monotone" }, series.key))) }));
    },
    pie: ({ resultSet, nameTransform, pivotConfig, height, fill, stroke }) => {
        let seriesNames = resultSet.seriesNames(pivotConfig);
        if (nameTransform) {
            nameTransform(seriesNames);
        }
        return (_jsx(ResponsiveContainer, { width: "100%", height: height, children: _jsxs(PieChart, { children: [_jsx(Pie, { isAnimationActive: false, data: resultSet.chartPivot(), nameKey: "x", dataKey: seriesNames[0].key, fill: "#8884d8", children: resultSet.chartPivot(pivotConfig).map((e, index) => {
                            const i = index % (stroke?.length ?? CHART_COLORS.length);
                            return (_jsx(Cell, { stroke: stroke?.[i] ?? getChartSolidColorByIndex(i), fill: fill?.[i] ?? getChartSolidColorByIndex(i) }, index));
                        }) }), _jsx(Legend, {}), _jsx(Tooltip, {})] }) }));
    },
    table: ({ isLoading, resultSet, height, pivotConfig }) => {
        const columnData = resultSet?.tableColumns(pivotConfig);
        const dataSet = resultSet?.tablePivot(pivotConfig);
        const granularityMap = {};
        let headerSize = 1;
        Object.keys(dataSet[0] || {}).forEach((key) => {
            const size = key.split(',').length;
            if (size > headerSize) {
                headerSize = size;
            }
        });
        columnData.forEach((field, i) => {
            if (field.key && typeof field.key === 'string') {
                granularityMap[field.key] = field.key.split('.')[2];
            }
            else {
                field.key = `key${i}`; // fallback index
            }
        });
        return (_jsx(Table, { loading: isLoading, tableLayout: "auto", locale: {
                emptyText: 'There is no data for the selected time interval and filters. Try updating the filters above',
            }, pagination: false, columns: columnData.map((c) => {
                const column = { ...c, dataIndex: c.key, title: c.shortTitle };
                const granularity = granularityMap[c.key];
                return {
                    width: 90,
                    ...column,
                    render: granularity
                        ? (text) => {
                            try {
                                return isValidISOTimestamp(text)
                                    ? formatDateByGranularity(new Date(text), granularity)
                                    : text;
                            }
                            catch (e) {
                                return text;
                            }
                        }
                        : (text) => {
                            switch (typeof text) {
                                case 'boolean':
                                    return text ? 'true' : 'false';
                                case 'undefined':
                                case 'object':
                                    return text === null ? _jsx(Tag, { children: "NULL" }) : _jsx(Tag, { children: "OBJECT" });
                                default:
                                    if (c.type === 'boolean') {
                                        return text && text !== '0' ? 'true' : 'false';
                                    }
                                    return text;
                            }
                        },
                };
            }), dataSource: dataSet, scroll: { y: height - headerSize * 60, x: 'max-content' } }));
    },
    number: ({ resultSet }) => (_jsx(Row, { justify: "center", align: "middle", style: {
            height: '100%',
        }, children: _jsx(Col, { children: resultSet.seriesNames().map((s) => (_jsx(StyledStatistic, { value: resultSet.totalRow()[s.key] || 'No data' }, s.key))) }) })),
};
const TypeToMemoChartComponent = Object.keys(TypeToChartComponent)
    .map((key) => ({
    [key]: memo(TypeToChartComponent[key]),
}))
    .reduce((a, b) => ({ ...a, ...b }));
const renderChart = (Component) => function ({ resultSet, error, ...restParams }, chartType) {
    if (error) {
        return _jsx(LocalError, { error: error });
    }
    if (chartType === 'table') {
        return _jsx(Component, { ...restParams, resultSet: resultSet });
    }
    return ((resultSet && _jsx(Component, { ...restParams, resultSet: resultSet })) || (_jsx(Skeleton, { layout: "chart", fill: "#white", height: restParams.height })));
};
export function PlaygroundChartRenderer({ query, chartType, resultSet, component, chartHeight, ...rest }) {
    const componentToRender = component || TypeToMemoChartComponent[chartType];
    if (componentToRender) {
        return renderChart(componentToRender)({
            height: chartHeight,
            ...rest,
            grid: 'both',
            resultSet,
        }, chartType);
    }
    return null;
}
//# sourceMappingURL=ChartRenderer.js.map