import { Evented } from "@arcgis/core/core/Evented.js";
/**
 * A class that can take in initial property values in its constructor.
 */
export type SerializableClass<P, T extends SerializableBase<P>> = new (properties?: P, ...other: any[]) => T;
/**
 * An object that can be serialized to/from plain JSON.
 */
export interface Serializable<TProperties> {
    /**
     * Returns a serializable representation of the item.
     *
     * @param serializeMode If specified, only properties that are appropriate
     *   for the given mode are returned. Otherwise, all properties will be
     *   serialized.
     */
    toJSON(serializeMode?: SerializeMode): Partial<TProperties>;
    /**
     * Sets the properties for this item.
     *
     * @param properties A plain object containing property values to set, keyed
     *   by property name.
     */
    assignProperties(properties: Partial<TProperties>): void;
    /**
     * Sets the properties for this item.
     *
     * This version will also await any asynchronous logic that is needed to set
     * the properties.
     *
     * @param properties A plain object containing property values to set, keyed
     *   by property name.
     */
    assignPropertiesAsync(properties: Partial<TProperties>): Promise<void>;
    /**
     * Waits for all deserialization logic initiated thus far to finish, whether
     * invoked by passing properties into the constructor, or by invoking
     * `assignProperties()` or `assignPropertiesAsync()`.
     */
    finishAssignProperties(): Promise<void>;
    /**
     * Gets the object's default property values.
     */
    getDefaults(): Partial<TProperties>;
    /**
     * Gets the default value of an object's property.
     *
     * @param key The property of the object for which to get the default value.
     */
    getDefault<K extends keyof TProperties>(key: K): TProperties[K];
    /**
     * Returns the serializable properties.
     *
     * @param serializeMode Optional. If specified, only properties that support
     *   the given serialization mode will be returned.
     */
    getSerializableProperties(serializeMode?: SerializeMode): PropertyDefs<TProperties>;
}
/**
 * Default implementation of a {@link Serializable} that supports observability
 * and serialization.
 */
export declare abstract class SerializableBase<TProperties> extends Evented implements Serializable<TProperties> {
    private readonly _assignPropertiesPromises;
    constructor(_properties?: TProperties);
    /**
     * @inheritDoc
     */
    toJSON(serializeMode?: SerializeMode): TProperties;
    /**
     * @inheritDoc
     */
    assignProperties(properties: Partial<TProperties>): void;
    /**
     * @inheritDoc
     */
    assignPropertiesAsync(properties: Partial<TProperties>): Promise<void>;
    /**
     * @inheritDoc
     */
    finishAssignProperties(): Promise<void>;
    /**
     * Returns the serializable properties.
     *
     * @param serializeMode Optional. If specified, only properties that support
     *   the given serialization mode will be returned.
     */
    getSerializableProperties(serializeMode?: SerializeMode): PropertyDefs<TProperties>;
    /**
     * @inheritDoc
     */
    getDefaults(): TProperties;
    /**
     * @inheritDoc
     */
    getDefault<K extends keyof TProperties>(key: K): TProperties[K];
    /**
     * The property keys and their metadata that are used to implement
     * serializing and deserializing the class instance.
     */
    protected _getSerializableProperties(): PropertyDefs<TProperties>;
    /**
     * Converts the value to a PropertyDef object.
     *
     * @param def The value to convert.
     */
    protected _toPropertyDef<T>(def: PropertyDef<T> | PropertyDefSerializeMode[] | PropertyDefSerializeMode): PropertyDef<T>;
}
/**
 * A decorator that marks a class as being serializable.
 *
 * @param SerializableClass The decorated class.
 */
export declare function serializable<P>(SerializableClass: SerializableClass<P, any>): any;
/**
 * A flag that's passed into an item's toJSON() function that is used to
 * serialize the item in different ways. Depending on the flag, some properties
 * may be present in the serialization or filtered out.
 */
export type SerializeMode = "initial" | "initial-with-defaults" | "project" | "preferences" | "all";
/**
 * The set of allowed {@link SerializeMode}s when defining the serialize mode for
 * a property definition.
 */
export type PropertyDefSerializeMode = Exclude<SerializeMode, "initial-with-defaults">;
/**
 * A set of {@link PropertyDef}s for an object that allows it to be intelligently
 * serialized and deserialized.
 */
