import { Request, TerrainData, Credit, TerrainProvider, Rectangle, CesiumTerrainProvider, TilingScheme, TileAvailability } from 'cesium';

/** A range of tiles from `start` to `end` */
type TileRange = {
    /** Top Left tile coordinates */
    start: {
        x: number;
        y: number;
    };
    /** Bottom Right tile coordinates */
    end: {
        x: number;
        y: number;
    };
};

/**
 * @class
 * Represents a geographic area with a specific terrain provider.
 * `TerrainArea` pairs a provider with geographic bounds and level constraints.
 */
declare class TerrainArea {
    private _terrainProvider;
    private _rectangle;
    private _tileRanges;
    private _ready;
    private _credit;
    private _isCustom;
    /**
     * Creates a new instance of `TerrainArea`.
     * @param options Object describing initialization options
     */
    constructor(options: TerrainArea.ConstructorOptions);
    /**
     * Checks if the specified tile coordinates are within the bounds.
     * @param x The tile X coordinate.
     * @param y The tile Y coordinate.
     * @param level The tile level.
     * @returns `true` if the tile is within bounds, `false` otherwise.
     */
    contains(x: number, y: number, level: number): boolean;
    /**
     * Requests the geometry for a given tile. The result must include terrain data and
     * may optionally include a water mask and an indication of which child tiles are available.
     * @param x - The X coordinate of the tile for which to request geometry.
     * @param y - The Y coordinate of the tile for which to request geometry.
     * @param level - The level of the tile for which to request geometry.
     * @param [request] - The request object. Intended for internal use only.
     * @returns A promise for the requested geometry.  If this method
     *          returns undefined instead of a promise, it is an indication that too many requests are already
     *          pending and the request will be retried later.
     */
    requestTileGeometry(x: number, y: number, level: number, request?: Request): Promise<Awaited<TerrainData>> | undefined;
    /**
     * Determines whether data for a tile is available to be loaded.
     * @param x - The X coordinate of the tile for which to request geometry.
     * @param y - The Y coordinate of the tile for which to request geometry.
     * @param level - The level of the tile for which to request geometry.
     * @returns Undefined if not supported by the terrain provider, otherwise true or false.
     * @see {@link TerrainProvider.getTileDataAvailable} */
    getTileDataAvailable(x: number, y: number, level: number): boolean;
    /** Checks if this terrain provider is marked as a custom provider. */
    get isCustom(): boolean;
    /** Gets the credit associated with this terrain area. */
    get credit(): string | Credit;
    /** Gets the terrain provider for this terrain area. */
    get terrainProvider(): TerrainProvider;
    /** Gets available tile ranges with zoom levels set with this terrain area. */
    get tileRanges(): Map<number, TileRange>;
    /** Gets the rectangle representing this terrain area. */
    get rectangle(): Rectangle;
    /** Gets if this terrain area is ready. */
    get ready(): boolean;
}
/**
 * @namespace
 * Contains types and factory methods for creating `TerrainArea` instances.
 */
declare namespace TerrainArea {
    /** Initialization options for `TerrainArea` constructor. */
    interface ConstructorOptions {
        /** The terrain provider for this area or a URL to create one from. */
        terrainProvider: TerrainProvider;
        /**
         * Tile ranges by level when using tileRange type.
         * Keys are zoom levels, values define the range of tiles at that level.
         */
        tileRanges: Map<number, TileRange>;
        /**
         * Credit to associate with this terrain provider.
         * Used to identify custom terrain providers.
         * @default custom
         */
        credit?: string | Credit;
        /**
         * Whether this is a custom terrain provider.
         * @default true
         */
        isCustom?: boolean;
    }
    /**
     * Creates a `TerrainArea` from a URL and tile ranges.
     * @param url The URL to create the terrain provider from.
     * @param tileRanges Tile ranges by level.
     * @param options: Constructor options for CesiumTerrainProvider.
     * @returns A promise resolving to a new `TerrainArea`
     */
    function fromUrl(url: string, tileRanges: Map<number, TileRange>, options?: CesiumTerrainProvider.ConstructorOptions): Promise<Awaited<TerrainArea>>;
}

/**
 * @class
 * Provides terrain by delegating requests to different terrain providers
 * based on geographic regions and zoom levels. This allows combining
 * multiple terrain sources into a single seamless terrain.
 *
 * @example
 * ``` typescript
 * // Set up tile ranges
 * const tileRanges = new Map<number, TileRange>;
 * tileRanges.set(15, { start: { x: 55852, y: 9556 }, end: { x: 55871, y: 9575 } });
 * // Set up tile areas
 * const area = new TerrainArea({ terrainProvider: provider, tileRanges });
 *
 * const hybridTerrain = new HybridTerrainProvider({
 *   terrainAreas: [area],
 *   terrainProvider: new EllipsoidTerrainProvider(),
 * });
 *
 * viewer.terrainProvider = hybridTerrain;
 * ```
 */
