import { Color, type ColorRepresentation, EventDispatcher, type MagnificationTextureFilter, type Material, type MinificationTextureFilter, type Object3D, type Object3DEventMap, type PixelFormat, type Texture, type TextureDataType, Vector2, type WebGLRenderTarget } from 'three';
import type RenderingContextHandler from '../../renderer/RenderingContextHandler';
import type ImageSource from '../../sources/ImageSource';
import type ColorMap from '../ColorMap';
import type Context from '../Context';
import type Disposable from '../Disposable';
import type ElevationRange from '../ElevationRange';
import type Coordinates from '../geographic/Coordinates';
import type CoordinateSystem from '../geographic/CoordinateSystem';
import type { GridExtent } from '../geographic/Extent';
import type Instance from '../Instance';
import type MemoryUsage from '../MemoryUsage';
import type OffsetScale from '../OffsetScale';
import type Progress from '../Progress';
import type RequestQueue from '../RequestQueue';
import type ColorLayer from './ColorLayer';
import type NoDataOptions from './NoDataOptions';
import Extent from '../geographic/Extent';
import { type GetMemoryUsageContext } from '../MemoryUsage';
import Shared from '../Shared';
import Interpretation from './Interpretation';
import LayerComposer from './LayerComposer';
export interface TextureAndPitch {
    texture: Texture;
    pitch: OffsetScale;
}
/**
 * Events for nodes.
 */
export interface LayerNodeEventMap extends Object3DEventMap {
    dispose: unknown;
    'visibility-changed': unknown;
}
/**
 * A node material.
 */
export interface LayerNodeMaterial extends Material {
    setColorTextures(layer: ColorLayer, textureAndPitch: TextureAndPitch): void;
    setLayerVisibility(layer: ColorLayer, visible: boolean): void;
    setLayerOpacity(layer: ColorLayer, opacity: number): void;
    setLayerElevationRange(layer: ColorLayer, range: ElevationRange | null): void;
    setColorimetry(layer: ColorLayer, brightness: number, contrast: number, saturation: number): void;
    hasColorLayer(layer: ColorLayer): boolean;
    indexOfColorLayer(layer: ColorLayer): number;
    removeColorLayer(layer: ColorLayer): void;
    pushColorLayer(layer: ColorLayer, extent: Extent): void;
}
/**
 * Represents an object that can be painted by this layer.
 * Nodes might be map tiles or anything else that matches the interface definition.
 */
