import Collection from "@arcgis/core/core/Collection";
import type Extent from "@arcgis/core/geometry/Extent";
import type Layer from "@arcgis/core/layers/Layer";
import type PortalItem from "@arcgis/core/portal/PortalItem";
import type { RendererUnion } from "@arcgis/core/renderers/types.js";
import type { Feature } from "../data/Feature.js";
import type { FeatureSet } from "../data/FeatureSet.js";
import type { FeatureReadOptions, FeatureWriteOptions } from "../data/FeatureSource.js";
import type { FeatureSourceBaseProperties } from "../data/FeatureSourceBase.js";
import { FeatureSourceBase } from "../data/FeatureSourceBase.js";
import type { QuerySourceCapabilities } from "../data/QuerySourceCapabilities.js";
import { Schema } from "../data/Schema.js";
import type { Relationship, RelationshipProperties } from "../data/_Relationship.js";
import { type LayerJson } from "../json/LayerJson.js";
import type { ArcGISRequestHelper } from "../support/ArcGISRequestHelper.js";
import type { InitializableBase } from "../support/InitializableBase.js";
import type { PropertyDefs } from "../support/Serializable.js";
import type { VisibilityMode } from "../support/esri.js";
import type { PortalItemLike } from "../utilities/portal.js";
import type { BasemapExtension } from "./BasemapExtension.js";
import type { GroundExtension } from "./GroundExtension.js";
import type { MapExtension } from "./MapExtension.js";
import type { SublayerExtension, SublayerExtensionProperties } from "./_SublayerExtension.js";
import type { LayerExtensionFactory } from "./support/LayerExtensionFactory.js";
import type { LayerListSettings, LayerListSettingsProperties } from "./support/LayerListSettings.js";
import type { SublayerExtensionCollection } from "./support/_SublayerExtensionCollection.js";
import { SublayerExtensionCollectionBase } from "./support/_SublayerExtensionCollection.js";
/**
 * Properties that can be passed into the constructor for
 * {@link mapping/_LayerExtension!LayerExtension}.
 */
export interface LayerExtensionProperties extends FeatureSourceBaseProperties {
    /**
     * See {@link mapping/_LayerExtension!LayerExtension.layer}.
     */
    layer?: Layer | LayerProperties;
    /**
     * See {@link mapping/_LayerExtension!LayerExtension.sublayerExtensions}.
     */
    sublayerExtensions?: (SublayerExtension | SublayerExtensionProperties)[];
    /**
     * See {@link mapping/_LayerExtension!LayerExtension.requestHelper}.
     */
    requestHelper?: ArcGISRequestHelper;
    /**
     * See {@link mapping/_LayerExtension!LayerExtension.layerListSettings}.
     */
    layerListSettings?: LayerListSettingsProperties;
    /**
     * See {@link mapping/_LayerExtension!LayerExtension.relationships}.
     */
    relationships?: (Relationship | RelationshipProperties)[];
    /**
     * See {@link mapping/_LayerExtension!LayerExtension.iconUrl}.
     */
    iconUrl?: string;
    /**
     * See {@link mapping/_LayerExtension!LayerExtension.visibilityMode}.
     */
    visibilityMode?: VisibilityMode;
    /**
     * See {@link mapping/_LayerExtension!LayerExtension.tpkSource}.
     */
    tpkSource?: string;
}
/**
 * Properties that can be specified for the
 * {@link mapping/_LayerExtension!LayerExtensionProperties.layer} property.
 */
export type LayerProperties = LayerJson & {
    /**
     * When present, {@link mapping/_LayerExtension!LayerExtension.layer} will be
     * loaded from the given web layer in Portal. The web layer can be specified
     * either as a PortalItem object, or simply using the portal item ID.
     */
    $portalItem?: PortalItemLike;
    /**
     * A reference to an existing layer, which is the ID or title of the layer
     * (or both). In this case, the layer extension will attempt to find an
     * existing layer instead of creating one.
     */
    $ref?: string | LayerReference;
};
/**
 * Matches an existing layer.
 */
