import type Extent from "../geometry/Extent.js";
import type Multipoint from "../geometry/Multipoint.js";
import type Point from "../geometry/Point.js";
import type Polyline from "../geometry/Polyline.js";
import type Layer from "./Layer.js";
import type ElevationSampler from "./support/ElevationSampler.js";
import type { MultiOriginJSONSupportMixin } from "../core/MultiOriginJSONSupport.js";
import type { AbortOptions } from "../core/promiseUtils.js";
import type { ArcGISCachedService, ArcGISCachedServiceProperties } from "./mixins/ArcGISCachedService.js";
import type { OperationalLayer, OperationalLayerProperties } from "./mixins/OperationalLayer.js";
import type { PortalLayer, PortalLayerProperties } from "./mixins/PortalLayer.js";
import type { ElevationQueryResult, ElevationQueryGeometry, ElevationQueryOptions, CreateElevationSamplerOptions, ElevationTileData } from "./support/types.js";
import type { LayerProperties } from "./Layer.js";

export interface ElevationLayerProperties extends LayerProperties, PortalLayerProperties, OperationalLayerProperties, ArcGISCachedServiceProperties, Partial<Pick<ElevationLayer, "sourceJSON" | "url">> {
  /**
   * The title of the layer used to identify it in places such as the [LayerList](https://developers.arcgis.com/javascript/latest/references/core/widgets/LayerList/) widget.
   *
   * When loading a layer by service url, the title is derived from the service name.
   * When the layer is loaded from a portal item, the title of the portal item will be used instead.
   * Finally, if a layer is loaded as part of a webmap or a webscene, then the title of the layer as stored in the webmap/webscene will be used.
   */
  title?: string | null;
}

export interface FetchTileOptions extends AbortOptions {
  /**
   * The value representing pixels
   *   in the tile that don't contain an elevation value.
   */
  noDataValue?: number;
}

/**
 * ElevationLayer is a tile layer used for rendering elevations in [SceneViews](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/).
 * A default [world elevation layer](https://www.arcgis.com/home/item.html?id=7029fb60158543ad845c7e1527af11e4)
 * can be added to the map by setting the [map's ground](https://developers.arcgis.com/javascript/latest/references/core/Map/#ground) property to `world-elevation`.
 *
 *
 * ![elev-default](https://developers.arcgis.com/javascript/latest/assets/references/core/ground/elev-default.png)
 *
 * Elevation layers are set in the [Ground.layers](https://developers.arcgis.com/javascript/latest/references/core/Ground/#layers) property of a
 * [map's ground](https://developers.arcgis.com/javascript/latest/references/core/Map/#ground). They should not be added to the
 * map's [operational layers](https://developers.arcgis.com/javascript/latest/references/core/Map/#layers).
 *
 * ```js
 * let elevLyr = new ElevationLayer({
 *   // Custom elevation service
 *   url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/Elevation/MtBaldy_Elevation/ImageServer"
 * });
 * // Add elevation layer to the map's ground.
 * map.ground.layers.add(elevLyr);
 * ```
 *
 * If the service is requested from a different domain, a [CORS enabled server](https://developers.arcgis.com/javascript/latest/cors/) or
 * [a proxy](https://developers.arcgis.com/javascript/latest/proxies/) is required.
 *
 * @since 4.0
 * @see [Sample - 3D Map with elevation services](https://developers.arcgis.com/javascript/latest/sample-code/scene-elevationlayer/)
 * @see [Sample - Query Elevation (points)](https://developers.arcgis.com/javascript/latest/sample-code/elevation-query-points/)
 * @see [ArcGIS Blog - Creating and Using Elevation Layers in ArcGIS Online & ArcGIS Pro](https://blogs.esri.com/esri/arcgis/2016/08/30/creating-and-using-elevation-layers-in-arcgis-online/)
 */
