import type { ChartAnimationPhase, Scaling } from 'ag-charts-core';
import { ChartAxisDirection, type Point, type Scale, StateMachine } from 'ag-charts-core';
import type { AgDrawingMode, AgSeriesSegmentation } from 'ag-charts-types';
import type { HighlightNodeDatum } from '../../../core/eventsHub';
import type { AnimationValue } from '../../../motion/animation';
import { BBox } from '../../../scene/bbox';
import { Group, TranslatableGroup } from '../../../scene/group';
import type { Node, NodeWithOpacity } from '../../../scene/node';
import { SegmentedGroup } from '../../../scene/segmentedGroup';
import { Selection } from '../../../scene/selection';
import { Path } from '../../../scene/shape/path';
import { Text } from '../../../scene/shape/text';
import { QuadtreeNearest } from '../../../scene/util/quadtree';
import type { ChartAxis } from '../../chartAxis';
import { DataModelSeries, type DataModelSeriesConstructorOpts } from '../dataModelSeries';
import type { SeriesDirectionKeysMapping, SeriesNodePickMatch } from '../series';
import { SeriesNodeEvent } from '../series';
import { SeriesProperties } from '../seriesProperties';
import type { DatumIndexType, ISeries, SeriesNodeDatum, SeriesNodeEventTypes } from '../seriesTypes';
import { type ShapeFillBBox } from '../shapeUtil';
import type { CartesianSeriesNodeDataContext, CartesianSeriesNodeDatum, CartesianSeriesPropertiesBase, CartesianSeriesTypes, ContextOf, CreateNodeDataContextOf, DatumOf, LabelOf, NodeOf, OptionsOf, PropertiesOf, StackContextOf } from './cartesianSeriesTypes';
type CartesianSeriesOpts<TTypes extends CartesianSeriesTypes> = {
    pathsPerSeries: string[];
    pathsZIndexSubOrderOffset: number[];
    propertyKeys: SeriesDirectionKeysMapping<PropertiesOf<TTypes>>;
    propertyNames: SeriesDirectionKeysMapping<PropertiesOf<TTypes>>;
    datumSelectionGarbageCollection: boolean;
    animationAlwaysUpdateSelections: boolean;
    animationAlwaysPopulateNodeData: boolean;
    segmentedDataNodes: boolean;
    animationResetFns?: {
        path?: (path: Path<DatumOf<TTypes>>) => Partial<Path<DatumOf<TTypes>>>;
        datum?: (node: NodeOf<TTypes>, datum: DatumOf<TTypes>) => AnimationValue & Partial<NodeOf<TTypes>>;
        label?: (node: Text, datum: LabelOf<TTypes>) => AnimationValue & Partial<Text>;
    };
};
export declare const DEFAULT_CARTESIAN_DIRECTION_KEYS: {
    x: "xKey"[];
    y: "yKey"[];
};
export declare const DEFAULT_CARTESIAN_DIRECTION_NAMES: {
    x: "xName"[];
    y: "yName"[];
};
export declare class CartesianSeriesNodeEvent<TEvent extends string = SeriesNodeEventTypes> extends SeriesNodeEvent<SeriesNodeDatum<number>, TEvent> {
    readonly xKey?: string;
    readonly yKey?: string;
    constructor(type: TEvent, nativeEvent: Event, datum: SeriesNodeDatum<number>, series: ISeries<number, SeriesNodeDatum<number>, {
        xKey?: string;
        yKey?: string;
    }>);
}
type CartesianAnimationState = 'empty' | 'ready' | 'waiting' | 'clearing' | 'disabled';
type CartesianAnimationEvent<TTypes extends CartesianSeriesTypes> = {
    update: CartesianAnimationData<NodeOf<TTypes>, DatumOf<TTypes>, LabelOf<TTypes>, ContextOf<TTypes>>;
    updateData: undefined;
    highlight: Selection<NodeOf<TTypes>, DatumOf<TTypes>>;
    resize: CartesianAnimationData<NodeOf<TTypes>, DatumOf<TTypes>, LabelOf<TTypes>, ContextOf<TTypes>>;
    clear: CartesianAnimationData<NodeOf<TTypes>, DatumOf<TTypes>, LabelOf<TTypes>, ContextOf<TTypes>>;
    reset: undefined;
    skip: undefined;
    disable: undefined;
};
export interface CartesianAnimationData<TNode extends Node, TDatum extends CartesianSeriesNodeDatum, TLabel extends SeriesNodeDatum<number> = TDatum, TContext extends CartesianSeriesNodeDataContext<TDatum, TLabel> = CartesianSeriesNodeDataContext<TDatum, TLabel>> {
    datumSelection: Selection<TNode, TDatum>;
    labelSelection: Selection<Text, TLabel>;
    annotationSelections: Selection<NodeWithOpacity, TDatum>[];
    contextData: TContext;
    previousContextData?: TContext;
    paths: Path[];
    seriesRect?: BBox;
    duration?: number;
}
export declare abstract class CartesianSeriesProperties<T extends object> extends SeriesProperties<T> implements CartesianSeriesPropertiesBase<T> {
    xKeyAxis: string;
    yKeyAxis: string;
    legendItemName?: string;
    pickOutsideVisibleMinorAxis: boolean;
    segmentation: AgSeriesSegmentation;
}
export declare const RENDER_TO_OFFSCREEN_CANVAS_THRESHOLD = 100;
export declare abstract class CartesianSeries<TTypes extends CartesianSeriesTypes> extends DataModelSeries<DatumOf<TTypes>, OptionsOf<TTypes>, PropertiesOf<TTypes>, LabelOf<TTypes>, ContextOf<TTypes>> {
    private _contextNodeData?;
    get contextNodeData(): ContextOf<TTypes> | undefined;
    getNodeData(): DatumOf<TTypes>[] | undefined;
    protected readonly NodeEvent: typeof CartesianSeriesNodeEvent;
    private readonly paths;
    protected readonly dataNodeGroup: SegmentedGroup;
    readonly labelGroup: TranslatableGroup;
    private datumSelection;
    protected labelSelection: Selection<Text, LabelOf<TTypes>>;
    private highlightSelection;
    protected highlightLabelSelection: Selection<Text, LabelOf<TTypes>>;
    annotationSelections: Set<Selection<NodeWithOpacity, DatumOf<TTypes>>>;
    seriesBelowStackContext: StackContextOf<TTypes> | undefined;
    private readonly opts;
    private readonly debug;
    protected quadtree?: QuadtreeNearest<DatumOf<TTypes>>;
    protected animationState: StateMachine<CartesianAnimationState, CartesianAnimationEvent<TTypes>>;
    constructor({ pathsPerSeries, pathsZIndexSubOrderOffset, datumSelectionGarbageCollection, animationAlwaysUpdateSelections, animationAlwaysPopulateNodeData, segmentedDataNodes, animationResetFns, propertyKeys, propertyNames, ...otherOpts }: Partial<CartesianSeriesOpts<TTypes>> & Pick<CartesianSeriesOpts<TTypes>, 'propertyKeys' | 'propertyNames'> & DataModelSeriesConstructorOpts<PropertiesOf<TTypes>>);
    getKeyAxis(direction: ChartAxisDirection): string | undefined;
    attachSeries(seriesContentNode: Group, seriesNode: Group, annotationNode: Group | undefined): void;
    detachSeries(seriesContentNode: Group | undefined, seriesNode: Group, annotationNode: Group | undefined): void;
    updatedDomains(): void;
    protected attachPaths(paths: Path[]): void;
    protected detachPaths(paths: Path[]): void;
    renderToOffscreenCanvas(): boolean;
    resetAnimation(phase: ChartAnimationPhase): void;
    destroy(): void;
    isSeriesHighlighted(highlightedDatum: HighlightNodeDatum | undefined): highlightedDatum is DatumOf<TTypes>;
    protected strokewidthChange(): boolean;
    update({ seriesRect }: {
        seriesRect?: BBox;
    }): void;
    createStackContext(): StackContextOf<TTypes> | undefined;
    /**
     * Determines if incremental node updates are possible based on common criteria.
     *
     * Returns true if existing nodeData exists AND either:
     * - processedData has a changeDescription (partial update), OR
     * - animation is disabled (large dataset)
     *
     * Series may extend with additional conditions by OR'ing additional checks:
     * ```
     * const canIncrementallyUpdate =
     *     this.canIncrementallyUpdateNodes() || (existingNodeData && seriesSpecificCondition);
     * ```
     *
     * @param additionalCondition - Optional series-specific condition to OR with base conditions
     */
    protected canIncrementallyUpdateNodes(additionalCondition?: boolean): boolean;
    /**
     * Trims the node array after incremental updates.
     *
     * Call at the end of createNodeData() when using incremental updates:
     * ```
     * if (ctx.canIncrementallyUpdate) {
     *     this.trimIncrementalNodeArray(ctx.nodes, ctx.nodeIndex);
     * }
     * ```
     *
     * @param nodes - The node array to trim
     * @param nodeIndex - The final write position (new array length)
     */
    protected trimIncrementalNodeArray<T>(nodes: T[], nodeIndex: number): void;
    /**
     * Template method for creating node data.
     *
     * This implementation provides the common algorithm skeleton:
     * 1. Validate preconditions (axes, dataModel, processedData)
     * 2. Create context with cached values
     * 3. Initialise result object
     * 4. Populate node data (strategy selection inside)
     * 5. Finalize (trim arrays, post-processing)
     * 6. Assemble and return result
     *
     * Subclasses that have been migrated to the template pattern should NOT
     * override this method. Instead, implement the abstract hooks.
     *
     * Subclasses that haven't been migrated yet can override this method entirely.
     */
    createNodeData(): ContextOf<TTypes> | undefined;
    /**
     * Creates the shared context for datum creation/update operations.
     * Called once per createNodeData() invocation.
     *
     * MUST return an object extending CartesianCreateNodeDataContext with:
     * - Cached data arrays (resolved from dataModel)
     * - Cached scales (from axes)
     * - Pre-computed positioning values
     * - Property key lookups
     * - Incremental update state (canIncrementallyUpdate, nodes, nodeIndex)
     *
     * @returns Context object or undefined if context cannot be created
     */
    protected createNodeDatumContext(_xAxis: ChartAxis, _yAxis: ChartAxis): CreateNodeDataContextOf<TTypes> | undefined;
    /**
     * Populates the node data array by iterating over data.
     *
     * Strategy selection happens inside this method:
     * - Simple iteration for ungrouped data
     * - Grouped iteration for grouped data
     * - Aggregation iteration for large datasets
     *
     * Implementations should use the upsert pattern:
     * - prepareNodeDatumState() → validate and compute state
     * - upsertNodeDatum() → create or update node in place
     */
    protected populateNodeData(_ctx: CreateNodeDataContextOf<TTypes>): void;
    /**
     * Initializes the result context object that will be returned.
     * Called before populate phase to allow early return for invisible series.
     *
     * Should create the context with:
     * - itemId
     * - nodeData (reference to ctx.nodes)
     * - labelData (reference or separate array)
     * - scales
     * - visible
     * - styles
     */
    protected initializeResult(_ctx: CreateNodeDataContextOf<TTypes>): ContextOf<TTypes>;
    /**
     * Validates preconditions for createNodeData.
     * Default: checks axes, dataModel, and processedData exist.
     *
     * Override for specialized axis requirements (e.g., category vs value axis in bar series).
     */
    protected validateCreateNodeDataPreconditions(): {
        xAxis: ChartAxis;
        yAxis: ChartAxis;
    } | undefined;
    /**
     * Returns empty result when context creation fails.
     * Default: returns undefined.
     */
    protected getEmptyResult(): ContextOf<TTypes> | undefined;
    /**
     * Finalizes node data after population phase.
     * Default: trims incremental node arrays.
     *
     * Override to add post-processing (sorting, additional cleanup, multiple arrays).
     */
    protected finalizeNodeData(ctx: CreateNodeDataContextOf<TTypes>): void;
    /**
     * Assembles final result from context and initialized result.
     * Default: returns the initialized result unchanged.
     *
     * Override to add computed fields (segments, groupScale).
     */
    protected assembleResult(_ctx: CreateNodeDataContextOf<TTypes>, result: ContextOf<TTypes>): ContextOf<TTypes>;
    protected updateSelections(): boolean;
    protected updateSeriesSelections(): void;
    protected abstract nodeFactory(): NodeOf<TTypes>;
    protected getShapeFillBBox(): ShapeFillBBox;
    protected updateNodes(itemHighlighted: boolean, nodeRefresh: boolean): void;
    protected getHighlightData(_nodeData: DatumOf<TTypes>[], highlightedItem: DatumOf<TTypes>): DatumOf<TTypes>[] | undefined;
    protected getHighlightLabelData(labelData: LabelOf<TTypes>[], highlightedItem: DatumOf<TTypes>): LabelOf<TTypes>[] | undefined;
    protected updateHighlightSelection(): boolean;
    protected markQuadtreeDirty(): void;
    protected datumNodesIter(): Iterable<NodeOf<TTypes>>;
    getQuadTree(): QuadtreeNearest<DatumOf<TTypes>>;
    protected initQuadTree(_quadtree: QuadtreeNearest<DatumOf<TTypes>>): void;
    protected pickNodeDataExactShape(point: Point): SeriesNodeDatum<DatumIndexType>[] | undefined;
    protected pickModulesExactShape(point: Point): SeriesNodeDatum<DatumIndexType>[] | undefined;
    protected pickNodesExactShape(point: Point): SeriesNodeDatum<DatumIndexType>[];
    protected pickNodeDataClosestDatum(point: Point): {
        datum: SeriesNodeDatum<DatumIndexType> | undefined;
        distance: number;
    } | undefined;
    private pickModulesClosestDatum;
    protected pickNodeClosestDatum(point: Point): SeriesNodePickMatch | undefined;
    protected pickNodeMainAxisFirst(point: Point, requireCategoryAxis: boolean): SeriesNodePickMatch | undefined;
    protected isPathOrSelectionDirty(): boolean;
    shouldFlipXY(): boolean;
    protected abstract xCoordinateRange(xValue: any, pixelSize: number, index: number): [number, number];
    protected abstract yCoordinateRange(yValues: any[], pixelSize: number, index: number): [number, number];
    visibleRangeIndices(axisKey: string, visibleRange: [any, any], indices?: Uint32Array | number[], sortOrderParams?: {
        sortOrder: 1 | -1;
    }): [number, number];
    protected domainForVisibleRange(_direction: ChartAxisDirection, axisKeys: string[], crossAxisKey: string, visibleRange: [any, any], indices?: number[]): [number, number];
    protected domainForClippedRange(direction: ChartAxisDirection, axisKeys: string[], crossAxisKey: string): any[];
    protected zoomFittingVisibleItems(crossAxisKey: string, _axisKeys: string[], // TODO: remove this parameter
    xVisibleRange: [number, number], yVisibleRange: [number, number] | undefined, minVisibleItems: number): {
        x: [number, number];
        y: [number, number] | undefined;
    } | undefined;
    protected countVisibleItems(crossAxisKey: string, axisKeys: string[], xVisibleRange: [number, number], yVisibleRange: [number, number] | undefined, minVisibleItems: number): number;
    minTimeInterval(): number | undefined;
    protected updateHighlightSelectionItem(opts: {
        items?: DatumOf<TTypes>[];
        highlightSelection: Selection<NodeOf<TTypes>, DatumOf<TTypes>>;
    }): Selection<NodeOf<TTypes>, DatumOf<TTypes>>;
    protected updateDatumSelection(opts: {
        nodeData: DatumOf<TTypes>[];
        datumSelection: Selection<NodeOf<TTypes>, DatumOf<TTypes>>;
    }): Selection<NodeOf<TTypes>, DatumOf<TTypes>>;
    protected updateDatumNodes(_opts: {
        datumSelection: Selection<NodeOf<TTypes>, DatumOf<TTypes>>;
        isHighlight: boolean;
        drawingMode: AgDrawingMode;
    }): void;
    protected updateDatumStyles(_opts: {
        datumSelection: Selection<NodeOf<TTypes>, DatumOf<TTypes>>;
        isHighlight: boolean;
    }): void;
    protected updatePaths(opts: {
        itemId?: string;
        contextData: ContextOf<TTypes>;
        paths: Path[];
    }): void;
    protected updatePathNodes(opts: {
        itemId?: string;
        paths: Path[];
        visible: boolean;
        animationEnabled: boolean;
    }): void;
    protected resetPathAnimation(data: CartesianAnimationData<NodeOf<TTypes>, DatumOf<TTypes>, LabelOf<TTypes>, ContextOf<TTypes>>): void;
    protected resetDatumAnimation(data: CartesianAnimationData<NodeOf<TTypes>, DatumOf<TTypes>, LabelOf<TTypes>, ContextOf<TTypes>>): void;
    protected resetLabelAnimation(data: CartesianAnimationData<NodeOf<TTypes>, DatumOf<TTypes>, LabelOf<TTypes>, ContextOf<TTypes>>): void;
    protected resetAllAnimation(data: CartesianAnimationData<NodeOf<TTypes>, DatumOf<TTypes>, LabelOf<TTypes>, ContextOf<TTypes>>): void;
    protected animateEmptyUpdateReady(data: CartesianAnimationData<NodeOf<TTypes>, DatumOf<TTypes>, LabelOf<TTypes>, ContextOf<TTypes>>): void;
    protected animateWaitingUpdateReady(data: CartesianAnimationData<NodeOf<TTypes>, DatumOf<TTypes>, LabelOf<TTypes>, ContextOf<TTypes>>): void;
    protected animateReadyHighlight(data: Selection<NodeOf<TTypes>, DatumOf<TTypes>>): void;
    protected animateReadyResize(data: CartesianAnimationData<NodeOf<TTypes>, DatumOf<TTypes>, LabelOf<TTypes>, ContextOf<TTypes>>): void;
    protected animateClearingUpdateEmpty(data: CartesianAnimationData<NodeOf<TTypes>, DatumOf<TTypes>, LabelOf<TTypes>, ContextOf<TTypes>>): void;
    private getAnimationData;
    protected updateLabelSelection(opts: {
        labelData: LabelOf<TTypes>[];
        labelSelection: Selection<Text, LabelOf<TTypes>>;
    }): Selection<Text, LabelOf<TTypes>>;
    protected abstract updateLabelNodes(opts: {
        labelSelection: Selection<Text, LabelOf<TTypes>>;
        isHighlight?: boolean;
    }): void;
    protected abstract isLabelEnabled(): boolean;
    protected getScaling(scale: Scale<any, any>): Scaling | undefined;
    protected calculateScaling(): {
        x?: Scaling | undefined;
        y?: Scaling | undefined;
        angle?: Scaling | undefined;
        radius?: Scaling | undefined;
    };
}
export {};
