import EventEmitter from 'eventemitter3';
import type { ObjectGeneratorOptions } from './object-generator';
import { ElementEvents, type ElementEventsType } from './element-events';
import type { Document } from './document';
import type { TypeCastTypes } from 'hadron-type-checker';
import type { BSONArray, BSONObject, BSONValue, HadronEJSONOptions } from './utils';
export declare const DATE_FORMAT = "YYYY-MM-DD HH:mm:ss.SSS";
export { ElementEvents, type ElementEventsType };
/**
 * Is this the path to a field that is used internally by the
 * MongoDB driver or server and not for user consumption?
 */
export declare function isInternalFieldPath(path: string | number): boolean;
export declare const DEFAULT_VISIBLE_ELEMENTS = 25;
export declare function isValueExpandable(value: BSONValue): value is BSONObject | BSONArray;
/**
 * Represents an element in a document.
 */
export declare class Element extends EventEmitter {
    uuid: string;
    key: string | number;
    currentKey: string | number;
    value: BSONValue;
    currentValue: BSONValue;
    added: boolean;
    removed: boolean;
    elements?: ElementList;
    originalExpandableValue?: BSONObject | BSONArray;
    parent: Element | Document | null;
    type: TypeCastTypes;
    currentType: TypeCastTypes;
    level: number;
    currentTypeValid?: boolean;
    invalidTypeMessage?: string;
    decrypted: boolean;
    expanded: boolean;
    maxVisibleElementsCount: number;
    /**
     * Cancel any modifications to the element.
     */
    cancel(): void;
    /**
     * Create the element.
     *
     * @param key - The key.
     * @param value - The value.
     * @param parent - The parent element.
     * @param added - Is the element a new 'addition'?
     */
    constructor(key: string | number, value: BSONValue | number, parent?: Element | Document | null, added?: boolean);
    get nextElement(): Element | undefined;
    get previousElement(): Element | undefined;
    _getLevel(): number;
    /**
     * Edit the element.
     *
     * @param value - The new value.
     */
    edit(value: BSONValue): void;
    preserveType(otherElement: Element): void;
    /**
     * Adjust this element's type based on the collection's existing schema.
     * Only converts Int32 → Double or Int32 → Int64 when the schema indicates
     * the field should be one of those types. This prevents unintended type
     * narrowing when inserting new documents (e.g. 5.0 becoming Int32 when
     * the field is typically Double).
     *
     * @param schemaFields - A map of dotted field paths to objects containing
     *   a `type` property with their schema type(s). Type values use
     *   mongodb-schema naming: 'Double', 'Int32', 'Long'.
     * @param parentPath - The dotted path prefix for nested elements.
     */
    preserveTypeFromSchema(schemaFields: Readonly<Record<string, {
        type: string | string[];
    }>>, parentPath: string): void;
    changeType(newType: TypeCastTypes): void;
    getRoot(): Document;
    /**
     * Get an element by its key.
     *
     * @param key - The key name.
     *
     * @returns The element.
     */
    get(key: string | number): Element | undefined;
    /**
     * Get an element by its index.
     *
     * @param i - The index.
     *
     * @returns The element.
     */
    at(i: number): Element | undefined;
    /**
     * Rename the element. Update the parent's mapping if available.
     *
     * @param key - The new key.
     */
    rename(key: string | number): void;
    /**
     * Generate the javascript object for this element.
     *
     * @returns The javascript object.
     */
    generateObject(options?: ObjectGeneratorOptions): BSONValue;
    /**
     * Generate the javascript object representing the original values
     * for this element (pre-element removal, renaming, editing).
     *
     * @returns The javascript object.
     */
    generateOriginalObject(options?: ObjectGeneratorOptions): BSONValue;
    /**
     * Generate the Extended JSON string representation of this element.
     *
     * @returns The Extended JSON string.
     */
    toEJSON(source?: 'original' | 'current', options?: HadronEJSONOptions): string;
    /**
     * Insert an element after the provided element. If this element is an array,
     * then ignore the key specified by the caller and use the correct index.
     * Update the keys of the rest of the elements in the LinkedList.
     *
     * @param element - The element to insert after.
     * @param key - The key.
     * @param value - The value.
     *
     * @returns The new element.
     */
    insertAfter(element: Element, key: string | number, value: BSONValue): Element;
    /**
     * Add a new element to this element.
     *
     * @param| Number} key - The element key.
     * @param value - The value.
     *
     * @returns The new element.
     */
    insertEnd(key: string | number, value: BSONValue): Element;
    /**
     * Insert a placeholder element at the end of the element.
     *
     * @returns The placeholder element.
     */
    insertPlaceholder(): Element;
    insertSiblingPlaceholder(): Element;
    /**
     * Is the element a newly added element
     *
     * @returns If the element is newly added.
     */
    isAdded(): boolean;
    /**
     * Is the element blank?
     *
     * @returns If the element is blank.
     */
    isBlank(): boolean;
    /**
     * Does the element have a valid value for the current type?
     *
     * @returns If the value is valid.
     */
    isCurrentTypeValid(): boolean;
    /**
     * Set the element as valid.
     */
    setValid(): void;
    /**
     * Set the element as invalid.
     *
     * @param value - The value.
     * @param newType - The new type.
     * @param message - The error message.
     */
    setInvalid(value: BSONValue, newType: TypeCastTypes, message: string): void;
    /**
     * Determine if the key is a duplicate.
     *
     * @param value - The value to check.
     *
     * @returns If the key is a duplicate.
     */
    isDuplicateKey(value: string | number): boolean;
    /**
     * Determine if the element is edited - returns true if
     * the key or value changed. Does not count array values whose keys have
     * changed as edited.
     *
     * @returns If the element is edited.
     */
    isEdited(): boolean;
    /**
     * Check for value equality.
  
     * @returns If the value is equal.
     */
    _valuesEqual(): boolean;
    _isObjectIdEqual(): boolean;
    _isExpandable(): boolean;
    /**
     * Is the element the last in the elements.
     *
     * @returns If the element is last.
     */
    isLast(): boolean;
    /**
     * Determine if the element was explicitly renamed by the user.
     *
     * @returns If the element was explicitly renamed by the user.
     */
    isRenamed(): boolean;
    /**
     * Determine if the element was renamed, potentially as part
     * of moving array elements.
     *
     * @returns If the element was renamed, explicitly or implicitly.
     */
    hasChangedKey(): boolean;
    /**
     * Can changes to the element be reverted?
     *
     * @returns If the element can be reverted.
     */
    isRevertable(): boolean;
    /**
     * Can the element be removed?
     *
     * @returns If the element can be removed.
     */
    isRemovable(): boolean;
    /**
     * Can no action be taken on the element
     *
     * @returns If no action can be taken.
     */
    isNotActionable(): boolean;
    /**
     * Determine if the value has been decrypted via CSFLE.
     *
     * Warning: This does *not* apply to the children of decrypted elements!
     * This only returns true for the exact field that was decrypted.
     *
     * a: Object
     *  \-- b: Object <- decrypted
     *      \-- c: number
     *
     * a.isValueDecrypted() === false
     * a.get('b')?.isValueDecrypted() === true
     * a.get('b')?.get('c')?.isValueDecrypted() === true
     *
     * @returns If the value was encrypted on the server and is now decrypted.
     */
    isValueDecrypted(): boolean;
    /**
     * Detemine if this value or any of its children were marked
     * as having been decrypted with CSFLE.
     *
     * Warning: This does *not* apply to the children of decrypted elements!
     * This only returns true for the exact field that was decrypted
     * and its parents.
     *
     * a: Object
     *  \-- b: Object <- decrypted
     *      \-- c: number
     *
     * a.containsDecryptedChildren() === true
     * a.get('b')?.containsDecryptedChildren() === true
     * a.get('b')?.get('c')?.containsDecryptedChildren() === false
     *
     * @returns If any child of this element has been decrypted directly.
     */
    containsDecryptedChildren(): boolean;
    /**
     * Determine if the value is editable.
     *
     * @returns If the value is editable.
     */
    isValueEditable(): boolean;
    /**
     * Determine if the key of the parent element is editable.
     *
     * @returns If the parent's key is editable.
     */
    isParentEditable(): boolean;
    _isKeyLegallyEditable(): boolean;
    /**
     * Determine if the key is editable.
     *
     * @returns If the key is editable.
     */
    isKeyEditable(): boolean;
    /**
     * Is this a field that is used internally by the MongoDB driver or server
     * and not for user consumption?
     *
     * @returns
     */
    isInternalField(): boolean;
    /**
     * Determine if the element is modified at all.
     *
     * @returns If the element is modified.
     */
    isModified(): boolean;
    /**
     * Is the element flagged for removal?
     *
     * @returns If the element is flagged for removal.
     */
    isRemoved(): boolean;
    /**
     * Are any immediate children of this element flagged for removal?
     *
     * @returns If any immediate children of this element are flagged for removal.
     */
    hasAnyRemovedChild(): boolean;
    /**
     * Elements themselves are not the root.
     *
     * @returns Always false.
     */
    isRoot(): false;
    /**
     * Flag the element for removal.
     */
    remove(): void;
    /**
     * Revert the changes to the element.
     */
    revert(): void;
    /**
     * Expands the target element and optionally its children as well.
     * Document.expand is when we would want to expand the children otherwise we
     * will most expand the element itself.
     */
    expand(expandChildren?: boolean): void;
    /**
     * Collapses only the target element
     */
    collapse(): void;
    /**
     * Fire and bubble up the event.
     *
     * @param evt - The event.
     * @paramdata - Optional.
     */
    _bubbleUp(evt: ElementEventsType, ...data: BSONArray): void;
    /**
     * Convert this element to an empty object.
     */
    _convertToEmptyObject(): void;
    /**
     * Convert to an empty array.
     */
    _convertToEmptyArray(): void;
    /**
     * Is the element empty?
     *
     * @param element - The element to check.
     *
     * @returns If the element is empty.
     */
    _isElementEmpty(element: Element | undefined | null): boolean;
    /**
     * Generates a sequence of child elements.
     *
     * @param object - The object to generate from.
     *
     * @returns The elements.
     */
    _generateElements(object: BSONObject | BSONArray): ElementList;
    /**
     * Removes the added elements from the element.
     */
    _removeAddedElements(): void;
    getVisibleElements(): Element[];
    setMaxVisibleElementsCount(newCount: number): void;
    getTotalVisibleElementsCount(): number;
    findUUIDs(): {
        subtype4Count: number;
        subtype3Count: number;
    };
    private emitVisibleElementsChanged;
    /**
     * @deprecated Use ElementEvents import instead
     */
    static get Events(): typeof ElementEvents;
}
/**
 * Represents a doubly linked list.
 */
