import '../../assert/js/assert.js';
import '../../globals.js';
import IntentionalAny from '../../phet-core/js/types/IntentionalAny.js';
import StrictOmit from '../../phet-core/js/types/StrictOmit.js';
import PhetioObject, { PhetioObjectOptions } from '../../tandem/js/PhetioObject.js';
import IOType from '../../tandem/js/types/IOType.js';
import { DisposerOptions } from './Disposable.js';
import { TinyEmitterOptions } from './TinyEmitter.js';
import TinyProperty from './TinyProperty.js';
import TReadOnlyProperty, { PropertyLazyLinkListener, PropertyLinkListener, PropertyListener } from './TReadOnlyProperty.js';
import { Units } from './units.js';
import { Validator, ValueComparisonStrategy } from './Validation.js';
export type ReadOnlyPropertyState<StateType> = {
    value: StateType;
    validValues: StateType[] | null;
    units: string | null;
};
type SelfOptions = {
    units?: Units | null;
    reentrant?: boolean;
    phetioValueType?: IOType;
    phetioOuterType?: (parameterType: IOType) => IOType;
    hasListenerOrderDependencies?: boolean;
} & Pick<TinyEmitterOptions, 'reentrantNotificationStrategy'>;
type ParentOptions<T> = Validator<T> & PhetioObjectOptions;
export type PropertyOptions<T> = SelfOptions & StrictOmit<ParentOptions<T>, 'phetioType'>;
export type LinkOptions = {
    phetioDependencies?: Array<TReadOnlyProperty<unknown>>;
};
type ReadOnlyPropertyLinkOptions = LinkOptions & DisposerOptions;
/**
 * Base class for Property, DerivedProperty, DynamicProperty.  Set methods are protected/not part of the public
 * interface.  Initial value and resetting is not defined here.
 */