export type PropertyDefs<T> = {
    [P in keyof T]?: PropertyDef<T[P]> | PropertyDefSerializeMode[] | PropertyDefSerializeMode;
};
/**
 * Metadata that describes how (and whether) a given property should be
 * serialized and deserialized.
 */
export interface PropertyDef<T> {
    /**
     * The flag values that will cause the property to serialize.
     */
    serializeModes?: PropertyDefSerializeMode[];
    /**
     * The default value of the property. This is used to prevent unnecessary
     * config from making its way into an exported json file.
     */
    default?: T;
    /**
     * A function that takes in a serialized value of the property and returns a
     * boolean depicting whether or not the value is equivalent to the
     * property's default value. This is used to prevent unnecessary config from
     * making its way into an exported json file.
     */
    isDefault?: (value: T, serializeMode: SerializeMode) => boolean;
    /**
     * A function that serializes the property into configuration. Setting this
     * to `false` will disable serialization for this property.
     */
    serialize?: ((mode?: SerializeMode) => T) | false;
    /**
     * A function that deserializes configuration into the property. Setting
     * this to `false` will disable deserialization for this property.
     */
    deserialize?: ((config: T) => void | Promise<void>) | false;
}
/**
 * Whether the serialize mode should include default values.
 *
 * @param mode The flag that determines how the item should be serialized.
 */
export declare function shouldExcludeDefaults(mode: SerializeMode): boolean;
/**
 * Serializes an item and filters out properties based on the serializationMode
 * flag that's provided.
 *
 * @param defs The property definitions associated with the item's properties.
 * @param context The item being serialized.
 * @param serializeMode The flag that determines how the item should be
 *   serialized.
 */
export declare function filterJSONProperties<T, TContext extends object = object>(defs: PropertyDefs<T>, context: TContext, serializeMode: SerializeMode): T;
/**
 * Sets properties on an object based on deserialization rules defined in
 * property metadata.
 *
 * @param defs The property metadata for the object.
 * @param obj The object to modify.
 * @param properties The property values to set keyed by property name.
 */
export declare function assignProperties<T>(defs: PropertyDefs<T>, obj: object, properties: Partial<T>): void;
/**
 * Sets properties on an object based on deserialization rules defined in
 * property metadata. This will also await any deserialization that is performed
 * asynchronously.
 *
 * @param defs The property metadata for the object.
 * @param obj The object to modify.
 * @param properties The property values to set keyed by property name.
 */
export declare function assignPropertiesAsync<T>(defs: PropertyDefs<T>, obj: object, properties: Partial<T>): Promise<void>;
/**
 * Gets default property values from an object's property.
 *
 * @param defs The property metadata for an object.
 */
export declare function getDefaults<T>(defs: PropertyDefs<T>): T;
/**
 * Gets the default value of an object's property.
 *
 * @param defs The property metadata for an object.
 * @param key The property of the object for which to get the default value.
 */
export declare function getDefault<T, TProperty = unknown>(defs: PropertyDefs<T>, key: keyof T): TProperty;
/**
 * Determines if given value takes the form of a default property value in JSON.
 * This function returns true when the value is undefined, null, an empty
 * object, or an empty array.
 *
 * @param value The value to check.
 */
export declare function isDefault(value: unknown): boolean;
/**
 * Converts the value to a PropertyDef object.
 *
 * @param def The value to convert.
 */
export declare function toPropertyDef<T>(def: PropertyDef<T> | PropertyDefSerializeMode[] | PropertyDefSerializeMode): PropertyDef<T>;
/**
 * Returns whether or not an object is serializable.
 *
 * @param obj The object to test.
 */
export declare function isSerializable<T>(obj: unknown): obj is Serializable<T>;
/**
 * Returns the PropertyDefs for a Serializable instance that are relevant for a
 * given SerializeMode.
 *
 * @param propertyDefs All property defs for the Serializable instance.
 * @param serializeMode The serialize mode.
 */
export declare function getSerializableProperties<TProperties>(propertyDefs: PropertyDefs<TProperties>, serializeMode?: SerializeMode): {
    [P in keyof TProperties]?: PropertyDef<TProperties[P]>;
};
