import type Collection from "../../core/Collection.js";
import type Extent from "../../geometry/Extent.js";
import type SpatialReference from "../../geometry/SpatialReference.js";
import type Sublayer from "../../layers/support/Sublayer.js";
import type TimeExtent from "../../time/TimeExtent.js";
import type { ReadonlyArrayOrCollection } from "../../core/Collection.js";
import type { JSONSupport } from "../../core/JSONSupport.js";
import type { GeometryUnion } from "../../geometry/types.js";
import type { MeshProperties } from "../../geometry/Mesh.js";
import type { PolylineProperties } from "../../geometry/Polyline.js";
import type { PolygonProperties } from "../../geometry/Polygon.js";
import type { PointProperties } from "../../geometry/Point.js";
import type { MultipointProperties } from "../../geometry/Multipoint.js";
import type { ExtentProperties } from "../../geometry/Extent.js";
import type { SpatialReferenceProperties } from "../../geometry/SpatialReference.js";
import type { TimeExtentProperties } from "../../time/TimeExtent.js";

export interface IdentifyParametersProperties extends Partial<Pick<IdentifyParameters, "dpi" | "gdbVersion" | "geometryPrecision" | "height" | "layerIds" | "layerOption" | "maxAllowableOffset" | "returnFieldName" | "returnGeometry" | "returnM" | "returnUnformattedValues" | "returnZ" | "tolerance" | "width">> {
  /**
   * The geometry used to select features during the Identify operation.
   * The type of the geometry is specified by [Geometry.type](https://developers.arcgis.com/javascript/latest/references/core/geometry/Geometry/#type).
   * The most common geometry used with Identify is a [Point](https://developers.arcgis.com/javascript/latest/references/core/geometry/Point/).
   */
  geometry?: ((ExtentProperties & { type: "extent" }) | (MultipointProperties & { type: "multipoint" }) | (PointProperties & { type: "point" }) | (PolygonProperties & { type: "polygon" }) | (PolylineProperties & { type: "polyline" }) | (MeshProperties & { type: "mesh" })) | null;
  /**
   * The historic moment to identify. This parameter applies only if the `supportsQueryWithHistoricMoment`
   * capability of the service being queried is `true`. This setting is provided in the layer resource.
   *
   * @since 4.29
   */
  historicMoment?: (Date | number | string) | null;
  /**
   * The Extent or bounding box of the current map view. The `mapExtent` property is assumed to be in the spatial
   * reference of the map unless [spatialReference](https://developers.arcgis.com/javascript/latest/references/core/rest/support/IdentifyParameters/#spatialReference) has been specified.
   *
   * The values for [mapExtent](https://developers.arcgis.com/javascript/latest/references/core/rest/support/IdentifyParameters/#mapExtent), [height](https://developers.arcgis.com/javascript/latest/references/core/rest/support/IdentifyParameters/#height), [width](https://developers.arcgis.com/javascript/latest/references/core/rest/support/IdentifyParameters/#width), and [dpi](https://developers.arcgis.com/javascript/latest/references/core/rest/support/IdentifyParameters/#dpi) are used
   * to determine the current map scale. Once the scale is known, the map service can exclude layers based
   * on their scale dependency settings. The map service is not performing a spatial intersection based on
   * the provided extent. These properties are also used to calculate the search distance on the map based
   * on the tolerance in screen pixels.
   */
  mapExtent?: ExtentProperties | null;
  /**
   * The spatial reference of the input and output geometries as well as of the [mapExtent](https://developers.arcgis.com/javascript/latest/references/core/rest/support/IdentifyParameters/#mapExtent).
   * If the spatial reference is not specified, the geometry and the extent are assumed to be in the
   * spatial reference of the view, and the output geometries will also be in the spatial reference of the view.
   */
  spatialReference?: SpatialReferenceProperties | null;
  /**
   * An [Collection](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/) of [Sublayer](https://developers.arcgis.com/javascript/latest/references/core/layers/support/Sublayer/)
   * objects used to change the layer ordering and/or rendering, or redefine the map.
   *
   * Usually this property is set with the layer's [MapImageLayer.sublayers](https://developers.arcgis.com/javascript/latest/references/core/layers/MapImageLayer/#sublayers).
   *
   * @since 4.22
   * @see [Identify - ArcGIS Server REST API](https://developers.arcgis.com/rest/services-reference/identify-map-service-.htm)
   * @example
   * const {
   *   extent: maxExtent,
   *   spatialReference,
   *   width,
   *   height,
   *   timeExtent,
   * } = view;
   *
   * const parameters = new IdentifyParameters({
   *   sublayers: layer.sublayers,
   *   layerOption: "popup",
   *   returnGeometry: true,
   *   geometry: maxExtent.center,
   *   tolerance: 5,
   *   height,
   *   mapExtent,
   *   spatialReference,
   *   timeExtent,
   *   width,
   * });
   *
   * identify(layer.url, parameters).then((response) => {
   *   // process the response
   * });
   */
  sublayers?: ReadonlyArrayOrCollection<Sublayer> | null;
  /**
   * Specify the time extent used by identify.
   *
   * @since 4.22
   */
  timeExtent?: TimeExtentProperties | null;
}