export default class ReadOnlyProperty<T> extends PhetioObject implements TReadOnlyProperty<T> {
    private readonly id;
    readonly units: Units | null;
    readonly validValues?: readonly T[];
    private tinyProperty;
    private notifying;
    private readonly reentrant;
    isDeferred: boolean;
    protected deferredValue: T | null;
    protected hasDeferredValue: boolean;
    protected readonly valueValidator: Validator<T>;
    protected readonly phetioValueType: IOType;
    /**
     * This is protected to indicate to clients that subclasses should be used instead.
     * @param value - the initial value of the property
     * @param [providedOptions]
     */
    protected constructor(value: T, providedOptions?: PropertyOptions<T>);
    /**
     * Returns true if the value can be set externally, using .value= or set()
     */
    isSettable(): boolean;
    /**
     * Gets the value.
     * You can also use the es5 getter (property.value) but this means is provided for inner loops
     * or internal code that must be fast.
     */
    get(): T;
    /**
     * Sets the value and notifies listeners, unless deferred or disposed. You can also use the es5 getter
     * (property.value) but this means is provided for inner loops or internal code that must be fast. If the value
     * hasn't changed, this is a no-op.
     *
     * NOTE: For PhET-iO instrumented Properties that are phetioState: true, the value is only
     * set by the PhetioStateEngine and cannot be modified by other code while isSettingPhetioStateProperty === true.
     */
    protected set(value: T): void;
    /**
     * For usage by the IOType during PhET-iO state setting.
     */
    protected unguardedSet(value: T): void;
    /**
     * Sets the value without notifying any listeners. This is a place to override if a subtype performs additional work
     * when setting the value.
     */
    protected setPropertyValue(value: T): void;
    /**
     * Returns true if and only if the specified value equals the value of this property
     */
    protected equalsValue(value: T): boolean;
    /**
     * Determine if the two values are equal, see TinyProperty.areValuesEqual().
     */
    areValuesEqual(a: T, b: T): boolean;
    /**
     * NOTE: a few sims are calling this even though they shouldn't
     */
    private _notifyListeners;
    /**
     * Use this method when mutating a value (not replacing with a new instance) and you want to send notifications about the change.
     * This is different from the normal axon strategy, but may be necessary to prevent memory allocations.
     * This method is unsafe for removing listeners because it assumes the listener list not modified, to save another allocation
     * Only provides the new reference as a callback (no oldValue)
     * See https://github.com/phetsims/axon/issues/6
     */
    notifyListenersStatic(): void;
    /**
     * When deferred, set values do not take effect or send out notifications.  After defer ends, the Property takes
     * its deferred value (if any), and a follow-up action (return value) can be invoked to send out notifications
     * once other Properties have also taken their deferred values.
     *
     * @param isDeferred - whether the Property should be deferred or not
     * @returns - function to notify listeners after calling setDeferred(false),
     *          - null if isDeferred is true, or if the value is unchanged since calling setDeferred(true)
     */
    setDeferred(isDeferred: boolean): (() => void) | null;
    get value(): T;
    protected set value(newValue: T);
    /**
     * This function registers an order dependency between this Property and another. Basically this says that when
     * setting PhET-iO state, each dependency must take its final value before this Property fires its notifications.
     * See propertyStateHandlerSingleton.registerPhetioOrderDependency and https://github.com/phetsims/axon/issues/276 for more info.
     */
    addPhetioStateDependencies(dependencies: Array<TReadOnlyProperty<IntentionalAny>>): void;
    /**
     * Adds listener and calls it immediately. If listener is already registered, this is a no-op. The initial
     * notification provides the current value for newValue and null for oldValue.
     *
     * @param listener - a function that takes a new value, old value, and this Property as arguments
     * @param [options]
     */
    link(listener: PropertyLinkListener<T>, options?: ReadOnlyPropertyLinkOptions): void;
    /**
     * Add a listener to the Property, without calling it back right away. This is used when you need to register a
     * listener without an immediate callback.
     */
    lazyLink(listener: PropertyLazyLinkListener<T>, options?: ReadOnlyPropertyLinkOptions): void;
    /**
     * Removes a listener. If listener is not registered, this is a no-op.
     */
    unlink(listener: PropertyListener<T>): void;
    /**
     * Removes all listeners. If no listeners are registered, this is a no-op.
     */
    unlinkAll(): void;
    /**
     * Links an object's named attribute to this property.  Returns a handle so it can be removed using Property.unlink();
     * Example: modelVisibleProperty.linkAttribute(view,'visible');
     *
     * NOTE: Duplicated with TinyProperty.linkAttribute
     */
    linkAttribute(object: IntentionalAny, attributeName: string): (value: T) => void;
    /**
     * Provide toString for console debugging, see http://stackoverflow.com/questions/2485632/valueof-vs-tostring-in-javascript
     */
    toString(): string;
    /**
     * Convenience function for debugging a Property's value. It prints the new value on registration and when changed.
     * @param name - debug name to be printed on the console
     * @returns - the handle to the linked listener in case it needs to be removed later
     */
    debug(name: string): (value: T) => void;
    isValueValid(value: T): boolean;
    getValidationError(value: T): string | null;
    private addPropertyDisposerAction;
    dispose(): void;
    /**
     * Checks whether a listener is registered with this Property
     */
    hasListener(listener: PropertyLinkListener<T>): boolean;
    /**
     * Returns the number of listeners.
     */
    private getListenerCount;
    /**
     * Invokes a callback once for each listener
     * @param callback - takes the listener as an argument
     */
    forEachListener(callback: (value: (...args: [T, T | null, TinyProperty<T> | ReadOnlyProperty<T>]) => void) => void): void;
    /**
     * Returns true if there are any listeners.
     */
    hasListeners(): boolean;
    get valueComparisonStrategy(): ValueComparisonStrategy<T>;
    set valueComparisonStrategy(valueComparisonStrategy: ValueComparisonStrategy<T>);
    /**
     * Implementation of serialization for PhET-iO support. Override this function to customize how this state
     * behaves (but be careful!).
     *
     * This function is parameterized to support subtyping. That said, it is a bit useless, since we don't want to
     * parameterize ReadOnlyProperty in general to the IOType's state type, so please bear with us.
     */
    protected toStateObject<StateType>(): ReadOnlyPropertyState<StateType>;
    /**
     * Implementation of serialization for PhET-iO support. Override this function to customize how this state
     * behaves (but be careful!).
     */
    protected applyState<StateType>(stateObject: ReadOnlyPropertyState<StateType>): void;
    /**
     * An observable Property that triggers notifications when the value changes.
     * This caching implementation should be kept in sync with the other parametric IOType caching implementations.
     */
    static PropertyIO<T, StateType>(parameterType: IOType<T, StateType>): IOType;
    /**
     * Support treating ourselves as an autoselectable entity for the "strings" selection mode.
     */
    getPhetioMouseHitTarget(fromLinking?: boolean): PhetioObject | 'phetioNotSelectable';
    static readonly CHANGED_EVENT_NAME = "changed";
}
export {};
//# sourceMappingURL=ReadOnlyProperty.d.ts.map