export interface LayerNode extends Object3D<LayerNodeEventMap> {
    /**
     * Is this node disposed ?
     */
    disposed: boolean;
    /**
     * The node material.
     */
    material: LayerNodeMaterial;
    /**
     * The node texture size, in pixels.
     */
    textureSize: Vector2;
    /**
     * Gets whether this node can accept a color layer texture.
     */
    canProcessColorLayer(): boolean;
    /**
     * The node's extent.
     */
    getExtent(): Extent;
    /**
     * The LOD or depth level of this node in the hierarchy (the root node is level zero).
     */
    lod: number;
}
declare enum TargetState {
    Pending = 0,
    Processing = 1,
    Complete = 2
}
export declare class Target implements MemoryUsage {
    readonly isMemoryUsage: true;
    node: LayerNode;
    pitch: OffsetScale;
    extent: Extent;
    width: number;
    height: number;
    renderTarget: Shared<WebGLRenderTarget, this> | null;
    imageIds: Set<string>;
    controller: AbortController;
    state: TargetState;
    textureIsFinal: boolean;
    geometryExtent: Extent;
    paintCount: number;
    private _disposed;
    private _onVisibilityChanged;
    isDisposed(): boolean;
    getMemoryUsage(context: GetMemoryUsageContext): void;
    constructor(options: {
        node: LayerNode;
        extent: Extent;
        geometryExtent: Extent;
        pitch: OffsetScale;
        width: number;
        height: number;
    });
    dispose(): void;
    private onVisibilityChanged;
    reset(): void;
    abort(): void;
    abortAndThrow(): void;
}
export interface LayerEvents {
    /**
     * Fires when layer visibility changes.
     */
    'visible-property-changed': {
        visible: boolean;
    };
    /**
     * Fires when the layer is disposed.
     */
    dispose: unknown;
    /**
     * Fires when a node has been completed.
     */
    'node-complete': {
        node: LayerNode;
        layer: Layer;
    };
}
export interface LayerOptions {
    /**
     * An optional name for this layer.
     */
    name?: string;
    /**
     * The source of the layer.
     */
    source: ImageSource;
    /**
     * The optional extent to use for this layer. If none is provided, then the extent from the
     * source is used instead. The layer will not be visible outside this extent.
     */
    extent?: Extent;
    /**
     * How to interpret the pixel data of the source.
     */
    interpretation?: Interpretation;
    /**
     * Displays the border of source images.
     */
    showTileBorders?: boolean;
    /**
     * Displays empty textures as colored rectangles.
     */
    showEmptyTextures?: boolean;
    /**
     * How to treat no-data values.
     */
    noDataOptions?: NoDataOptions;
    /**
     * Enables min/max computation of source images. Mainly used for elevation data.
     */
    computeMinMax?: boolean;
    /**
     * The optional color map to use.
     */
    colorMap?: ColorMap;
    /**
     * Enables or disable preloading of low resolution fallback images. Those fallback images
     * are used when no data is available yet on a particular region of the layer.
     */
    preloadImages?: boolean;
    /**
     * The optional background color of the layer.
     */
    backgroundColor?: ColorRepresentation;
    /**
     * The resolution factor applied to textures generated by this layer, compared to the pixel size
     * of the targets. Default is `1`. A value greater than one will create textures with a higher
     * resolution than what is asked by the targets. For example, if a map tile has a texture size
     * of 256\*256, and a layer has a resolution factor of 2, the generated textures will have a
     * size of 512\*512 pixels.
     */
    resolutionFactor?: number;
    /**
     * The optional texture filter for minification.
     * @defaultValue Generally bilinear filtering, but some sources might provide different defaults.
     */
    minFilter?: MinificationTextureFilter;
    /**
     * The optional texture filter for magnification.
     * @defaultValue Generally bilinear filtering, but some sources might provide different defaults.
     */
    magFilter?: MagnificationTextureFilter;
}
export type LayerUserData = Record<string, unknown>;
/**
 * Base class of layers. Layers are components of maps or any compatible entity.
 *
 * The same layer can be added to multiple entities. Don't forget to call {@link dispose} when the
 * layer should be destroyed, as removing a layer from an entity will not release memory associated
 * with the layer (such as textures).
 *
 * ## Layer nodes
 *
 * Layers generate textures to be applied to {@link LayerNode | nodes}. Nodes might be map tiles, point
 * cloud tiles or any object that matches the definition of the interface.
 *
 * ## Types of layers
 *
 * `Layer` is an abstract class. See subclasses for specific information. Main subclasses:
 *
 * - `ColorLayer` for color information, such as satellite imagery, vector data, etc.
 * - `ElevationLayer` for elevation and terrain data.
 * - `MaskLayer`: a special kind of layer that applies a mask on its host map.
 *
 * ## The `userData` property
 *
 * The `userData` property can be used to attach custom data to the layer, in a type safe manner.
 * It is recommended to use this property instead of attaching arbitrary properties to the object:
 *
 * ```ts
 * type MyCustomUserData = {
 *   creationDate: Date;
 *   owner: string;
 * };
 * const newLayer = new ColorLayer<MyCustomUserData>({ ... });
 *
 * newLayer.userData.creationDate = Date.now();
 * newLayer.userData.owner = 'John Doe';
 * ```
 *
 * ## Reprojection capabilities
 *
 * When the {@link source} of the layer has a different coordinate system (CRS) than the instance,
 * the images from the source will be reprojected to the instance CRS.
 *
 * Note that doing so will have a performance cost in both CPU and memory.
 *
 * ```js
 * // Add and create a new Layer to an existing map.
 * const newLayer = new ColorLayer({ ... });
 *
 * await map.addLayer(newLayer);
 *
 * // Change layer's visibilty
 * newLayer.visible = false;
 * instance.notifyChange(); // update instance
 *
 * // Change layer's opacity
 * newLayer.opacity = 0.5;
 * instance.notifyChange(); // update instance
 *
 * // Listen to properties
 * newLayer.addEventListener('visible-property-changed', (event) => console.log(event));
 * ```
 * @typeParam TEvents - The event map of the layer.
 * @typeParam TUserData - The type of the `userData` property.
 */
