import type TopFilter from "./TopFilter.js";
import type TimeExtent from "../../time/TimeExtent.js";
import type { JSONSupport, JSONSupportMixinProperties } from "../../core/JSONSupport.js";
import type { QueryMixin, QueryMixinProperties } from "./QueryMixin.js";
import type { ObjectId } from "../../views/types.js";
import type { TimeExtentProperties } from "../../time/TimeExtent.js";
import type { TopFilterProperties } from "./TopFilter.js";

export interface TopFeaturesQueryProperties extends JSONSupportMixinProperties, QueryMixinProperties, Partial<Pick<TopFeaturesQuery, "geometryPrecision" | "maxAllowableOffset" | "num" | "objectIds" | "orderByFields" | "outFields" | "returnGeometry" | "returnM" | "returnZ" | "start">> {
  /**
   * A time extent for a temporal query against [time-aware layers](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html#timeInfo).
   * For example, it can be used to discover all crimes that occurred during the
   * night shift from 10 PM to 6 AM on a particular date.
   *
   * @example
   * // query hurricanes that took place in 1992 and
   * // return a hurricane track with the highest wind speed in each category
   * const query = new TopFeaturesQuery({
   *   outFields: ["STAGE, WINDSPEED, PRESSURE"],
   *   topFilter: new TopFilter({
   *     topCount: 1,
   *     groupByFields: ["STAGE"],
   *     orderByFields: ["WINDSPEED DESC"]
   *   }),
   *   timeExtent: {
   *     start: new Date(1992, 0, 1),
   *     end: new Date(1992, 11, 31)
   *   }
   * });
   * featureLayer.queryTopFeatures(query)
   *   .then(function(response){
   *      // returns a hurricane with the highest wind speed
   *      // in each stage... the query will only run against
   *     // hurricanes  that happened in 1992
   *    });
   * @example
   * let layer = new FeatureLayer( ... );
   * let timeExtent = new TimeExtent({
   *   start: new Date(1992, 0, 1),
   *   end: new Date(1992, 11, 31)
   * });
   * let timeQuery = new Query({
   *   timeExtent: timeExtent
   * });
   * layerView.queryFeatures(timeQuery).then(function(featureSet) { ... });
   */
  timeExtent?: TimeExtentProperties | null;
  /**
   * The `topFilter` parameter is used to set the [TopFilter#groupByFields](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFilter.html#groupByFields), [TopFilter#orderByFields](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFilter.html#orderByFields),
   * and [TopFilter#topCount](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFilter.html#topCount) criteria used in generating the result.
   *
   * @example
   * // return top three most populous cities from each state
   * const query = new TopFeaturesQuery({
   *   topFilter: new TopFilter({
   *     topCount: 3,
   *     groupByFields: ["State"],
   *     orderByFields: ["Pop_total DESC"]
   *   })
   * });
   * layer.queryTopFeatures(query).then(function(featureSet) { ... });
   */
  topFilter?: TopFilterProperties;
}

