import { CustomLayerInterface, CustomRenderMethodInput, MapProjectionEvent, Map as MapSDK } from '@maptiler/sdk';
import { Extent } from 'ol/extent.js';
import { ColoringFragmentBase, MultiChannelGradientColoringFragment } from '../../core/ColoringFragment';
import { Tile, TileTextureSource } from '../../core/TileTextureSource';
import { TimeFrame, TimeFrameAnimation } from '../../core/TimeFrameAnimation';
import { GlobeTilesService } from '../../tiles/GlobeTilesService';
import { TileLayerOptions, TilePlacement, TileList } from './types';
import * as three from "three";
/**
 * Special layer that can be added to MapTiler SDK's Map.
 * Consists of multiple timeframes, every frame is a tile pyramid in a different moment in time.
 * The individual frames are smoothly animated.
 * Decoding of the data and their visual representation is configurable.
 */
declare class TileLayer extends TimeFrameAnimation<TileTextureSource> implements CustomLayerInterface {
    id: string;
    type: "custom";
    renderingMode: "3d";
    /**
     * Instance of MapTiler SDK map
     */
    protected map: MapSDK | null;
    protected dataMinZoom: number;
    protected dataMaxZoom: number;
    /**
     * Array of array of Tiles (plane geometry meshes)
     */
    protected readonly slippyTiles: Array<Array<three.Mesh>>;
    /**
     * Renderer to render the tiles
     */
    protected renderer: three.WebGLRenderer | null;
    /**
     * Camera used to render the tiles
     */
    protected readonly camera: three.Camera;
    /**
     * Scene to add the tiles to
     */
    protected readonly scene: three.Scene;
    /**
     * The shader material of the tiles (with uniforms such as textures, time, etc.)
     * TODO: Fix the initialisation to get rid of the `!` operator
     */
    private material;
    /**
     * The plane geometry used for all the tiles
     */
    private geometry;
    /**
     * A TileGrid (from OL) that contains some tile logic such as mercator to index, etc.
     */
    private tilegrid;
    /**
     * Extent as in OL
     */
    private extent;
    /**
     * Indicated whether the the function `map.triggerRepaint()` should be called
     * when the animation is paused.
     */
    private repaintOnPausedAnimation;
    /**
     * Manages a pool of rawshadermaterial to reuse, rather cloning endlessly
     */
    private materialPool;
    private bluringNodePasses;
    /**
     * ratio to wich the extent is enlarged when using the method `.getVisibleExtent()`
     */
    protected extentScale: number;
    /**
     * The event `"extentChanged"` is emitted when the intersection-over-union ration from the former extent to the new
     * is below this.extentChangedThreshold
     */
    private extentChangedThreshold;
    private lastExtent;
    private timeInterpolation;
    protected isReady: boolean;
    private defaultTexture;
    private onMoveEndListener;
    private onResizeListener;
    private onMoveListener;
    private onProjectionChangedListener;
    private coloringFragments;
    private multiChannelColoringFragment;
    private loadLowerZoomLevels;
    private interpolateTileEdge;
    private flusher;
    /**
     * Globe related changes
     */
    protected globeTilesService: GlobeTilesService;
    protected threeWorldGroup: three.Group;
    protected slippyTilesGroup: three.Group;
    /**
     * @param id Unique identifier of the layer in the map.
     * @param options
     * @param coloringFragments
     * @param multiChannelColoringFragment
     */
    constructor(id: string, options: TileLayerOptions | null, coloringFragments?: ColoringFragmentBase[] | null, multiChannelColoringFragment?: MultiChannelGradientColoringFragment | null);
    /**
     * TODO: Add description
     */
    protected init(options: TileLayerOptions, coloringFragments?: ColoringFragmentBase[] | null, multiChannelColoringFragment?: MultiChannelGradientColoringFragment | null): void;
    /**
     * @description Event handler - callback when the window is resized.
     */
    protected onResize(): void;
    /**
     * @description Event handler - callback when the map is moved.
     */
    protected onMove(): void;
    /**
     * @description Event handler - called when the map movement ends.
     */
    protected onMoveEnd(): void;
    /**
     * @description Event handler - called when projection is changed
     */
    onProjectionChanged(event: MapProjectionEvent): void;
    /**
     * Remove the current tiles of the tile grid from the scene and reinstanciate them all
     * (three.Mesh) based onthe arguments, then add them to the scene again.
     * Note: The tils positions are not updated yet, this is performed by `.updateSlippyTile()`
     * @param width
     * @param height
     */
    private updateSlippyTileGrid;
    /**
     * TODO: Add description
     */
    private validateSource;
    /**
     * Adds another frame to the animation.
     * @param time Time of the data in this frame. Should be unique.
     * @param url URL to the tiles. Expected to have `{zxy}` placeholder to be dynamically replaced with `z/x/y` coordinates.
     */
    addSource(time: number, url: string, loadedCallback?: ((tile: Tile, url?: string, error?: ErrorEvent | null) => void) | null): void;
    /**
     * Removes frame
     */
    removeSource(time: number): void;
    /**
     * Get the Extent as defined in OL
     * @param scale
     * @returns
     */
    getVisibleExtent(scale?: number): Extent | null;
    /**
     * Get the list of all the tiles wanted for this extent and from the min zoom to the max zoom.
     * This is used to prevent updating tiles that are not in this list in `.updateSlippyTile()`
     * @param currentZ
     * @returns {TileList}
     */
    getWantedTiles(currentZ: number, minZoom: number, maxZoom: number): TileList;
    /**
     * Changes the global opacity of the layer.
     * Default is `1`
     *
     * @param opacity Opacity 0-1.
     */
    setOpacity(opacity: number): void;
    /**
     * Method from CustomLayerInterface, called when the layer is added to the map
     * @param map
     * @param gl
     */
    onAdd(map: MapSDK, gl: WebGLRenderingContext | WebGL2RenderingContext): void;
    /**
     * Method which should be override by the child class
     * for additional logic which has to be done:
     * - on adding the layer to the map
     * - on mouseEnd event
     */
    protected refresh(): void;
    /**
     * The method is called when the layer is removed from the map
     * `CustomLayerInterface` method
     */
    onRemove(_map: MapSDK, _gl: WebGLRenderingContext | WebGL2RenderingContext): void;
    /**
     * Remove some data allocated (not of the tiles)
     */
    protected disposeObjects(): void;
    /**
     * Get the TilePlacement from a zxy
     * @param source
     * @param load
     * @param z
     * @param x
     * @param y
     * @param originalTileCoordinates
     * @returns
     */
    private getTilePlacement;
    /**
     * WARNING: Globe projection only
     *
     * Update the tiles textures
     * TODO: Make mercator mode also use this method instead of `updateSlippyTiles`
     */
    private updateTilesMaterials;
    /**
     * WARNING: Mercator projection only
     *
     * Update the tile's mesh position and size, as well each tile material uniforms (time, texture, etc.)
     *
     * @returns {void}
     */
    protected updateSlippyTiles(): void;
    /**
     * TODO: Add description
     */
    protected getTilesPair(frameA: TimeFrame<TileTextureSource>, frameB: TimeFrame<TileTextureSource>, tileId: string): {
        tileA: TilePlacement;
        tileB: TilePlacement;
    } | null;
    /**
     * `CustomLayerInterface` method
     * This is used to apply the map matrix to the local camera
     */
    prerender(_gl: WebGLRenderingContext | WebGL2RenderingContext, options: CustomRenderMethodInput): void;
    /**
     * The reason for this method is to allow child classes to do some work during the prerender phase
     */
    protected prerenderInternal(): void;
    /**
     * `CustomLayerInterface` method
     * It is used to render the local tiles into the MapTiler SDK context
     */
    render(_gl: WebGLRenderingContext | WebGL2RenderingContext, _options: CustomRenderMethodInput): void;
    /**
     * The reason for this method is to allow child classes to do some work during the render phase
     * (after renderer state reset and before the actual rendering)
     */
    protected renderInternal(): void;
    /**
     * Get layer image decoded value (decoded means on the real world interval such as provided [decode.min, decode.max])
     * @param lng
     * @param lat
     * @param source
     * @returns
     */
    private pickFrame;
    /**
     * TODO: Add description
     */
    private pickFrameBilinear;
    /**
     * Picks the best currently available values at the position.
     *
     * The values are read from the already loaded tiles at the current time.
     *
     * Return the interpolated array of decoded values
     * of the same length as the number of specified coloring fragments.
     *
     * If the coloring fragments uses more channels (e.g. "rg"),
     * the corresponding value is an array of `[r value, g value, sqrt(r^2 + g^2)]`.
     *
     * @param lng
     * @param lat
     * @returns Array of decoded interpolated values. In case of using a multi-channel coloring fragment, the returned value is an array where the first value is the value and the second is the category
     */
    pick(lng: number, lat: number, options?: {
        /**
         * Enable bilinear interpolation if `true`, otherwise, the picking will be based on the nearest neighbor (NN) pixel.
         * NN has less impact on performance because it requires less texture reading, so it is generaly faster. Bilinear is more precise
         * and will retrieve values that are closer to what is being displayed (since tiles are rendered using a native-GPU bilinear method)
         * Default: `false`
         */
        bilinear?: boolean;
        /**
         * If `true`, the picking will be perfomed on the highest resolution tile available. If `false`, the picking is done on the tile currently showing on the map.
         */
        highestRes?: boolean;
        /**
         * Will force the loading of the tile if it was not already cached.
         * Usually unnecesary when the picking is done from hovering the pointer on the map, unless the option `.highRes` is `true`.
         * Default: `false`.
         */
        load?: boolean;
    }): number[] | null;
    /**
     * The map is available only after the layer is attached to the map
     * The method simplifies the access to the map object
     */
    protected getMapOrThrow: () => MapSDK;
    /**
     * The renderer is available only after the layer is attached to the map
     * The method simplifies the access to the renderer object
     */
    protected getRendererOrThrow: () => three.WebGLRenderer;
    /**
     * The method simplifies the access to the triggerRepaint method
     */
    forceRepaint(): void;
    /**
     * Get the current mixed image as a ImageData, meaning with pixel data, width, height and number of channels
     * Used by: Weather Plus
     * @param options.zxy The tile ID
     * @param options.blurKernel Size of the bluring kernel
     * @param options.outputSize Size of the outpout image (-1 means same as input). Note that the bluring is applied on an image of this size.
     * @returns ImageData | null
     */
    computeCurrentMixedImage({ zxy, blurKernel, outputSize, channel, }: {
        zxy?: string;
        blurKernel?: number;
        outputSize?: number;
        channel?: string;
    }): ImageData | null;
    /**
     * Enables data interpolation between keyframes when true. Only shows keyframe data when false.
     * @param ti
     */
    setTimeInterpolation(ti: boolean): void;
    /**
     * Enable smoothing category color when true. Hard edge between categories when false.
     * This seeting applies only to TileLayers using MultiChannelGradientColoringFragment
     * as the other types of oloring fragment do not use categories.
     * @param cst
     */
    setCategorySmoothTransition(cst: boolean): void;
    /**
     * If `true`, enables the local smoothing
     * @param s
     */
    setLocalSmoothing(s: boolean): void;
    /**
     * Defines the size of the smoothing kernel
     * @param d
     */
    setMaxSmoothingDistance(d: number): void;
    /**
     * Defines by what factor the smoothing kernel size is reduced with increasing zoom level
     * @param f
     */
    setSmoothingDistanceDecayFactor(f: number): void;
    /**
     * Get whether or not the frames continues to rendered on a paused animation
     * @returns
     */
    getRepaintOnPausedAnimation(): boolean;
    /**
     * If `true`, even the paused animation is rendered up to 60 times
     * per seconds. If `false`, the rendering is paused when the animation is paused.
     * Pausing the animation has side effects:
     * - it lowers energy consumtion
     * - it prevents overheating
     * - it pauses time-independant annimation (arrows, particles)
     * @param r
     */
    setRepaintOnPausedAnimation(r: boolean): void;
    /**
     * Wrapping telemetry registration with protected method to allow registration of modules which extends this class
     */
    protected registerTelemetry(map: MapSDK): void;
}
export { TileLayer };
/**
 * TODO:
 * - Add explanation
 * - Export to separate file, somehow
 */
interface ImageData {
    /**
     * The pixel data
     */
    data: Uint8Array;
    /**
     * The number of channels of the image (example: if image is RGBA then channels is 4)
     */
    channels: number;
    /**
     * Width of the image
     */
    width: number;
    /**
     * Height of the image
     */
    height: number;
}