declare class HybridTerrainProvider implements TerrainProvider {
    private _terrainAreas;
    private _terrainProvider;
    private _fallbackProvider;
    private _tilingScheme;
    private _ready;
    private _availability?;
    /**
     * Creates a new `HybridTerrainProvider` instance.
     * @param options {@link HybridTerrainProvider.ConstructorOptions}
     * @returns A new `HybridTerrainProvider` instance.
     */
    constructor(options: HybridTerrainProvider.ConstructorOptions);
    /**
     * Gets a value indicating whether or not the provider is ready for use,
     * or a promise that resolves when the provider becomes ready.
     */
    get ready(): boolean;
    /**
     * Gets the tiling scheme used by this provider.
     */
    get tilingScheme(): TilingScheme;
    /**
     * Gets an object that can be used to determine availability of terrain from this provider.
     */
    get availability(): TileAvailability | undefined;
    /**
     * Gets the list of terrain areas managed by this provider.
     */
    get terrainAreas(): readonly TerrainArea[];
    /**
     * Gets the default terrain provider.
     */
    get defaultProvider(): TerrainProvider;
    /**
     * Gets the fallback terrain provider.
     */
    get fallbackProvider(): TerrainProvider;
    /**
     * Gets the credit to display when this terrain provider is active.  Typically this is used to credit
     * the source of the terrain.
     */
    get credit(): any;
    /**
     * Gets an event that is raised when the terrain provider encounters an asynchronous error.  By subscribing
     * to the event, you will be notified of the error and can potentially recover from it.  Event listeners
     * are passed an instance of `TileProviderError`.
     */
    get errorEvent(): any;
    /**
     * Gets a value indicating whether or not the provider includes a water mask.  The water mask
     * indicates which areas of the globe are water rather than land, so they can be rendered
     * as a reflective surface with animated waves.
     */
    get hasWaterMask(): boolean;
    /** Gets a value indicating whether or not the requested tiles include vertex normals. */
    get hasVertexNormals(): boolean;
    /**
     * Makes sure we load availability data for a tile
     * @param x - The X coordinate of the tile for which to request geometry.
     * @param y - The Y coordinate of the tile for which to request geometry.
     * @param level - The level of the tile for which to request geometry.
     * @returns Undefined if nothing need to be loaded or a Promise that resolves when all required tiles are loaded
     */
    loadTileDataAvailability(x: number, y: number, level: number): Promise<void> | undefined;
    /**
     * Gets the maximum geometric error allowed in a tile at a given level.
     * @param level - The tile level for which to get the maximum geometric error.
     * @returns The maximum geometric error.
     */
    getLevelMaximumGeometricError(level: number): number;
    /**
     * Requests the terrain for a given tile coordinate.
     * @param x The X coordinate of the tile.
     * @param y The Y coordinate of the tile.
     * @param level The zoom level of the tile.
     * @param request The request.
     * @returns A promise for the requested terrain.
     */
    requestTileGeometry(x: number, y: number, level: number, request?: Request): Promise<Awaited<TerrainData>> | undefined;
    /**
     * Determines whether data for a tile is available to be loaded. Checks the specified terrain areas first.
     * @param x - The X coordinate of the tile for which to request geometry.
     * @param y - The Y coordinate of the tile for which to request geometry.
     * @param level - The level of the tile for which to request geometry.
     * @returns Undefined if not supported by the terrain provider, otherwise true or false.
     */
    getTileDataAvailable(x: number, y: number, level: number): boolean | undefined;
}
/**
 * @namespace
 * Contains types and factory methods for creating `HybridTerrainProvider` instance.
 */
declare namespace HybridTerrainProvider {
    /** Initialization options for `HybridTerrainProvider` constructor. */
    interface ConstructorOptions {
        /** An array of terrain areas to include in the hybrid terrain. */
        terrainAreas: TerrainArea[];
        /** Default provider to use outside of specified terrain areas.  */
        terrainProvider: TerrainProvider;
        /** Optional fallback provider when data is not available from default provider. @default EllipsoidTerrainProvider */
        fallbackProvider?: TerrainProvider;
    }
}

export { HybridTerrainProvider as H, TerrainArea as T, type TileRange as a };