export interface LayerReference {
    /**
     * The layer's ID.
     */
    id?: string;
    /**
     * The path to the geodatabase used by an MMAP layer. Mobile only.
     */
    path?: string;
    /**
     * The Layer's type, used for Layer types with multiple possible layer
     * extension mappings.
     */
    subtype?: string;
    /**
     * The layer's title.
     */
    title?: string;
    /**
     * The layer's url.
     */
    url?: string;
}
/**
 * Extends the capabilities of an Esri Layer object.
 */
export declare abstract class LayerExtension<TProperties extends LayerExtensionProperties = LayerExtensionProperties> extends FeatureSourceBase<TProperties> {
    /**
     * The Esri `Layer` object being extended.
     */
    get layer(): Layer;
    /**
     * The parent map extension.
     */
    get mapExtension(): MapExtension;
    /**
     * The parent basemap extension if the extended layer is a layer in a
     * basemap.
     */
    get basemapExtension(): BasemapExtension;
    /**
     * The parent ground extension if the extended layer is an elevation layer
     * in a ground object.
     */
    get groundExtension(): GroundExtension;
    /**
     * The parent layer extension if the extended layer is in a group layer.
     */
    get parentLayerExtension(): LayerExtension;
    /**
     * Determines whether this type of layer is capable of producing features.
     */
    get hasFeatures(): boolean;
    get capabilities(): QuerySourceCapabilities;
    /**
     * The renderer, if any, that the ESRI layer uses to display data on the
     * map.
     */
    get renderer(): RendererUnion;
    /**
     * Indicates how to manage the visibility of the children layers or
     * sublayers.
     */
    get visibilityMode(): VisibilityMode;
    set visibilityMode(value: VisibilityMode);
    /**
     * The sublayer extensions associated with each sublayer of this layer.
     */
    get sublayerExtensions(): SublayerExtensionCollection;
    /**
     * The {@link utilities/RequestHelper!RequestHelper} to use when making
     * requests to external services. If not specified, a default implementation
     * will be used.
     */
    get requestHelper(): ArcGISRequestHelper;
    set requestHelper(value: ArcGISRequestHelper);
    /**
     * See {@link data/FeatureSource!FeatureSource.title}.
     */
    get title(): string;
    /**
     * Determines whether this type of layer is capable of having sublayers.
     */
    get supportsSublayers(): boolean;
    /**
     * The effective min scale for this layer extension.
     */
    get effectiveMinScale(): number;
    /**
     * The effective max scale for this layer extension.
     */
    get effectiveMaxScale(): number;
    /**
     * The effective visibility for this layer extension.
     */
    get isEffectivelyVisible(): boolean;
    /**
     * The effective full extent of this layer extension.
     */
    get effectiveFullExtent(): Extent;
    /**
     * Determines whether the type of layer being extended supports changing
     * Scale.
     */
    get canChangeScale(): boolean;
    /**
     * Determines whether the type of layer being extended supports changing
     * opacity.
     */
    get canChangeOpacity(): boolean;
    /**
     * Determines whether the type of layer being extended supports changing
     * labels. Default is false.
     */
    get canChangeLabels(): boolean;
    /**
     * Determines whether the type of layer being extended supports changing its
     * renderer.
     */
    get canChangeRenderer(): boolean;
    /**
     * Determines whether the type of layer being extended supports changing its
     * definition expression.
     */
    get canChangeDefinitionExpression(): boolean;
    /**
     * String value containing the initial definition expression configured on
     * the layer.
     */
    get initialDefinitionExpression(): string | undefined;
    /**
     * A clone of the initial renderer, if any, that the ESRI layer uses to
     * display data on the map.
     */
    get initialRenderer(): RendererUnion | undefined;
    /**
     * Indicates the initial layer visibility.
     */
    get initialVisibility(): boolean;
    /**
     * The layer's sublayers.
     */
    private get _sublayers();
    /**
     * The factory that will be used whenever a new layer extension needs to be
     * created. Applications can supply their own factory to customize layer
     * extension creation.
     */
    static factory: LayerExtensionFactory;
    /**
     * Indicates that the layer was added dynamically.
     */
    get dynamicallyAddedLayer(): boolean;
    set dynamicallyAddedLayer(value: boolean);
    /**
     * Handle group key for watchers on the current `layer`.
     */
    private static readonly _layerWatchHandlesKey;
    /**
     * An optional remote source for a .tpk, .tpkx or .vtpk file. May be a
     * portal item URL or a portal item ID. Mobile Only.
     */
    tpkSource: string;
    /**
     * Settings that affect the behavior and presentation of the layer in the
     * layer list.
     */
    readonly layerListSettings: LayerListSettings;
    /**
     * All descendant sublayer extensions associated with this layer.
     */
    readonly allSublayerExtensions: SublayerExtensionCollection;
    /**
     * Determines whether the type of layer being extended has a readonly
     * sublayer collection.
     */
    get sublayersAreReadOnly(): boolean;
    /**
     * @inheritDoc
     */
    protected readonly _itemType: string;
    private _mapExtension;
    private _basemapExtension;
    private _groundExtension;
    private _parentLayerExtension;
    private readonly _sublayerExtensions;
    private _layer;
    private _dynamicallyAddedLayer;
    private _isSwitchingLayer;
    private _deferredLayerProperties;
    private _requestHelper;
    private _initialDefinitionExpression;
    private _initialRenderer;
    private _initialVisibility;
    private _visibilityMode;
    private readonly _portalItem;
    /**
     * Creates a new instance of {@link mapping/_LayerExtension!LayerExtension}.
     *
     * @param properties An object containing initial property values to set.
     */
    constructor(properties?: TProperties);
    /**
     * Creates the appropriate subclass of
     * {@link mapping/_LayerExtension!LayerExtension} based on the supplied
     * properties. Applications can customize the default creation behavior by
     * supplying a custom factory object (see
     * {@link mapping/_LayerExtension!LayerExtension.factory}).
     *
     * @param properties The layer extension properties.
     */
    static create(properties: LayerExtensionProperties): LayerExtension;
    /**
     * Creates the appropriate subclass of
     * {@link mapping/_LayerExtension!LayerExtension} based on the type of the
     * supplied portal item.
     *
     * @param portalItemLike The portal item that determines the subclass to
     *   create.
     * @param layerExtensionProperties The properties used to create the
     *   subclass.
     */
    static fromPortalItem(portalItemLike: PortalItemLike, layerExtensionProperties?: Partial<LayerExtensionProperties>): Promise<LayerExtension>;
    getFeatures(ids: string[], options?: FeatureReadOptions): AsyncIterable<Feature>;
    getFullExtent(): Extent | undefined;
    addFeatures(features: FeatureSet, options?: FeatureWriteOptions): Promise<void>;
    updateFeatures(features: FeatureSet, options?: FeatureWriteOptions): Promise<void>;
    deleteFeatures(ids: string[], options?: FeatureWriteOptions): Promise<void>;
    deleteFeatures(features: Iterable<Feature>, options?: FeatureWriteOptions): Promise<void>;
    /**
     * A callback executed when a sublayer is added as a child of the
     * LayerExtension, after the LayerExtension has been initialized.
     *
     * @param sublayerX The sublayer that was added.
     */
    protected readonly _onSublayerAddedPostInitialize: (sublayerX: SublayerExtension) => Promise<void>;
    protected _onDestroy(): Promise<void>;
    protected _getSerializableProperties(): PropertyDefs<TProperties>;
    /**
     * Overridden in child sublayer extensions that need to add an layerType ref
     * properties.
     */
    protected _getSerializableLayerType(): string | undefined;
    /**
     * Overridden in child sublayer extensions that need to add additional
     * properties when serializing layer references.
     */
    protected _getSerializableRefLayerProperties(): Record<string, unknown>;
    /**
     * Called to create a child sublayer extension. Must be overridden by layer
     * extensions that support sublayers.
     *
     * @param properties Properties used to initialize the sublayer extension.
     */
    protected _createSublayerExtension(properties?: SublayerExtensionProperties): SublayerExtension;
    /**
     * Determines whether the layer is of the right type for the type of layer
     * extension.
     *
     * @param layer The layer to validate.
     */
    protected abstract _isSupportedLayer(layer: Layer): boolean;
    protected _onInitialize(): Promise<void>;
    protected _postInitialize(): Promise<void>;
    /**
     * Apply properties from a portal item to an ESRI API Layer object.
     *
     * @param portalItem The portal item to apply.
     */
    protected _applyPortalItemProperties(portalItem: PortalItem): void | Promise<void>;
    /**
     * Called prior to loading the layer in order to perform any extra
     * initialization.
     */
    protected _initializeLayer(): Promise<void>;
    /**
     * Called to create the
     * {@link mapping/support/LayerListSettings!LayerListSettings} for this layer
     * extension.
     *
     * @param properties Initial properties for the layer list settings.
     */
    protected _createLayerListSettings(properties?: LayerListSettingsProperties): LayerListSettings;
    /**
     * Called to create the
     * {@link mapping/support/_SublayerExtensionCollection!SublayerExtensionCollection}
     * for this layer extension.
     */
    protected _createSublayerExtensionCollection(): SublayerExtensionCollectionBase;
    protected _capabilities(): QuerySourceCapabilities;
    protected _initializableChildCollections(): IterableIterator<Collection<InitializableBase>>;
    /**
     * Called to create an Esri layer from layer properties.
     *
     * @param properties The initial layer properties to apply.
     */
    protected _createLayer(properties: LayerProperties): Promise<Layer>;
    /**
     * Called to apply layer properties to a layer.
     *
     * @param properties The layer properties to apply.
     * @param layer The layer to apply properties to.
     */
    protected _applyLayerProperties(properties: LayerProperties, layer: Layer): Promise<void>;
    private _setLayer;
    private _setupSublayersHandles;
    private readonly _onVisibleChanged;
    private readonly _onSublayersSublayerVisibleChanged;
    private readonly _onSublayersAfterAdd;
    private readonly _onSublayersAfterRemove;
    private _ensureAChildSublayerVisible;
    private _ensureAtMostOneChildSublayerVisible;
}
/**
 * Represents advance options for a binding between a schema setting and a Layer
 * property.
 */
