/**
 * Represents a splice operation to be applied to an array.
 * Designed for direct use with Array.splice() for efficient mutations.
 */
export interface SpliceOperation {
    /** Index at which to start the splice (in current array state) */
    index: number;
    /** Number of elements to delete from this position */
    deleteCount: number;
    /** Number of new elements to insert at this position */
    insertCount: number;
    /** Optional source indices for preserved elements (for tracking) */
    sourceIndices?: number[];
}
/**
 * Tracks transformations from original array indices to final array indices.
 * Optimized for efficient array mutations using splice operations.
 */
export interface IndexTransformationMap {
    /** Original array length before any transactions */
    originalLength: number;
    /** Final array length after all transactions */
    finalLength: number;
    /**
     * Splice operations to transform the array.
     * Applied from back to front to avoid index shifting issues.
     * Each operation represents a single splice call.
     */
    spliceOps: SpliceOperation[];
    /** Set of removed original indices */
    removedIndices: Set<number>;
    /** Set of updated final indices (indices in the final array that have updated items) */
    updatedIndices: Set<number>;
    /** Total number of prepended items */
    totalPrependCount: number;
    /** Total number of appended items */
    totalAppendCount: number;
}
/**
 * Helper functions to compute derived properties from IndexTransformationMap.
 * These avoid storing redundant computed values and enable optimization checks.
 */
/**
 * Check if the change is append-only (no prepends, no removals).
 *
 * **Optimization:** Append-only operations don't shift existing indices,
 * so preserved items don't need to be marked as "moved".
 *
 * @param indexMap - The index transformation map to check
 * @returns True if only appends occurred
 *
 * @example
 * ```typescript
 * if (isAppendOnly(changeDesc.indexMap)) {
 *     // Skip tracking moved items - nothing moved
 * }
 * ```
 */
export declare function isAppendOnly(indexMap: IndexTransformationMap): boolean;
/**
 * Check if the change is prepend-only (no appends, no removals).
 *
 * **Optimization:** Prepend-only operations shift ALL existing items by a fixed offset,
 * so we can bulk-mark them as moved without iteration.
 *
 * @param indexMap - The index transformation map to check
 * @returns True if only prepends occurred
 *
 * @example
 * ```typescript
 * if (isPrependOnly(changeDesc.indexMap)) {
 *     // All items shifted by totalPrependCount
 *     markAllAsMoved(changeDesc.indexMap.totalPrependCount);
 * }
 * ```
 */
export declare function isPrependOnly(indexMap: IndexTransformationMap): boolean;
/**
 * Check if no items were removed (may have prepends/appends).
 *
 * **Optimization:** When no removals occurred, items are either:
 * - In their original positions (if no prepends)
 * - Shifted by a fixed offset (if prepends occurred)
 *
 * @param indexMap - The index transformation map to check
 * @returns True if no removals occurred
 *
 * @example
 * ```typescript
 * if (hasNoRemovals(changeDesc.indexMap) && indexMap.totalPrependCount > 0) {
 *     // All original items shifted by prepend count
 * }
 * ```
 */
export declare function hasNoRemovals(indexMap: IndexTransformationMap): boolean;
/** Check if only in-place updates occurred (no adds/removes). */
export declare function isUpdateOnly(indexMap: IndexTransformationMap): boolean;
/**
 * Check if only removals occurred (no prepends, appends, or other insertions).
 *
 * **Optimization:** Removal-only operations preserve sort order and uniqueness:
 * - Removing values can't create duplicates (only reduce them)
 * - Removing values can't change ascending to descending order
 * - KEY_SORT_ORDERS metadata can be preserved
 */
export declare function hasOnlyRemovals(indexMap: IndexTransformationMap): boolean;
/** Check if all removals are contiguous starting at index 0. */
export declare function hasContiguousRemovalsAtStart(indexMap: IndexTransformationMap): boolean;
/** Check for rolling window pattern: contiguous removals at start + appends at end. */
export declare function isRollingWindow(indexMap: IndexTransformationMap): boolean;
/**
 * Abstract description of changes to be applied to source data.
 * Provides precise index mapping for optimized incremental updates.
 *
 * **Responsibilities:**
 * - Describes what changed (splice operations, index mappings, prepend/append counts)
 * - Provides transformation methods for applying changes to arrays
 * - Enables iteration over preserved/moved elements
 *
 * **Usage Pattern:**
 * 1. DataSet builds DataChangeDescription from pending transactions
 * 2. DataController passes it to DataModel for incremental updates
 * 3. DataModel uses methods below to transform keys, columns, and invalidity arrays
 *
 * **Design Note:**
 * This class intentionally separates "change description" from "transaction management" (DataSet)
 * and "data processing" (DataModel). This enables:
 * - Multiple consumers (DataController, DataModel)
 * - Independent testing
 * - Clear separation of concerns
 */
