import { CSSProperties } from 'react';
import { DOMAttributes } from 'react';
import { ForwardedRef } from 'react';
import { JSX } from 'react/jsx-runtime';
import { ReactElement } from 'react';
import { ReactNode } from 'react';
import { SVGProps } from 'react';

declare type ActiveBar = CSSProperties | boolean;

declare type Axes = {
    [key: string | number]: Axis;
};

declare interface Axis {
    id: number | string;
    min: number;
    max: number;
    xAxis: {
        domain: number[];
        range: number[];
    };
    yAxis: {
        domain: number[];
        range: number[];
    };
    getX: (x: number) => number;
    getY: (y: number | null) => number;
    getPoint: (point: [number, number | null]) => [number, number];
}

export declare const Bar: {
    <TData>(props: BarProps<TData>): JSX.Element | null;
    displayName: string;
};

export declare type BarProps<TData> = Omit<PresentationAttributesWithProps<SVGPathElement>, "points" | "name" | "radius"> & BarShapeProps & InternalShapeProps<TData>;

declare interface BarShapeExtraProps extends ShapeProps {
    radius?: SparklinesRadius;
    activeBar?: ActiveBar;
    barWidth?: number;
    maxBarWidth?: number;
    barGap?: number | string;
    positive?: Omit<PresentationAttributesWithProps<SVGPathElement>, "points" | "name" | "radius" | "width" | "height"> & {
        radius?: SparklinesRadius;
    };
    negative?: Omit<PresentationAttributesWithProps<SVGPathElement>, "points" | "name" | "radius" | "width" | "height"> & {
        radius?: SparklinesRadius;
    };
}

declare type BarShapeProps = Omit<PresentationAttributesWithProps<SVGPathElement>, "points" | "name" | "radius" | "width" | "height"> & BarShapeExtraProps;

declare type DataKey = string | number;

declare interface DotProps extends SVGProps<SVGCircleElement> {
    className?: string;
    cx?: number;
    cy?: number;
    r?: number;
    dot?: ReactElement<SVGElement> | ((props: DotProps) => ReactElement<SVGElement>);
    show?: LineDotsVisibility;
    color?: string;
}

declare interface InternalShapeProps<TData> {
    sparklineData?: UseSparklineData<TData>;
    data?: SparklineData<TData>;
    width?: number;
    height?: number;
    margin?: SparklinesMargin;
    withBarAdjustment?: boolean;
    activeIndex?: number | null;
    clipPathId?: string;
    tooltip?: boolean;
    startAtZero?: boolean;
    zeroBaseline?: boolean;
}

export declare const Line: {
    <TData>(props: LineProps<TData>): JSX.Element | null;
    displayName: string;
};

declare type LineDot = ReactElement<SVGElement> | ((props: DotProps) => ReactElement<SVGElement>) | DotProps | boolean | undefined | null;

declare type LineDotsVisibility = "START" | "END" | "START_END" | boolean;

export declare type LineProps<TData> = Omit<PresentationAttributesWithProps<SVGPathElement>, "points" | "name"> & LineShapeProps & InternalShapeProps<TData>;

declare interface LineShapeExtraProps extends ShapeProps {
    dots?: LineDot;
    activeDot?: LineDot;
    curved?: boolean | number;
    connectNulls?: boolean;
}

declare type LineShapeProps = Omit<PresentationAttributesWithProps<SVGPathElement>, "points" | "name" | "width" | "height"> & LineShapeExtraProps;

declare type Margin = {
    top: number;
    right: number;
    bottom: number;
    left: number;
};

declare type PresentationAttributesWithProps<T> = Omit<SVGProps<T>, keyof DOMAttributes<T>>;

export declare const ReferenceLine: <TData>({ x, y, data, ...rest }: ReferenceLineProps<TData>) => JSX.Element | null;

declare interface ReferenceLineExtraProps extends ShapeProps {
    x?: number | string;
    y?: number;
}

export declare type ReferenceLineProps<TData> = Omit<PresentationAttributesWithProps<SVGLineElement>, "points"> & ReferenceLineExtraProps & InternalShapeProps<TData>;

declare interface ShapeProps {
    dataKey?: DataKey;
    style?: CSSProperties;
    labelColor?: string;
    name?: string;
    axis?: string | number;
}

declare interface SparklineData<TData> {
    dataKey: DataKey;
    color: string;
    axis: Axis;
    entries: SparklineDataEntry<TData>[];
    values: (number | null)[];
    points: [number, number | null][];
    pointsDefined: [number, number][];
    coords: [number, number][];
}

declare interface SparklineDataEntry<TData> {
    label: any;
    dataKey: DataKey;
    x: number;
    y: number | null;
    index: number;
    original: TData;
    color: string;
}

