import type Query from "../../rest/support/Query.js";
import type { JSONSupport } from "../../core/JSONSupport.js";
import type { QueryProperties } from "../../rest/support/Query.js";

export interface FeatureFilterProperties extends Partial<Pick<FeatureFilter, "objectIds">> {
  /**
   * Specifies a search distance from a given [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry) in a spatial filter.
   * The [units property](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#units) indicates the unit of measurement. In essence, setting this property
   * creates a buffer at the specified size around the input [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry). The filter will use that
   * buffer to display features in the layer or layer view that adhere to the to the indicated [spatial relationship](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#spatialRelationship).
   */
  distance?: QueryProperties["distance"];
  /**
   * The geometry to apply to the spatial filter. The spatial relationship as specified by [spatialRelationship](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#spatialRelationship)
   * will indicate how the geometry should be used to filter features.
   *
   * > [!WARNING]
   * >
   * > **Known Limitations**
   * >
   * > [Mesh](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Mesh.html) geometry types are currently not supported.
   */
  geometry?: QueryProperties["geometry"];
  /**
   * For spatial filters, this parameter defines the spatial relationship to filter features in the layer view
   * against the filter [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry). The spatial relationships discover how features are spatially related to each other.
   * For example, you may want to know if a polygon representing a county completely contains points representing settlements.
   *
   * The spatial relationship is determined by whether the boundaries or interiors of a geometry intersect.
   * * Boundary — The endpoints of all linear parts for line features, or the linear outline of a polygon. Only lines and polygons have boundaries.
   * * Interior — Points are entirely interior and have no boundary. For lines and polygons, the interior is any part of the geometry that is not part of the boundary.
   *
   * The possible values for this parameter are described below and the images highlight the geometries returned for the specified spatial
   * relationship for given geometries.
   *
   *  The `intersects` spatial relationship returns features in the layer view that intersect the filter [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry).
   *
   * > [!WARNING]
   * >
   * > **Known Limitations**
   * >
   * > The filter of [SceneLayerView](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-layers-SceneLayerView.html) with 3D object scene layers only supports the
   * > spatial relationships `contains`, `intersects` and `disjoint`.
   *
   *
   * ![intersects](https://developers.arcgis.com/javascript/latest/assets/img/apiref/layers/spatialRelationships/intersects.png)
   *
   * The `contains` spatial relationship returns features in the layer view that are completely contained by the filter [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry).
   *
   * ![contains](https://developers.arcgis.com/javascript/latest/assets/img/apiref/layers/spatialRelationships/contains.png)
   *
   * The `crosses` spatial relationship returns features in the layer view when the interior of a filter [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry) comes into contact with
   * the interior or boundary of features in the layer view. In other words, the geometries share some interior area, but not all interior area.
   *
   * ![crosses](https://developers.arcgis.com/javascript/latest/assets/img/apiref/layers/spatialRelationships/crosses.png)
   *
   * The `envelope-intersects` spatial relationship returns features in the layer view that intersect the envelope (or extent)
   * of the filter [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry).
   *
   * ![envelope-intersects](https://developers.arcgis.com/javascript/latest/assets/img/apiref/layers/spatialRelationships/envelope-intersects.png)
   *
   * The `overlaps` spatial relationship returns features in the layer view that overlap the filter [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry).
   * Only features of the same geometry can be compared.
   *
   * ![overlaps](https://developers.arcgis.com/javascript/latest/assets/img/apiref/layers/spatialRelationships/overlap.png)
   *
   * The `touches` spatial relationship returns features in the layer view that touch the filter [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry).
   * The boundaries of the geometries intersect, but not their interiors.
   *
   * ![touches](https://developers.arcgis.com/javascript/latest/assets/img/apiref/layers/spatialRelationships/touches.png)
   *
   * The `within` spatial relationship returns features in the layer view that completely contain the filter [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry).
   * In other words, the filter geometry is completely `within` the features in the layer view. It is opposite of
   * `contains`.
   *
   * ![within](https://developers.arcgis.com/javascript/latest/assets/img/apiref/layers/spatialRelationships/within.png)
   *
   * The `disjoint` spatial relationship returns features in the layer view that do not intersect the filter [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry) in anyway.
   * Opposite of `intersects`.
   *
   * ![disjoint](https://developers.arcgis.com/javascript/latest/assets/img/apiref/layers/spatialRelationships/disjoint.png)
   *
   * @default "intersects"
   * @see [Sample - Filter features by geometry](https://developers.arcgis.com/javascript/latest/sample-code/featureeffect-geometry/)
   * @example
   * // display features that are completely within state
   * let filter = new FeatureFilter({
   *   spatialRelationship: "contains",
   *   geometry: statePolygon
   * });
   */
  spatialRelationship?: QueryProperties["spatialRelationship"];
  /**
   * A range of time with start and end date. Only the features that fall within this time extent will be displayed.
   * The Date field to be used for `timeExtent` should be added to [FeatureLayer.outFields](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html#outFields)
   * list when the layer is initialized. This ensures the best user experience when switching or updating fields for time filters.
   *
   * > [!WARNING]
   * >
   * > **Notes**
   * >
   * > The temporal filter can only be applied to a layer view if its layer has [TimeInfo](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-TimeInfo.html).
   */
  timeExtent?: QueryProperties["timeExtent"];
  /**
   * The unit for calculating the buffer distance when [distance](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#distance) is specified in a spatial filter.
   * If `units` is not specified, the unit is derived from the filter [geometry's](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry) spatial reference.
   */
  units?: QueryProperties["units"] | null;
  /**
   * A where clause for the feature filter. Any legal SQL92 where clause operating on the fields in the layer is allowed.
   * Be sure to have the correct sequence of single and double quotes when writing the where clause in JavaScript.
   *
   * For apps where users can interactively change fields used for attribute filter, we suggest you include all possible fields
   * in the [FeatureLayer.outFields](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html#outFields) of the layer. This ensures the best user experience when
   * switching or updating fields for attribute filters.
   *
   * > [!WARNING]
   * >
   * > **Notes**
   * >
   * > Attribute values are case sensitive.
   *
   * @see [Sample - Filter features by attributes](https://developers.arcgis.com/javascript/latest/sample-code/featurefilter-attributes/)
   * @example filter.where = "NAME = '" + stateName + "'";
   * @example filter.where = "POP04 > " + population;
   */
  where?: QueryProperties["where"];
}