/**
 * Input parameters for the [identify](https://developers.arcgis.com/javascript/latest/references/core/rest/identify/).
 *
 * @since 4.20
 * @see [identify](https://developers.arcgis.com/javascript/latest/references/core/rest/identify/)
 * @see [IdentifyResult](https://developers.arcgis.com/javascript/latest/references/core/rest/support/IdentifyResult/)
 * @see [Identify - ArcGIS Server REST API](https://developers.arcgis.com/rest/services-reference/identify-map-service-.htm)
 */
export default class IdentifyParameters extends JSONSupport {
  constructor(properties?: IdentifyParametersProperties);
  /**
   * Resolution of the current map view in dots per inch.
   *
   * @default 96
   */
  accessor dpi: number;
  /** Specify the geodatabase version to search. */
  accessor gdbVersion: string | null | undefined;
  /**
   * The geometry used to select features during the Identify operation.
   * The type of the geometry is specified by [Geometry.type](https://developers.arcgis.com/javascript/latest/references/core/geometry/Geometry/#type).
   * The most common geometry used with Identify is a [Point](https://developers.arcgis.com/javascript/latest/references/core/geometry/Point/).
   */
  get geometry(): GeometryUnion | null | undefined;
  set geometry(value: ((ExtentProperties & { type: "extent" }) | (MultipointProperties & { type: "multipoint" }) | (PointProperties & { type: "point" }) | (PolygonProperties & { type: "polygon" }) | (PolylineProperties & { type: "polyline" }) | (MeshProperties & { type: "mesh" })) | null | undefined);
  /** Specify the number of decimal places for the geometries returned by the task. */
  accessor geometryPrecision: number | null | undefined;
  /**
   * Height of the [View](https://developers.arcgis.com/javascript/latest/references/core/views/View/) in pixels.
   *
   * @default 400
   */
  accessor height: number;
  /**
   * The historic moment to identify. This parameter applies only if the `supportsQueryWithHistoricMoment`
   * capability of the service being queried is `true`. This setting is provided in the layer resource.
   *
   * @since 4.29
   */
  get historicMoment(): Date | null | undefined;
  set historicMoment(value: (Date | number | string) | null | undefined);
  /**
   * The layers on which to perform the identify operation. The layers are specified
   * as a comma-separated list of layer IDs.
   */
  accessor layerIds: number[] | null | undefined;
  /**
   * Specifies which layers to use when using Identify.
   *
   * Possible values | Description
   * --------------- | -----------
   * top | Only the top-most visible layer on the service is identified.
   * visible | All visible layers on the service are identified.
   * all | All layers on the service are identified, even if they are not visible. If your service has many layers, a request using this option will not perform well. A visible layer means you can see it in the map at the current extent.  If a layer is turned off or not in range based on its scale dependency settings, it cannot be identified.
   * popup | All visible layers with a popupTemplate. `sublayers` is required for this option.
   *
   * @default "top"
   */
  accessor layerOption: "top" | "visible" | "all" | "popup";
  /**
   * The Extent or bounding box of the current map view. The `mapExtent` property is assumed to be in the spatial
   * reference of the map unless [spatialReference](https://developers.arcgis.com/javascript/latest/references/core/rest/support/IdentifyParameters/#spatialReference) has been specified.
   *
   * The values for [mapExtent](https://developers.arcgis.com/javascript/latest/references/core/rest/support/IdentifyParameters/#mapExtent), [height](https://developers.arcgis.com/javascript/latest/references/core/rest/support/IdentifyParameters/#height), [width](https://developers.arcgis.com/javascript/latest/references/core/rest/support/IdentifyParameters/#width), and [dpi](https://developers.arcgis.com/javascript/latest/references/core/rest/support/IdentifyParameters/#dpi) are used
   * to determine the current map scale. Once the scale is known, the map service can exclude layers based
   * on their scale dependency settings. The map service is not performing a spatial intersection based on
   * the provided extent. These properties are also used to calculate the search distance on the map based
   * on the tolerance in screen pixels.
   */
  get mapExtent(): Extent | null | undefined;
  set mapExtent(value: ExtentProperties | null | undefined);
  /**
   * The maximum allowable offset used for generalizing geometries returned by the identify operation.
   * The offset is in the units of the [spatialReference](https://developers.arcgis.com/javascript/latest/references/core/rest/support/IdentifyParameters/#spatialReference). If a
   * [spatialReference](https://developers.arcgis.com/javascript/latest/references/core/rest/support/IdentifyParameters/#spatialReference) is not defined the spatial reference of the view is used.
   */
  accessor maxAllowableOffset: number | null | undefined;
  /**
   * If `true`, field names will be returned instead of field aliases.
   * Requires ArcGIS Server service 10.5 or greater.
   *
   * @default true
   */
  accessor returnFieldName: boolean;
  /**
   * If `true`, the result set includes the geometry associated with each result.
   *
   * @default false
   */
  accessor returnGeometry: boolean;
  /**
   * When `true`, indicates that M values will be returned.
   *
   * @default false
   */
  accessor returnM: boolean;
  /**
   * If `true`, the values in the result will not be formatted i.e. numbers will returned as is and dates
   * will be returned as epoch values.
   * Requires ArcGIS Server service 10.5 or greater.
   *
   * @default true
   */
  accessor returnUnformattedValues: boolean;
  /**
   * When `true`, indicates that z-values will be returned.
   *
   * @default false
   */
  accessor returnZ: boolean;
  /**
   * The spatial reference of the input and output geometries as well as of the [mapExtent](https://developers.arcgis.com/javascript/latest/references/core/rest/support/IdentifyParameters/#mapExtent).
   * If the spatial reference is not specified, the geometry and the extent are assumed to be in the
   * spatial reference of the view, and the output geometries will also be in the spatial reference of the view.
   */
  get spatialReference(): SpatialReference | null | undefined;
  set spatialReference(value: SpatialReferenceProperties | null | undefined);
  /**
   * An [Collection](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/) of [Sublayer](https://developers.arcgis.com/javascript/latest/references/core/layers/support/Sublayer/)
   * objects used to change the layer ordering and/or rendering, or redefine the map.
   *
   * Usually this property is set with the layer's [MapImageLayer.sublayers](https://developers.arcgis.com/javascript/latest/references/core/layers/MapImageLayer/#sublayers).
   *
   * @since 4.22
   * @see [Identify - ArcGIS Server REST API](https://developers.arcgis.com/rest/services-reference/identify-map-service-.htm)
   * @example
   * const {
   *   extent: maxExtent,
   *   spatialReference,
   *   width,
   *   height,
   *   timeExtent,
   * } = view;
   *
   * const parameters = new IdentifyParameters({
   *   sublayers: layer.sublayers,
   *   layerOption: "popup",
   *   returnGeometry: true,
   *   geometry: maxExtent.center,
   *   tolerance: 5,
   *   height,
   *   mapExtent,
   *   spatialReference,
   *   timeExtent,
   *   width,
   * });
   *
   * identify(layer.url, parameters).then((response) => {
   *   // process the response
   * });
   */
  get sublayers(): Collection<Sublayer> | null | undefined;
  set sublayers(value: ReadonlyArrayOrCollection<Sublayer> | null | undefined);
  /**
   * Specify the time extent used by identify.
   *
   * @since 4.22
   */
  get timeExtent(): TimeExtent | null | undefined;
  set timeExtent(value: TimeExtentProperties | null | undefined);
  /** The distance in screen pixels from the specified geometry within which the identify should be performed. */
  accessor tolerance: number | null | undefined;
  /**
   * Width of the current map view in pixels.
   *
   * @default 400
   */
  accessor width: number;
}