/**
 * This class defines parameters for executing [top features queries](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html#queryTopFeatures)
 * from a [FeatureLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html). Once a TopFeaturesQuery object's properties are defined, it can then be passed
 * into executable functions on a server-side [FeatureLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html), which can return a
 * [FeatureSet](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-FeatureSet.html) containing features within a group. For example, you can use FeatureLayer's
 * [FeatureLayer#queryTopFeatures()](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html#queryTopFeatures) method to query
 * the most populous three counties in each state of the United States.
 *
 * This class has many of the same properties as [Query](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-Query.html) class. However, unlike the Query class,
 * this class does not support properties such as `outStatistics` and its related parameters or `returnDistinctValues`.
 *
 * ```js
 * // query the top three most populous counties from each state.
 * // Results will be ordered based the population of each county in descending order
 * // top query will run against all features available in the service
 * const query = new TopFeaturesQuery({
 *   outFields: ["State, Pop_total, County"],
 *   topFilter: new TopFilter({
 *     topCount: 3,
 *     groupByFields: ["State"],
 *     orderByFields: ["Pop_total DESC"]
 *   })
 * });
 * featureLayer.queryTopFeatures(query)
 *   .then(function(response){
 *      // returns a feature set with features containing the most populous
 *      // three counties in each state ordered by population.
 *      // The following attributes are returned as well: State, Pop_total, County
 *    });
 * ```
 *
 * There are three types of top features queries: attribute, spatial and temporal queries. You can query for features
 * in one of these categories or use elements of each in a single query. When running a top features query,
 * the [topFilter](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFeaturesQuery.html#topFilter) parameter must always be set.
 *
 * <span id="attribute"></span>
 * ## Attribute queries
 *
 * To query top features based on attribute values, specify a SQL where clause in the [where](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFeaturesQuery.html#where) property along with the [topFilter](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFeaturesQuery.html#topFilter)
 * property. Setting the [outFields](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFeaturesQuery.html#outFields) of the query will limit the attributes returned from the query. This can improve the speed of the query
 * if your app doesn't require all the attributes for each feature.
 *
 * For example, you can use [where](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFeaturesQuery.html#where) and [topFilter](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFeaturesQuery.html#topFilter) parameters to query the top three most populous cities in each country if the
 * population is over 1,000,000.
 *
 * ```js
 * const query = new TopFeaturesQuery({
 *   where: "Population >= 1000000",
 *   outFields: ["Country, Population, Name"],
 *   topFilter: new TopFilter({
 *     topCount: 3,
 *     groupByFields: ["Country"],
 *     orderByFields: [`Population DESC`]
 *   })
 * });
 * featureLayer.queryTopFeatures(query)
 *   .then(function(response){
 *      // returns a feature set with features containing the most populous three cities
 *      // in each country. The query will run only against cities where the population is
 *      // over one million.
 *    });
 * ```
 *
 * <span id="spatial"></span>
 * ## Spatial queries
 *
 * You can query top features by geometry/location. While [where](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFeaturesQuery.html#where) is not required in this
 * workflow, you can use `where` as part of the query to get more refined results. The [topFilter](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFeaturesQuery.html#topFilter) property
 * must be set in addition to [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFeaturesQuery.html#geometry) property.
 * To execute a spatial query, you must set the [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFeaturesQuery.html#geometry) parameter to a
 * [Geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Geometry.html) object and specify a valid [spatialRelationship](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFeaturesQuery.html#spatialRelationship).
 * You can optionally provide a query [distance](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFeaturesQuery.html#distance) and [units](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFeaturesQuery.html#units) to query features against a buffer
 * around the given geometry.
 *
 * For example, to query for the two tallest buildings in each zoning category within 10 miles of a mouse move, you would do the following:
 *
 * ```js
 * view.on("pointer-move", function(event){
 *   const query = new TopFeaturesQuery({
 *     outFields: ["Zoning, Floors, Year"],
 *     topFilter: new TopFilter({
 *       topCount: 2,
 *       groupByFields: ["Zoning"],
 *       orderByFields: ["Floors DESC"]
 *     }),
 *     geometry: view.toMap(event),
 *     spatialRelationship:  "intersects",
 *     units: "miles",
 *     distance: 10,
 *     returnGeometry: true
 *   });
 *   featureLayer.queryTopFeatures(query)
 *     .then(function(response){
 *        // returns two tallest buildings in zoning category within a given geometry
 *        // The following attributes are returned as well: Zoning, Floors, Year
 *      });
 * });
 * ```
 *
 * You could also use `where`, for example, to return the tallest buildings in a specific residential zoning districts within
 * the 10-mile buffer.
 *
 * <span id="temporal"></span>
 * ## Temporal queries
 *
 * You can query top features based on a given time range by specifying the [timeExtent](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFeaturesQuery.html#timeExtent) property. The temporal query will return
 * results only if the feature service is published with [FeatureLayer#timeInfo](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html#timeInfo) information. The temporal
 * query can also be combined with attribute and geometry queries.
 *
 * For example, you can use [timeExtent](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFeaturesQuery.html#timeExtent) and [topFilter](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFeaturesQuery.html#topFilter) parameters to query hurricane tracks with the highest wind speed,
 * grouped by the hurricane categories within a given time extent.
 *
 * ```js
 * // query hurricanes that took place in 1992 and
 * // return a hurricane track with the highest wind speed in each category
 * const query = new TopFeaturesQuery({
 *   outFields: ["STAGE, WINDSPEED, PRESSURE"],
 *   topFilter: new TopFilter({
 *     topCount: 1,
 *     groupByFields: ["STAGE"],
 *     orderByFields: ["WINDSPEED DESC"]
 *   }),
 *   timeExtent: {
 *     start: new Date(1992, 0, 1),
 *     end: new Date(1992, 11, 31)
 *   }
 * });
 * featureLayer.queryTopFeatures(query)
 *   .then(function(response){
 *      // returns a hurricane with the highest wind speed
 *      // in each stage... the query will only run against
 *     // hurricanes  that happened in 1992
 *    });
 * ```
 *
 * > [!WARNING]
 * >
 * > **Known Limitations**
 * > Currently, the `TopFeatureQuery` is only supported with server-side [FeatureLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html).
 *
 * @since 4.20
 * @see [TopFilter](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFilter.html)
 * @see [FeatureLayer#queryTopFeatures()](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html#queryTopFeatures)
 * @see [Query and filter guide](https://developers.arcgis.com/javascript/latest/query-filter/)
 * @see [Sample - Aggregate spatial statistics](https://developers.arcgis.com/javascript/latest/sample-code/featurelayer-query-aggregate/)
 */