/**
 * This class defines parameters for setting a client-side filter on a [FeatureLayer.featureEffect](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html#featureEffect) or [layer view](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-layers-FeatureLayerView.html#filter).
 * Once a FeatureFilter's properties are defined, it can be used to set the
 * [FeatureLayerView.filter](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-layers-FeatureLayerView.html#filter) property of the layer view or [FeatureEffect.filter](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureEffect.html#filter).
 *
 * You can set filters by [attributes](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#where), [time](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#timeExtent), [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry) and geometry with [distance](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#distance).
 * Only the features that meet the requirements  specified in the filter will be displayed. Filters only affect feature visibility.
 * They do not return geometry or attribute information associated with the filtered features.
 * The [FeatureLayerView.queryFeatures()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-layers-FeatureLayerView.html#queryFeatures) method must be called to access additional information.
 *
 * FeatureFilter runs against features that are available for drawing on the client-side. Client-side features are optimized
 * for performance hence, feature filter results are not always accurate. Use the layer's `queryFeatures()` method or the `definitionExpression`
 * property if you need to run your filter against all features that are available in the layer.
 * See [querying and filtering guide doc](https://developers.arcgis.com/javascript/latest/query-filter/#filtering) for more information.
 *
 * ```js
 * // display rain gauges where their water percent is over 30%
 * // and if the gauges are completely contained by the 10-mile
 * // buffer around the filter geometry
 * featureLayerView.filter = new FeatureFilter({
 *   where: "percentile >= 30",
 *   geometry: filterPolygon,
 *   spatialRelationship: "contains",
 *   distance: 10,
 *   units: "miles"
 * });
 * ```
 * ![screen-size-perspective](https://developers.arcgis.com/javascript/latest/assets/img/apiref/layers/filter-attributes.gif)
 *
 * @since 4.22
 * @see [FeatureLayerView.filter](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-layers-FeatureLayerView.html#filter)
 * @see [Sample - Filter features by attributes](https://developers.arcgis.com/javascript/latest/sample-code/featurefilter-attributes/)
 * @see [Sample - Filter features by geometry](https://developers.arcgis.com/javascript/latest/sample-code/layers-scenelayer-feature-masking/)
 * @see [Querying and filtering guide doc](https://developers.arcgis.com/javascript/latest/query-filter/#filtering)
 */