export default class ElevationLayer extends ElevationLayerSuperclass {
  constructor(properties?: ElevationLayerProperties);
  /**
   * The [image service's metadata JSON](https://developers.arcgis.com/rest/services-reference/image-service.htm)
   * exposed by the ArcGIS REST API. While most commonly used properties
   * are exposed on the ElevationLayer class directly, this property gives access to all information returned
   * by the elevation image service. This property is useful if working in an application built using an older version
   * of the API which requires access to elevation image service properties from a more recent version.
   *
   * @since 4.13
   */
  accessor sourceJSON: any;
  /**
   * The title of the layer used to identify it in places such as the [LayerList](https://developers.arcgis.com/javascript/latest/references/core/widgets/LayerList/) widget.
   *
   * When loading a layer by service url, the title is derived from the service name.
   * When the layer is loaded from a portal item, the title of the portal item will be used instead.
   * Finally, if a layer is loaded as part of a webmap or a webscene, then the title of the layer as stored in the webmap/webscene will be used.
   */
  accessor title: string | null | undefined;
  /** The layer type provides a convenient way to check the type of the layer without the need to import specific layer modules. */
  get type(): "elevation";
  /**
   * URL pointing to the Elevation layer resource on an ArcGIS Image Server.
   *
   * @example url: "http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer"
   */
  accessor url: string | null | undefined;
  /**
   * The version of ArcGIS Server in which the elevation service (image service) is published.
   *
   * @example
   * // Prints the version number to the console - e.g. 10.91, 11.2, 11.3.
   * console.log(layer.version);
   */
  get version(): number;
  /**
   * Creates an elevation sampler for the given [Extent](https://developers.arcgis.com/javascript/latest/references/core/geometry/Extent/) by querying the service layer
   * for elevation data and caching it so values may be sampled quickly afterwards. The resolution
   * of the cached data can be set using the `demResolution` option. In many cases, `auto`
   * demResolution can be used to get high quality elevation samples without the
   * need to know exactly where the data in the service is located.
   * This is particularly useful for services which combine
   * elevation data from many sources (such as the world elevation service).
   * If more control, or higher quality samples are required, use either
   * `finest-contiguous` or a fixed `{number}` resolution.
   *
   * @param extent - The extent for which to create the sampler.
   * @param options - Additional query options.
   * @returns An elevation sampler.
   * @since 4.7
   */
  createElevationSampler(extent: Extent, options?: CreateElevationSamplerOptions): Promise<ElevationSampler>;
  /**
   * Requests a tile from the service and decodes the data into a linear
   * array of elevation values.
   *
   * The returned promise resolves with a plain object describing the obtained
   * elevation data for the tile. The object has the following properties:
   *
   * Property  | Type         | Description
   * ----------|--------------|------------
   * values    | Float32Array | The elevation values contained in the tile.
   * width     | number       | The number of elevation values in one row of the tile.
   * height    | number       | The number of elevation values in one column of the tile.
   *
   * @param level - the tile level.
   * @param row - the tile row.
   * @param column - the tile column.
   * @param options - Optional settings for the tile request.
   * @returns a Promise which resolves with elevation tile data.
   */
  fetchTile(level: number, row: number, column: number, options?: FetchTileOptions): Promise<ElevationTileData>;
  /**
   * This method returns a URL to a tile for a given level, row and column.
   *
   * @param level - The requested tile's level.
   * @param row - The requested tile's row.
   * @param col - The requested tile's column.
   * @returns Returns the tile URL.
   */
  getTileUrl(level: number, row: number, col: number): string;
  /**
   * @param geometry
   * @param options
   */
  queryElevation(geometry: Point, options?: ElevationQueryOptions): Promise<ElevationQueryResult<Point>>;
  /**
   * @param geometry
   * @param options
   */
  queryElevation(geometry: Multipoint, options?: ElevationQueryOptions): Promise<ElevationQueryResult<Multipoint>>;
  /**
   * @param geometry
   * @param options
   */
  queryElevation(geometry: Polyline, options?: ElevationQueryOptions): Promise<ElevationQueryResult<Polyline>>;
  /**
   * Queries the service layer for elevation values for the given geometry. The
   * returned result contains a copy of the geometry with z-values sampled from
   * elevation data from the service. The resolution from which the elevation is
   * queried can be set using the `demResolution` option. In many cases, `auto`
   * demResolution can be used to get high quality elevation samples without the
   * need to know exactly where the data in the service is located.
   * This is particularly useful for services which combine
   * elevation data from many sources (such as the world elevation service).
   * If more control, or higher quality samples are required, use either
   * `finest-contiguous` or a fixed `{number}` resolution.
   *
   * @param geometry - The geometry to use for sampling elevation data.
   * @param options - Additional query options.
   * @returns Resolves to an object with the sampled geometry, resolution information, and no data value.
   * @example
   * const [ElevationLayer, Multipoint] = await $arcgis.import([
   *   "@arcgis/core/layers/ElevationLayer.js",
   *   "@arcgis/core/geometry/Multipoint.js"
   * ]);
   * const url =
   *    "//elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer/";
   * const layer = new ElevationLayer(url);
   *
   * // Various points across a ridge of the mount everest
   * const points = [
   *   [86.9252, 27.9883],
   *   [86.9265, 27.9894],
   *   [86.9292, 27.9923],
   *   [86.9324, 27.996],
   *   [86.9359, 27.9992]
   * ];
   *
   * // Uses "auto" resolution by default
   * layer
   *   .queryElevation(new Multipoint({ points }), {
   *     returnSampleInfo: true
   *   })
   *
   *   // Successfully sampled all points
   *   .then(function (result) {
   *     // Print result of each sampled point to the console
   *     result.geometry.points.forEach(function (point, index) {
   *       const elevation = Math.round(point[2]);
   *       const resolution = result.sampleInfo[index].demResolution;
   *
   *       const coordinateText = "(" + point[0] + ", " + point[1] + ")";
   *       const resolutionText = Math.round(resolution) + " meter resolution";
   *
   *       console.log("Sampled " + coordinateText + ": " + elevation + " at " + resolutionText);
   *     });
   *   })
   *
   *   // Failed to sample (e.g. service unavailable)
   *   .catch(function (error) {
   *     console.error("Failed to query elevation:", error);
   *   });
   */
  queryElevation(geometry: ElevationQueryGeometry, options?: ElevationQueryOptions): Promise<ElevationQueryResult<ElevationQueryGeometry>>;
}
declare const ElevationLayerSuperclass: typeof Layer & typeof MultiOriginJSONSupportMixin & typeof PortalLayer & typeof OperationalLayer & typeof ArcGISCachedService