export default class TopFeaturesQuery extends TopFeaturesQuerySuperclass {
  constructor(properties?: TopFeaturesQueryProperties);
  /** Specifies the number of decimal places for geometries returned by the query operation. */
  accessor geometryPrecision: number;
  /**
   * The maximum distance in units of [outSpatialReference](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFeaturesQuery.html#outSpatialReference) used for
   * generalizing geometries returned by the query operation. It limits how far any part of the
   * generalized geometry can be from the original geometry. If `outSpatialReference` is not defined,
   * the spatialReference of the data is used.
   */
  accessor maxAllowableOffset: number;
  /**
   * The number of features to retrieve. This option should be used in conjunction with the [start property](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFeaturesQuery.html#start). Use this to
   * implement paging (i.e. to retrieve "pages" of results when querying).
   *
   * If not provided, but an instance of Query has a `start` property, then the default value of `num` is 10.
   * If neither `num` nor `start` properties are provided, then the default value of `num` is equal to the
   * `maxRecordCount` of the service, which can be found at the REST endpoint of the FeatureLayer.
   */
  accessor num: number | null | undefined;
  /** An array of ObjectIDs to be used to query for features in a layer. */
  accessor objectIds: ObjectId[] | null | undefined;
  /**
   * One or more field names used to order the query results. Specify `ASC` (ascending) or `DESC`
   * (descending) after the field name to control the order. The default order is `ASC`.
   *
   * @see [FeatureLayer#capabilities](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html#capabilities)
   * @example query.orderByFields = ["STATE_NAME DESC"];
   */
  accessor orderByFields: string[] | null | undefined;
  /**
   * Attribute fields to include in the [FeatureSet](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-FeatureSet.html). Fields must exist in the service layer. You must list actual
   * field names rather than field aliases. You may, however, use field aliases when you display
   * the results of the query.
   *
   * When specifying the output fields, you should limit the fields to only those you expect to use in the
   * query or the results. The fewer fields you include, the smaller the payload size, and therefore the faster the response of the query.
   *
   * You can also specify SQL expressions as `outFields` to calculate new values server side for the query results. See the
   * example snippets below for an example of this.
   *
   * Each query must have access to the `Shape` and `ObjectId` fields for a layer. However, the list of outFields does
   * not need to include these two fields.
   *
   * > [!WARNING]
   * >
   * > **Known Limitations**
   * >
   * > If specifying outFields as expressions on a feature service-based [FeatureLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html), the service capabilities
   * > `advancedQueryCapabilities.supportsOutFieldSQLExpression` and `useStandardizedQueries` must both be true.
   *
   * @example
   * // query for field attributes
   * query.outFields = [ "NAME", "STATE_ABBR", "POP04" ];
   * @example
   * // query for data returned from an expressions and other fields as the following field names
   * // POP_CHANGE_2020, NAME, POP2020
   * // where POP_CHANGE_2020 represents the population change from 2010 - 2020
   * query.outFields = [ "( (POP2020 - POP2010) / POP2010 ) * 100 as POP_CHANGE_2020", "NAME", "POP2020" ]
   */
  accessor outFields: string[] | null | undefined;
  /**
   * If `true`, each feature in the returned [FeatureSet](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-FeatureSet.html) includes the geometry.
   *
   * @default false
   */
  accessor returnGeometry: boolean;
  /** If `true`, and [returnGeometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFeaturesQuery.html#returnGeometry) is `true`, then m-values are included in the geometry. */
  accessor returnM: boolean;
  /** If `true`, and [returnGeometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFeaturesQuery.html#returnGeometry) is `true`, then z-values are included in the geometry. */
  accessor returnZ: boolean;
  /**
   * The zero-based index indicating where to begin retrieving features. This property should be used in conjunction with [num](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFeaturesQuery.html#num).
   * Use this to implement paging and retrieve "pages" of results when querying. Features are sorted ascending by
   * object ID by default.
   */
  accessor start: number | null | undefined;
  /**
   * A time extent for a temporal query against [time-aware layers](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html#timeInfo).
   * For example, it can be used to discover all crimes that occurred during the
   * night shift from 10 PM to 6 AM on a particular date.
   *
   * @example
   * // query hurricanes that took place in 1992 and
   * // return a hurricane track with the highest wind speed in each category
   * const query = new TopFeaturesQuery({
   *   outFields: ["STAGE, WINDSPEED, PRESSURE"],
   *   topFilter: new TopFilter({
   *     topCount: 1,
   *     groupByFields: ["STAGE"],
   *     orderByFields: ["WINDSPEED DESC"]
   *   }),
   *   timeExtent: {
   *     start: new Date(1992, 0, 1),
   *     end: new Date(1992, 11, 31)
   *   }
   * });
   * featureLayer.queryTopFeatures(query)
   *   .then(function(response){
   *      // returns a hurricane with the highest wind speed
   *      // in each stage... the query will only run against
   *     // hurricanes  that happened in 1992
   *    });
   * @example
   * let layer = new FeatureLayer( ... );
   * let timeExtent = new TimeExtent({
   *   start: new Date(1992, 0, 1),
   *   end: new Date(1992, 11, 31)
   * });
   * let timeQuery = new Query({
   *   timeExtent: timeExtent
   * });
   * layerView.queryFeatures(timeQuery).then(function(featureSet) { ... });
   */
  get timeExtent(): TimeExtent | null | undefined;
  set timeExtent(value: TimeExtentProperties | null | undefined);
  /**
   * The `topFilter` parameter is used to set the [TopFilter#groupByFields](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFilter.html#groupByFields), [TopFilter#orderByFields](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFilter.html#orderByFields),
   * and [TopFilter#topCount](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-TopFilter.html#topCount) criteria used in generating the result.
   *
   * @example
   * // return top three most populous cities from each state
   * const query = new TopFeaturesQuery({
   *   topFilter: new TopFilter({
   *     topCount: 3,
   *     groupByFields: ["State"],
   *     orderByFields: ["Pop_total DESC"]
   *   })
   * });
   * layer.queryTopFeatures(query).then(function(featureSet) { ... });
   */
  get topFilter(): TopFilter;
  set topFilter(value: TopFilterProperties);
  /**
   * Creates a deep clone of TopFeaturesQuery object.
   *
   * @returns A new instance of a TopFeaturesQuery object equal to the object used to call `.clone()`.
   */
  clone(): TopFeaturesQuery;
}
declare const TopFeaturesQuerySuperclass: typeof JSONSupport & typeof QueryMixin