export default class FeatureFilter extends JSONSupport {
  /**
   * @example
   * // Typical usage
   * const filter = new FeatureFilter({
   *   where: "magnitude >= 3"
   * });
   * layerView.filter = filter;
   */
  constructor(properties?: FeatureFilterProperties);
  /**
   * Specifies a search distance from a given [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry) in a spatial filter.
   * The [units property](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#units) indicates the unit of measurement. In essence, setting this property
   * creates a buffer at the specified size around the input [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry). The filter will use that
   * buffer to display features in the layer or layer view that adhere to the to the indicated [spatial relationship](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#spatialRelationship).
   */
  get distance(): Query["distance"];
  set distance(value: QueryProperties["distance"]);
  /**
   * The geometry to apply to the spatial filter. The spatial relationship as specified by [spatialRelationship](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#spatialRelationship)
   * will indicate how the geometry should be used to filter features.
   *
   * > [!WARNING]
   * >
   * > **Known Limitations**
   * >
   * > [Mesh](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Mesh.html) geometry types are currently not supported.
   */
  get geometry(): Query["geometry"];
  set geometry(value: QueryProperties["geometry"]);
  /**
   * An array of objectIds of the features to be filtered. If the array of object IDs is empty, all features will be displayed.
   * To hide all features when the array is empty, set the filter's [where](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#where) property to `1=0` as shown below.
   *
   * @example
   * // hide all features when objectIds array is empty
   * const oidsArray = layerView.queryObjectIds(query);
   * layerView.filter = oidsArray.length > 0 ?  { objectIds: oidsArray } : { where: "1=0" };
   */
  accessor objectIds: number[] | null | undefined;
  /**
   * For spatial filters, this parameter defines the spatial relationship to filter features in the layer view
   * against the filter [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry). The spatial relationships discover how features are spatially related to each other.
   * For example, you may want to know if a polygon representing a county completely contains points representing settlements.
   *
   * The spatial relationship is determined by whether the boundaries or interiors of a geometry intersect.
   * * Boundary — The endpoints of all linear parts for line features, or the linear outline of a polygon. Only lines and polygons have boundaries.
   * * Interior — Points are entirely interior and have no boundary. For lines and polygons, the interior is any part of the geometry that is not part of the boundary.
   *
   * The possible values for this parameter are described below and the images highlight the geometries returned for the specified spatial
   * relationship for given geometries.
   *
   *  The `intersects` spatial relationship returns features in the layer view that intersect the filter [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry).
   *
   * > [!WARNING]
   * >
   * > **Known Limitations**
   * >
   * > The filter of [SceneLayerView](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-layers-SceneLayerView.html) with 3D object scene layers only supports the
   * > spatial relationships `contains`, `intersects` and `disjoint`.
   *
   *
   * ![intersects](https://developers.arcgis.com/javascript/latest/assets/img/apiref/layers/spatialRelationships/intersects.png)
   *
   * The `contains` spatial relationship returns features in the layer view that are completely contained by the filter [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry).
   *
   * ![contains](https://developers.arcgis.com/javascript/latest/assets/img/apiref/layers/spatialRelationships/contains.png)
   *
   * The `crosses` spatial relationship returns features in the layer view when the interior of a filter [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry) comes into contact with
   * the interior or boundary of features in the layer view. In other words, the geometries share some interior area, but not all interior area.
   *
   * ![crosses](https://developers.arcgis.com/javascript/latest/assets/img/apiref/layers/spatialRelationships/crosses.png)
   *
   * The `envelope-intersects` spatial relationship returns features in the layer view that intersect the envelope (or extent)
   * of the filter [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry).
   *
   * ![envelope-intersects](https://developers.arcgis.com/javascript/latest/assets/img/apiref/layers/spatialRelationships/envelope-intersects.png)
   *
   * The `overlaps` spatial relationship returns features in the layer view that overlap the filter [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry).
   * Only features of the same geometry can be compared.
   *
   * ![overlaps](https://developers.arcgis.com/javascript/latest/assets/img/apiref/layers/spatialRelationships/overlap.png)
   *
   * The `touches` spatial relationship returns features in the layer view that touch the filter [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry).
   * The boundaries of the geometries intersect, but not their interiors.
   *
   * ![touches](https://developers.arcgis.com/javascript/latest/assets/img/apiref/layers/spatialRelationships/touches.png)
   *
   * The `within` spatial relationship returns features in the layer view that completely contain the filter [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry).
   * In other words, the filter geometry is completely `within` the features in the layer view. It is opposite of
   * `contains`.
   *
   * ![within](https://developers.arcgis.com/javascript/latest/assets/img/apiref/layers/spatialRelationships/within.png)
   *
   * The `disjoint` spatial relationship returns features in the layer view that do not intersect the filter [geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry) in anyway.
   * Opposite of `intersects`.
   *
   * ![disjoint](https://developers.arcgis.com/javascript/latest/assets/img/apiref/layers/spatialRelationships/disjoint.png)
   *
   * @default "intersects"
   * @see [Sample - Filter features by geometry](https://developers.arcgis.com/javascript/latest/sample-code/featureeffect-geometry/)
   * @example
   * // display features that are completely within state
   * let filter = new FeatureFilter({
   *   spatialRelationship: "contains",
   *   geometry: statePolygon
   * });
   */
  get spatialRelationship(): Query["spatialRelationship"];
  set spatialRelationship(value: QueryProperties["spatialRelationship"]);
  /**
   * A range of time with start and end date. Only the features that fall within this time extent will be displayed.
   * The Date field to be used for `timeExtent` should be added to [FeatureLayer.outFields](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html#outFields)
   * list when the layer is initialized. This ensures the best user experience when switching or updating fields for time filters.
   *
   * > [!WARNING]
   * >
   * > **Notes**
   * >
   * > The temporal filter can only be applied to a layer view if its layer has [TimeInfo](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-TimeInfo.html).
   */
  get timeExtent(): Query["timeExtent"];
  set timeExtent(value: QueryProperties["timeExtent"]);
  /**
   * The unit for calculating the buffer distance when [distance](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#distance) is specified in a spatial filter.
   * If `units` is not specified, the unit is derived from the filter [geometry's](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureFilter.html#geometry) spatial reference.
   */
  get units(): Query["units"] | null | undefined;
  set units(value: QueryProperties["units"] | null | undefined);
  /**
   * A where clause for the feature filter. Any legal SQL92 where clause operating on the fields in the layer is allowed.
   * Be sure to have the correct sequence of single and double quotes when writing the where clause in JavaScript.
   *
   * For apps where users can interactively change fields used for attribute filter, we suggest you include all possible fields
   * in the [FeatureLayer.outFields](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html#outFields) of the layer. This ensures the best user experience when
   * switching or updating fields for attribute filters.
   *
   * > [!WARNING]
   * >
   * > **Notes**
   * >
   * > Attribute values are case sensitive.
   *
   * @see [Sample - Filter features by attributes](https://developers.arcgis.com/javascript/latest/sample-code/featurefilter-attributes/)
   * @example filter.where = "NAME = '" + stateName + "'";
   * @example filter.where = "POP04 > " + population;
   */
  get where(): Query["where"];
  set where(value: QueryProperties["where"]);
  /**
   * Creates a deep clone of the FeatureFilter object.
   *
   * @returns A new instance of a FeatureFilter object equal to the object used to call `.clone()`.
   */
  clone(): FeatureFilter;
  /**
   * Creates [Query](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-Query.html) parameters that can be used to fetch features that
   * satisfy the layer's current filters and definitions.
   *
   * @returns The query object representing the layer's filters
   * and other definitions.
   * @example
   * // Get a query object from the filter's current configuration
   * const queryParams = layerView.filter.createQuery();
   * // set a geometry for querying features by the view's extent
   * queryParams.geometry = view.extent;
   *
   * // query the layer with the modified params object
   * layerView.queryFeatures(queryParams)
   *   .then(function(results){
   *     // prints the array of result graphics to the console
   *     console.log(results.features);
   *   });
   */
  createQuery(): Query;
}