export declare class ElementList implements Iterable<Element> {
    private elements;
    private parent;
    constructor(parent: Document | Element, originalDoc: BSONObject | BSONArray | null | undefined);
    private isArray;
    get size(): number;
    at(index: number): Element | undefined;
    get(key: string | number): Element | undefined;
    some(predicate: (value: Element, index: number, array: Element[]) => unknown): boolean;
    every(predicate: (value: Element, index: number, array: Element[]) => unknown): boolean;
    get firstElement(): Element | undefined;
    get lastElement(): Element | undefined;
    /**
     * Insert data after the provided element.
     *
     * @param afterElement - The element to insert after.
     * @param key - The element key.
     * @param value - The element value.
     * @param added - If the element is new.
     *
     * @returns The inserted element.
     */
    insertAfter(afterElement: Element, key: string | number, value: BSONValue, added?: boolean): Element | undefined;
    /**
     * Insert data before the provided element.
     *
     * @param beforeElement - The element to insert before.
     * @param key - The element key.
     * @param value - The element value.
     * @param added - If the element is new.
     *
     * @returns The inserted element.
     */
    insertBefore(beforeElement: Element, key: string | number, value: BSONValue, added?: boolean): Element | undefined;
    /**
     * Insert data at the beginning of the list.
     *
     * @param key - The element key.
     * @param value - The element value.
     * @param added - If the element is new.
     *
     * @returns The data element.
     */
    insertBeginning(key: string | number, value: BSONValue, added?: boolean): Element;
    /**
     * Insert data at the end of the list.
     *
     * @param key - The element key.
     * @param value - The element value.
     * @param added - If the element is new.
     *
     * @returns The data element.
     */
    insertEnd(key: string | number, value: BSONValue, added?: boolean): Element;
    /**
     * Remove the element from the list.
     *
     * @param removeElement - The element to remove.
     *
     * @returns The list with the element removed.
     */
    remove(removeElement: Element): this;
    findNext(el: Element): Element | undefined;
    findPrevious(el: Element): Element | undefined;
    [Symbol.iterator](): Iterator<Element>;
}
//# sourceMappingURL=element.d.ts.map