export interface LayerExtensionSchemaPropertyBindingOptions {
    /**
     * Value that will always be returned for this binding.
     */
    value?: unknown;
    /**
     * Whether the binding is readonly.
     */
    readonly?: boolean;
    /**
     * Property or property path to bind to.
     */
    property?: string;
    /**
     * True by default.
     */
    sync?: boolean;
}
/**
 * Represents a binding between a schema setting and a Layer property.
 */
export type LayerExtensionSchemaPropertyBinding = string | LayerExtensionSchemaPropertyBindingOptions;
/**
 * An implementation of Schema that allows for schema properties to directly
 * mirror equivalent properties on a Layer.
 */
export declare class LayerExtensionSchema extends Schema {
    /**
     * The parent layer extension.
     */
    protected readonly _layerExtension: LayerExtension;
    /**
     * Maps schema properties to properties on Layer.
     */
    protected readonly _layerBindings: Map<keyof this, LayerExtensionSchemaPropertyBinding>;
    constructor(layerExtension: LayerExtension);
    /**
     * Returns the property bindings.
     */
    protected _getPropertyBindings(): Partial<Record<keyof this, LayerExtensionSchemaPropertyBinding>>;
    protected _hasSettingIncludingAncestor<K extends keyof this>(setting: K): boolean;
    protected _getSetting<K extends keyof this>(setting: K, defaultValue?: this[K]): this[K];
    protected _setSetting<K extends keyof this>(setting: K, value: this[K]): void;
    /**
     * Binds the settings to the equivalent properties on the layer.
     */
    private _bindSettingsToLayerProperties;
    /**
     * Invoked when the layer is available.
     *
     * @param layer The newly resolved layer.
     */
    private _onLayerResolved;
}
/**
 * An implementation of Schema that allows for schema properties to directly
 * mirror equivalent properties on a Layer. Attempting to set bound properties
 * will result in a readonly error.
 */
export declare class LayerExtensionReadOnlySchema extends LayerExtensionSchema {
    protected _setSetting<K extends keyof this>(setting: K, value: this[K]): void;
}
/**
 * The error message for when readonly schema properties are set.
 */
export declare const ERR_SCHEMA_READ_ONLY = "This schema property is read-only.";