declare interface SparklineOptions {
    max?: number;
    min?: number;
    startAtZero?: boolean;
    zeroBaseline?: boolean;
    withBarAdjustment?: boolean;
    limit?: number;
    height: number;
    width: number;
    margin: Margin;
}

export declare const SparklinesBar: <TData>(props: SparklinesBarProps<TData> & {
    ref?: ForwardedRef<SVGRectElement>;
}) => ReturnType<typeof SparklinesBarInner>;

declare const SparklinesBarInner: <TData>({ height, activeBar, barWidth, maxBarWidth, barGap, max, width, withBarAdjustment, children, radius, preserveAspectRatio, min, margin, limit, style, data, dataKey, clip, name, label, onMouseMove, onMouseEnter, onMouseLeave, labelColor, onClick, startAtZero, zeroBaseline, positive, negative, ...rest }: SparklinesBarProps<TData>, ref: ForwardedRef<SVGRectElement>) => JSX.Element;

export declare type SparklinesBarProps<TData> = SparklinesComposedProps<TData> & BarShapeProps;

export declare const SparklinesComposed: <TData>(props: SparklinesComposedProps<TData> & {
    ref?: ForwardedRef<SVGRectElement>;
}) => ReturnType<typeof SparklinesComposedInner>;

declare const SparklinesComposedInner: <TData>({ data, width, height, margin, children, max, min, limit, preserveAspectRatio, style, label, withBarAdjustment, clip, startAtZero, onMouseMove, onMouseEnter, onMouseLeave, onClick, zeroBaseline, ...rest }: SparklinesComposedProps<TData>, ref: ForwardedRef<SVGRectElement>) => JSX.Element;

export declare interface SparklinesComposedProps<TData> {
    margin?: SparklinesMargin;
    min?: number;
    max?: number;
    data?: TData[];
    limit?: number;
    width?: number;
    height?: number;
    preserveAspectRatio?: string;
    style?: CSSProperties;
    withBarAdjustment?: boolean;
    label?: ReactNode;
    children?: any;
    clip?: boolean;
    startAtZero?: boolean;
    zeroBaseline?: boolean;
    onMouseMove?: (event: MouseEvent, data: SparklinesEventData<TData>) => void;
    onMouseLeave?: (event: MouseEvent, data: SparklinesEventData<TData>) => void;
    onMouseEnter?: (event: MouseEvent, data: SparklinesEventData<TData>) => void;
    onClick?: (event: MouseEvent, data: SparklinesEventData<TData>) => void;
}

export declare interface SparklinesDataEntry<TData> {
    dataKey: DataKey;
    x: number;
    y: number;
    value: number | null;
    index: number;
    entry: TData;
    color: string;
}

export declare interface SparklinesEventData<TData> {
    activeIndex: number | null;
    activeEntry: SparklineDataEntry<TData>[];
}

export declare const SparklinesLine: <TData>(props: SparklinesLineProps<TData> & {
    ref?: ForwardedRef<SVGRectElement>;
}) => ReturnType<typeof SparklinesLineInner>;

declare const SparklinesLineInner: <TData>({ height, max, width, withBarAdjustment, children, preserveAspectRatio, min, margin, limit, style, data, dataKey, dots, curved, activeDot, name, label, clip, labelColor, onMouseMove, onMouseEnter, onMouseLeave, onClick, startAtZero, zeroBaseline, connectNulls, ...rest }: SparklinesLineProps<TData>, ref: ForwardedRef<SVGRectElement>) => JSX.Element;

export declare type SparklinesLineProps<TData> = SparklinesComposedProps<TData> & LineShapeProps;

declare type SparklinesMargin = number | Partial<{
    top: number;
    right: number;
    bottom: number;
    left: number;
}>;

declare type SparklinesRadius = number | Partial<{
    topLeft: number;
    topRight: number;
    bottomLeft: number;
    bottomRight: number;
}>;

export declare const Tooltip: {
    (props: TooltipProps): JSX.Element;
    displayName: string;
};

declare type TooltipContent = ReactElement | ((props: TooltipProps) => ReactNode) | undefined;

export declare interface TooltipPayload {
    name?: DataKey;
    value?: number | null;
    dataKey?: DataKey;
    color?: string;
}

export declare interface TooltipProps {
    content?: TooltipContent;
    contentStyle?: CSSProperties;
    coords?: {
        x: number;
        y: number;
    };
    itemStyle?: CSSProperties;
    label?: ReactNode;
    labelStyle?: CSSProperties;
    payload?: Array<TooltipPayload>;
    separator?: string;
    wrapperStyle?: CSSProperties;
    formatter?: (payload: TooltipPayload) => ReactNode;
}

declare interface UseSparklineData<TData> {
    originalData: TData[];
    dataKeys: DataKey[];
    labels: (ReactNode | ((data: any) => ReactNode))[];
    axes: Axes;
    options: SparklineOptions;
    sparklines: SparklineData<TData>[];
}

export { }
