import { CellValue, IDisposable, LocaleService, Nullable } from '@univerjs/core';
import { Observable } from 'rxjs';
import { AreaLineStyle, AxisAlignEnum, AxisValueType, CategoryType, ChartBorderDashType, ChartSourceDataTypeEnum, ChartTrendlineType, ChartTypeBits, DataOrientation, InvalidValueType, IRuntimeAxisPosition, IRuntimeAxisPriority, LabelAlignEnum, LegendPositionEnum, LinePointShape, PieLabelPosition, RadarShape, RelationChartLayoutEnum, SelectModeEnum, SeriesLabelPosition, TitlePositionEnum, WaterfallSeriesTypeEnum, WaterfallStackTypeEnum, WordCloudShapeEnum } from './enum';
import { IEchartTheme } from './model/constants/build-in-theme';
import { BarSeriesOption } from './utils/echarts';
export type DeepPartial<T> = T extends Record<string, any> ? T extends any[] ? T : {
    [key in keyof T]+?: DeepPartial<T[key]>;
} : T;
export interface IChartDataSource {
    data$: Observable<IUniverDataSet>;
    canSwitchOrient$: Observable<boolean>;
    isRowDirection$: Observable<boolean>;
    convertDataSet(): IUniverDataSet;
    dispose(): void;
    getDataSet(): IUniverDataSet;
    getDimensionCount(): number;
    refresh(): void;
}
export type ChartDataSourceValue = Nullable<CellValue>;
export type ChartDataSourceValues = Array<Array<ChartDataSourceValue>>;
export interface IDimensionDefinition {
    type?: 'number' | 'ordinal' | 'time' | 'float' | 'int';
    name?: string;
    displayName?: string;
}
export type DimensionDefinitionLoose = IDimensionDefinition['name'] | IDimensionDefinition;
export type OptionDataValue = string | number | Date | null | undefined;
export interface IUniverDataSet {
    source: OptionDataValue[][];
    dimensions: Array<DimensionDefinitionLoose>;
    sourceType?: ChartSourceDataTypeEnum[][];
}
export interface IChartContext {
    headers?: string[];
    categoryType?: CategoryType;
    categoryIndex?: number;
    /**
     * the flag to indicate whether the chart use date axis, only all category data is date type, the chart will use date axis, if there are some string type data, the chart will use category axis even the flag is true.
     */
    useDateAxis?: boolean;
    categoryResourceIndexes?: number[];
    seriesIndexes?: number[];
    seriesResourceIndexes?: number[];
    transform?: {
        categoryIndex?: number;
        seriesIndexes?: number[];
    };
    bubbleSizeSeriesId?: number;
    bubbleXAxis?: number;
    bubbleYAxis?: number;
    bubbleLabel?: number;
    bubbleSeries?: number;
}
export interface IRelationNodes {
    id: string;
    category: string;
    name: string;
    value: number;
    symbolSize?: number;
}
export interface IRelationLink {
    source: string;
    target: string;
    value: number;
}
export interface IHeatmapAxisData {
    data: IChartDataItem[];
}
export interface IChartData {
    category?: IChartDataCategory;
    headers?: string[];
    series: IChartDataSeries[];
    maxValue: number;
    minValue: number;
    /**
     * the dataset of the chart, it should match echart dataset option
     */
    dataset?: IUniverDataSet;
    bubble?: {
        bubbleSizeData?: {
            id: string;
            name: string;
            items: IChartDataItem[];
        };
        bubbleXData?: {
            id: string;
            name: string;
            items: IChartDataItem[];
        };
        bubbleYData?: {
            id: string;
            name: string;
            items: IChartDataItem[];
        };
        bubbleLabelData?: {
            id: string;
            name: string;
            items: IChartDataItem[];
        };
        bubbleSeriesData?: {
            id: string;
            name: string;
            items: IChartDataItem[];
        };
        isValidateBubbleSource?: boolean;
    };
    heatmapData?: {
        xData: string[];
        yData: string[];
        values: number[][];
        isValidateHeatmapSource: boolean;
    };
    relationData?: {
        links: IRelationLink[];
        nodes: IRelationNodes[];
        categories: string[];
        max: number;
        min: number;
        isValidateRelationSource: boolean;
    };
    sankeyData?: {
        links: ISankeyLink[];
        nodes: ISankeyNode[];
        categories: string[];
        max: number;
        min: number;
        isValidateSankeySource: boolean;
        isCircular: boolean;
    };
}
export interface ISankeyNode {
    name: string;
}
export interface ISankeyLink {
    source: string;
    target: string;
    value: number;
}
export interface IChartDataCategory {
    index: number;
    name: string;
    type: CategoryType;
    useDateAxis: boolean;
    items: IChartDataItem[];
    keys: string[];
}
export interface IChartDataSeries {
    index: number;
    name: string;
    items: IChartDataItem[];
}
export interface IChartDataItem {
    value: OptionDataValue;
    label: string;
}
export interface IRuntimeAxis {
    priority: IRuntimeAxisPriority;
    position: IRuntimeAxisPosition;
    type: AxisValueType;
}
export interface IChartRuntimeContext {
    themeColors?: string[];
    axes: IRuntimeAxis[];
    themeInfo: IEchartTheme;
    /**
     * The function to transform the color to the render color with considering the system theme is dark mode or not.
     * @param {string} color - The color to be rendered.
     * @returns {string} - The color to be rendered.
     */
    getRenderColor(color: string): string;
    /**
     * The current theme is dark mode or not.
     */
    isDarkMode: boolean;
    hasSecondaryAxis: boolean;
    localeService: LocaleService;
    wordCloudImageMaskMap: Map<string, HTMLImageElement>;
}
export interface ILabelStyle {
    visible: boolean;
    content: string;
    fontSize: number;
    color: string;
    align: LabelAlignEnum;
    bold: boolean;
    family: string;
    strikethrough: boolean;
    italic: boolean;
    underline: boolean;
    padAngle: boolean;
    axisTitleAlign?: AxisAlignEnum | undefined;
    showMaxLabel?: boolean;
    showMinLabel?: boolean;
    rotate?: number;
}
export interface ILegendStyle {
    position?: LegendPositionEnum;
    label?: Omit<ILabelStyle, 'visible' | 'align' | 'content'>;
    selectMode?: SelectModeEnum;
}
export interface IGridLineStyle {
    visible: boolean;
    color: string;
    width: number;
}
export interface IAxisOptions {
    lineVisible: boolean;
    label: Omit<ILabelStyle, 'align' | 'content'>;
    lineStyle: IGridLineStyle;
    gridLine: IGridLineStyle;
    tick: {
        visible: boolean;
        lineWidth: number;
        lineColor: string;
        length: number;
        position: PieLabelPosition;
    };
    reverse?: boolean;
    min?: number | null;
    max?: number | null;
    format?: string;
}
export interface ISeriesLabelStyle extends ILabelStyle {
    contentType: number;
    position: SeriesLabelPosition;
}
export interface IPieLabelStyle extends Omit<ILabelStyle, 'align' | 'content'> {
    contentType: number;
    position: PieLabelPosition;
}
export interface IPointStyle {
    shape: LinePointShape;
    size: number;
    color: Nullable<string>;
}
export interface IDataPointStyle extends IPointStyle {
}
export interface ISeriesStyle {
    chartType?: ChartTypeBits.Line | ChartTypeBits.Column | ChartTypeBits.Area;
    rightYAxis?: boolean;
    color: Nullable<string>;
    fillOpacity: number;
    border: {
        opacity: number;
        color: Nullable<string>;
        width: number;
        dashType: ChartBorderDashType;
    };
    label: ISeriesLabelStyle;
    point: IPointStyle;
    dataPoints: {
        [index: number]: IDataPointStyle;
    };
    waterfall: {
        positive: ISeriesStyle & {
            name: string;
        };
        negative: ISeriesStyle & {
            name: string;
        };
        subtotal: ISeriesStyle & {
            name: string;
        };
    };
}
export type RightYAxisOptions = Omit<IAxisOptions, 'reverse'>;
export interface IAllSeriesStyle extends Pick<ISeriesStyle, 'border' | 'label' | 'rightYAxis' | 'point' | 'color' | 'waterfall'> {
}
export interface ITrendLine {
    seriesIndex: number;
    type: ChartTrendlineType;
    name: string;
    color?: string;
    width?: number;
    opacity?: number;
    dashType?: ChartBorderDashType;
    order?: number;
    period?: number;
    showFormula?: boolean;
    showR2?: boolean;
    r2Color?: string;
    formulaColor?: string;
}
export interface IChartStyle {
    runtime: IChartRuntimeContext;
    width: number;
    height: number;
    theme: string;
    invalidValueType: InvalidValueType;
    gradientFill: boolean;
    backgroundColor: Nullable<string>;
    titleFontSize: number;
    fontSize: number;
    fontColor: string;
    borderColor: Nullable<string>;
    titles: {
        title: Omit<ILabelStyle, 'visible'>;
        subtitle: Omit<ILabelStyle, 'visible'>;
        xAxisTitle: Omit<ILabelStyle, 'visible'>;
        yAxisTitle: Omit<ILabelStyle, 'visible'>;
        rightYAxisTitle: Omit<ILabelStyle, 'visible'>;
        titlePosition: TitlePositionEnum;
    };
    legend: ILegendStyle;
    xAxis: IAxisOptions;
    yAxis: IAxisOptions;
    rightYAxis: RightYAxisOptions;
    allSeriesStyle: IAllSeriesStyle;
    seriesStyleMap: {
        [id: string]: ISeriesStyle;
    };
    trendlines: ITrendLine[];
    pie: {
        doughnutHole: Nullable<number>;
        labelStyle: IPieLabelStyle;
        borderColor: string;
        hasPaddingAngle: boolean;
        isHalfPie: boolean;
        rosePie: boolean;
        showLabelLine: boolean;
        valueScale: number;
        valueSuffix: string;
        digitalFixed: number;
    };
    area: {
        lineStyle: AreaLineStyle;
    };
    radar: {
        shape: RadarShape;
        fill: boolean;
    };
    funnel: {
        gap: number;
        useAbsValue: boolean;
    };
    wordCloud: {
        shape: WordCloudShapeEnum;
        maskImage: string;
        repeat: boolean;
    };
    relation: {
        layout: RelationChartLayoutEnum;
        useValueAsSymbolSize: boolean;
        useEmphasis: boolean;
        force: IRelationForceOptions;
        circular: {
            rotateLabel: boolean;
        };
        nodeShape: LinePointShape;
    };
    waterfall: {
        stackType: WaterfallStackTypeEnum;
        useSubtotal: boolean;
    };
    tooltip: {
        indicatorLabelColor: string;
        indicatorLineType: ChartBorderDashType;
        indicatorLineColor: string;
        indicatorLabelTextColor: string;
    };
    pareto: {
        lineStyle: ISeriesStyle;
        barStyle: ISeriesStyle;
    };
    heatmap: {
        visualMapType: 'continuous' | 'piecewise';
        max?: number;
        min?: number;
    };
}
export interface IRelationForceOptions {
    repulsion?: number;
    edgeLength?: number;
    gravity?: number;
}
export type ChartStyle = DeepPartial<IChartStyle>;
export interface IChartDataAggregation {
    aggregate?: boolean;
    topN?: number;
}
export interface IChartConfig extends IChartData {
    type: ChartTypeBits;
}
export interface IChartSnapshot {
    id: string;
    chartType: ChartTypeBits;
    orient?: DataOrientation;
    context?: Pick<IChartContext, 'categoryIndex' | 'seriesIndexes' | 'transform'>;
    style?: ChartStyle;
    dataAggregation?: IChartDataAggregation;
}
export interface IWaterfallLegendData {
    name: string;
    color: string;
}
export interface IChartRenderSpecConverter<ChartRenderSpec = Record<string, any>> {
    canConvert: (config: IChartConfig) => boolean;
    convert: (config: IChartConfig, style: ChartStyle) => ChartRenderSpec;
}
export type ChartConfigInterceptor = (config: IChartConfig) => IChartConfig;
export type RenderSpecOperator<ChartRenderSpec> = (spec: ChartRenderSpec, style: ChartStyle, config: IChartConfig, instance: IChartInstance) => void;
export interface IChartRenderModelStylizeInit<Spec> {
    chartStyle: ChartStyle;
    chartConfig: IChartConfig;
    chartInstance?: IChartInstance<Spec>;
}
export interface IChartRenderModel<Spec extends Record<string, any> = Record<string, any>> extends IDisposable {
    toSpec(chartConfig: IChartConfig, style: ChartStyle): Spec;
    stylizeSpec(spec: Spec, stylizeInit: IChartRenderModelStylizeInit<Spec>, rect: IChartHostRect): Spec;
    updateWatermark(addWatermark: boolean): void;
    createChartInstance(): IChartInstance<Spec>;
    dispose(): void;
}
export interface IChartThemeOptions {
    colors: string[];
}
export interface IChartInstance<Spec = Record<string, any>> extends IDisposable {
    container: HTMLElement | string;
    mount(id: string | HTMLElement): void;
    render(spec: Spec, echartsProvider?: any): void;
    exportImg(): Promise<string>;
    onDispose?(dispose: () => void): void;
    resize(): void;
}
export interface IChartInstanceConstructor<Spec> {
    new (container: HTMLElement | string): IChartInstance<Spec>;
}
export type OptionalDataValue = number | string | null | undefined;
export type ExtractArrayItem<T> = T extends Array<infer U> ? U : never;
export type EChartSpec = echarts.EChartsOption;
export type EChartSeriesItem = ExtractArrayItem<EChartSpec['series']> & {
    rawData?: number[];
    seriesId: string;
};
export type EChartInstance = IChartInstance<EChartSpec>;
export type EChartRenderSpecOperator = RenderSpecOperator<EChartSpec>;
export interface IChartHostRect {
    width: number;
    height: number;
}
export type WaterfallBarSeriesOptionType = BarSeriesOption & {
    baseSeriesIndex: string;
    waterfallSeriesType: WaterfallSeriesTypeEnum;
};