export declare abstract class Layer<TEvents extends LayerEvents = LayerEvents, TUserData extends LayerUserData = LayerUserData> extends EventDispatcher<TEvents & LayerEvents> implements Progress, MemoryUsage, RenderingContextHandler, Disposable {
    readonly isMemoryUsage: true;
    /**
     * Optional name of this layer.
     */
    readonly name: string | undefined;
    /**
     * The unique identifier of this layer.
     */
    readonly id: string;
    /**
     * Read-only flag to check if a given object is of type Layer.
     */
    readonly isLayer: boolean;
    type: string;
    readonly interpretation: Interpretation;
    readonly showTileBorders: boolean;
    readonly showEmptyTextures: boolean;
    readonly noDataOptions: NoDataOptions;
    readonly computeMinMax: boolean;
    private _visible;
    /** The colormap of this layer */
    readonly colorMap: ColorMap | null;
    /** The extent of this layer */
    readonly extent: Extent | null;
    /** The source of this layer */
    readonly source: ImageSource;
    /** @internal */
    protected _composer: LayerComposer | null;
    private readonly _targets;
    private readonly _targetsToDestroy;
    private readonly _filter;
    /** @internal */
    protected readonly _queue: RequestQueue;
    private readonly _opCounter;
    private _sortedTargets;
    private _instance;
    private _composerProjection;
    private readonly _createReadableTextures;
    private readonly _preloadImages;
    private readonly _minFilter?;
    private readonly _magFilter?;
    private _fallbackImagesPromise;
    /** The resolution factor applied to the textures generated by this layer. */
    readonly resolutionFactor: number;
    private _preprocessOnce;
    private _onNodeDisposed;
    private _ready;
    backgroundColor: Color;
    /**
     * An object that can be used to store custom data about the {@link Layer}.
     */
    readonly userData: TUserData;
    /**
     * Disables automatic updates of this layer. Useful for debugging purposes.
     */
    frozen: boolean;
    get ready(): boolean;
    getMemoryUsage(context: GetMemoryUsageContext): void;
    /**
     * Creates a layer.
     *
     * @param options - The layer options.
     */
    constructor(options: LayerOptions);
    private shouldCancelRequest;
    private onSourceUpdated;
    onRenderingContextLost(): void;
    onRenderingContextRestored(): void;
    /**
     * Resets all render targets to a blank state and repaint all the targets.
     * @param extent - An optional extent to limit the region to clear.
     */
    clear(extent?: Extent): void;
    /**
     * Gets or sets the visibility of this layer.
     */
    get visible(): boolean;
    set visible(v: boolean);
    get loading(): boolean;
    get progress(): number;
    /**
     * Initializes this layer. Note: this method is automatically called when the layer is added
     * to an entity.
     *
     * @param options - Initialization options.
     * @returns A promise that resolves when the initialization is complete.
     * @internal
     */
    initialize(options: {
        /**
         * The instance to associate this layer.
         * Once set, the layer cannot be used with any other instance.
         */
        instance: Instance;
        composerProjection: CoordinateSystem;
    }): Promise<this>;
    protected get instance(): Instance;
    /**
     * Perform the initialization. This should be called exactly once in the lifetime of the layer.
     */
    private initializeOnce;
    /**
     * Returns the final extent of this layer. If this layer has its own extent defined,
     * this will be used.
     * Otherwise, will return the source extent (if any).
     * May return undefined if not pre-processed yet.
     *
     * @returns The layer final extent.
     */
    getExtent(): Extent | undefined;
    loadFallbackImagesInternal(): Promise<void>;
    protected onTextureCreated(texture: Texture): void;
    private addToComposer;
    loadFallbackImages(): Promise<void>;
    /**
     * Called when the layer has finished initializing.
     */
    protected onInitialized(): Promise<void>;
    private fetchImagesSync;
    private getExtentAsSourceCRS;
    /**
     * @param options - Options.
     * @returns A promise that is settled when all images have been fetched.
     */
    private fetchImages;
    private destroyTarget;
    /**
     * Removes the node from this layer.
     *
     * @param node - The disposed node.
     */
    unregisterNode(node: LayerNode, immediate?: boolean): void;
    protected adjustExtent(extent: Extent): Extent;
    /**
     * Adjusts the extent to avoid visual artifacts.
     *
     * @param originalExtent - The original extent.
     * @param originalWidth - The width, in pixels, of the original extent.
     * @param originalHeight - The height, in pixels, of the original extent.
     * @returns And object containing the adjusted extent, as well as adjusted pixel size.
     */
    protected adjustExtentAndPixelSize(originalExtent: Extent, originalWidth: number, originalHeight: number): GridExtent;
    /**
     * @returns Targets sorted by extent dimension.
     */
    private getSortedTargets;
    /**
     * Get the pixels colors of this layer at coordinate.
     * This will samples all pixel colors within a square region of specified size, centered at the given coordinate.
     * Returns undefined if no non-transparent (colored) pixels are found, or if no texture is available for this coordinate.
     *
     * Note: only 8-bit layers are supported. If the layer has non 8-bit pixels, returns `undefined`.
     * @returns The colors
     */
    getPixel(params: {
        /**
         * The coordinate to sample.
         */
        coordinates: Coordinates;
        /**
         * The size, in pixels, of the square to sample
         * @defaultValue 1
         */
        size?: number;
    }): Color[] | undefined;
    /**
     * Returns the first ancestor that is completely loaded, or null if not found.
     * @param target - The target.
     * @returns The smallest target that still contains this extent.
     */
    private getLoadedAncestor;
    private getLoadedDirectChildren;
    private borrowTextureFromAncestor;
    private borrowTexturesFromChildren;
    private generateDefaultTextureFromExistingComposerImages;
    /**
     * Immediately applies a temporary texture to the target while
     * the actual texture is being asynchronously processed, to
     * avoid displaying a black texture.
     */
    protected applyInterimTexture(target: Target): void;
    /**
     * @internal
     */
    getInfo(node: LayerNode): {
        state: string;
        imageCount: number;
        paintCount: number;
    };
    /**
     * Processes the target once, fetching all images relevant for this target,
     * then paints those images to the target's texture.
     *
     * @param target - The target to paint.
     */
    private processTarget;
    private createRenderTargetIfNecessary;
    private paintTarget;
    private setTargetState;
    /**
     * Updates the provided node with content from this layer.
     *
     * @param context - the context
     * @param node - the node to update
     */
    update(context: Context, node: LayerNode): void;
    /**
     * @param extent - The extent to test.
     * @returns `true` if this layer contains the specified extent, `false` otherwise.
     */
    contains(extent: Extent): boolean;
    abstract getRenderTargetPixelFormat(): PixelFormat;
    abstract getRenderTargetDataType(): TextureDataType;
    /**
     * @param target - The render target to release.
     */
    private releaseRenderTarget;
    /**
     * @param width - Width
     * @param height - Height
     * @returns The render target.
     */
    private acquireRenderTarget;
    postUpdate(): void;
    /**
     * @internal
     */
    get composer(): Readonly<LayerComposer | null>;
    protected updateMaterial(material: Material): void;
    /**
     * Returns true if this layer has loaded data for this node.
     */
    isLoaded(nodeId: LayerNode['id']): boolean;
    protected abstract applyTextureToNode(texture: TextureAndPitch, target: Target, isLastRender: boolean): void;
    protected abstract applyEmptyTextureToNode(target: Target): void;
    /**
     * Disposes the layer. This releases all resources held by this layer.
     */
    dispose(): void;
}
/**
 * Returns `true` if the given object is a {@link Layer}.
 */
export declare function isLayer(obj: unknown): obj is Layer;
export default Layer;
//# sourceMappingURL=Layer.d.ts.map