export declare class DataChangeDescription {
    /**
     * Map from original to final indices.
     *
     * Contains splice operations, removed indices, and counts needed for transformations.
     * Access directly for low-level operations (e.g., updating banded domains).
     */
    readonly indexMap: IndexTransformationMap;
    private readonly prependValues;
    private readonly appendValues;
    private readonly insertionValues;
    constructor(indexMap: IndexTransformationMap, insertions: {
        prependValues: unknown[];
        appendValues: unknown[];
        insertionValues: unknown[];
    });
    /**
     * Get all indices that were removed from the original array, sorted ascending.
     *
     * @returns Array of removed indices (e.g., [2, 5, 8])
     *
     * @example
     * ```typescript
     * const removed = changeDesc.getRemovedIndices();
     * console.log(`Removed ${removed.length} items at indices: ${removed}`);
     * ```
     */
    getRemovedIndices(): number[];
    /**
     * Get all indices that were updated in the final array, sorted ascending.
     *
     * @returns Array of updated indices (e.g., [1, 3, 7])
     *
     * @example
     * ```typescript
     * const updated = changeDesc.getUpdatedIndices();
     * console.log(`Updated ${updated.length} items at indices: ${updated}`);
     * ```
     */
    getUpdatedIndices(): number[];
    /**
     * Iterate over preserved elements, mapping source index to destination index.
     * Only calls callback for elements that were NOT removed.
     *
     * **Use this for:**
     * - Tracking which elements moved (when sourceIndex !== destIndex)
     * - Generating diff metadata (added/removed/moved items)
     * - Understanding index shifts caused by prepends/removes
     *
     * @param callback - Called for each preserved element with (sourceIndex, destIndex)
     *
     * @example Detecting moved items
     * ```typescript
     * const movedItems = new Set<number>();
     * changeDesc.forEachPreservedIndex((srcIdx, destIdx) => {
     *     if (srcIdx !== destIdx) {
     *         movedItems.add(destIdx);
     *     }
     * });
     * ```
     */
    forEachPreservedIndex(callback: (sourceIndex: number, destIndex: number) => void): void;
    /**
     * Get the values that were prepended to the beginning of the array.
     *
     * These values are stored during change description construction and can be used
     * to avoid reprocessing prepended data.
     *
     * @returns Array of prepended values in order
     *
     * @example Processing prepended data
     * ```typescript
     * const prependedData = changeDesc.getPrependedValues<DataRow>();
     * for (const row of prependedData) {
     *     processRow(row);
     * }
     * ```
     */
    getPrependedValues<T = unknown>(): T[];
    /**
     * Get the values that were appended to the end of the array.
     *
     * These values are stored during change description construction and can be used
     * to avoid reprocessing appended data.
     *
     * @returns Array of appended values in order
     *
     * @example Processing appended data
     * ```typescript
     * const appendedData = changeDesc.getAppendedValues<DataRow>();
     * for (const row of appendedData) {
     *     processRow(row);
     * }
     * ```
     */
    getAppendedValues<T = unknown>(): T[];
    /**
     * Get the values that were inserted at arbitrary indices.
     *
     * These values are stored during change description construction and can be used
     * to avoid reprocessing inserted data.
     *
     * @returns Array of insertion values in the order they appear in splice operations
     *
     * @example Processing inserted data
     * ```typescript
     * const insertedData = changeDesc.getInsertionValues<DataRow>();
     * for (const row of insertedData) {
     *     processRow(row);
     * }
     * ```
     */
    getInsertionValues<T = unknown>(): T[];
    /**
     * Applies the transformation to an array in-place using native Array operations.
     * This is a zero-copy operation that mutates the array directly.
     *
     * **Use this for:**
     * - Transforming processed data arrays (keys, columns, invalidity)
     * - Applying prepends, removals, and appends in a single pass
     * - Maintaining synchronization between data and processed arrays
     *
     * **How it works:**
     * 1. Applies splice operations in order (prepends, removals, appends)
     * 2. Calls processInsertion callback for each inserted element
     * 3. Mutates the array in-place for zero-copy efficiency
     *
     * @param array - The array to transform in-place (will be mutated)
     * @param processInsertion - Callback to generate values for inserted indices
     *
     * @example Transforming a column array
     * ```typescript
     * // Transform processed column to match new data layout
     * const insertionCache = new Map(); // Pre-computed processed values
     * changeDesc.applyToArray(columnArray, (destIndex) => {
     *     return insertionCache.get(destIndex) ?? defaultValue;
     * });
     * ```
     *
     * @example Transforming an invalidity array
     * ```typescript
     * // Transform invalidity flags to match new data
     * changeDesc.applyToArray(invalidityArray, (destIndex) => {
     *     const cached = insertionCache.get(destIndex);
     *     return cached?.hasInvalidKey ?? false;
     * });
     * ```
     */
    applyToArray<T>(array: T[], processInsertion: (destIndex: number) => T, onRemove?: (removed: T[], op: SpliceOperation) => void): void;
}
