/**
 * This object contains a helper method for generating a [HeatmapRenderer](https://developers.arcgis.com/javascript/latest/api-reference/esri-renderers-HeatmapRenderer.html) for a point [Layer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-Layer.html).
 *
 * It is important to note that the input layer must have features available in the input view
 * for the [createRenderer()](https://developers.arcgis.com/javascript/latest/api-reference/esri-smartMapping-renderers-heatmap.html#createRenderer) method to generate a meaningful heatmap.
 * Otherwise, the method will fail.
 *
 * > [!WARNING]
 * >
 * > **Known Limitation**
 * >
 * > Only layers with point geometries are supported.
 *
 * @since 4.11
 * @see [Styles and data visualization](https://developers.arcgis.com/javascript/latest/visualization/)
 * @see [Sample - Explore point data with a heatmap](https://developers.arcgis.com/javascript/latest/sample-code/visualization-heatmap/)
 */
import type FeatureFilter from "../../layers/support/FeatureFilter.js";
import type HeatmapRenderer from "../../renderers/HeatmapRenderer.js";
import type { AbortOptions } from "../../core/promiseUtils.js";
import type { SupportedLayer } from "../types.js";
import type { HeatmapStatisticsResult } from "../statistics/types.js";
import type { HeatmapScheme, BasemapTheme } from "../symbology/types.js";
import type { MapViewOrSceneView } from "../../views/MapViewOrSceneView.js";

/**
 * Generates a [HeatmapRenderer](https://developers.arcgis.com/javascript/latest/api-reference/esri-renderers-HeatmapRenderer.html) that may be applied directly to the
 * layer used to call this method. The
 * renderer represents points as a continuous surface using optimal colors for the view's background.
 *
 * This method should be called when at least some points are visible in the input view's extent. If no
 * points are visible in the view, then the response will not return a useful visualization.
 *
 * In most cases you will provide a `layer`, `view`, and optional `field` to generate this renderer.
 * This is a scenario in which
 * the statistics and the distribution of the data aren't well known and the user doesn't know what colors
 * to use in the visualization.
 *
 * The other options are provided for convenience for more involved custom visualization authoring
 * applications. For example, if you already generated statistics in another operation, you
 * can pass the statistics object to the `statistics` parameter to avoid making an extra call to the server.
 *
 * @param parameters - Input parameters for generating a heatmap visualization based on data
 * returned from a given field. See the table below for details of each parameter.
 * @returns Resolves to an instance of [HeatmapRendererResult](https://developers.arcgis.com/javascript/latest/api-reference/esri-smartMapping-renderers-heatmap.html#HeatmapRendererResult).
 * @example
 * let earthquakeLayer = new FeatureLayer({
 *   // url to a point dataset
 * });
 *
 * // visualization based on field
 *
 * let heatmapParams = {
 *   layer: earthquakeLayer,
 *   view: view,
 *   field: "magnitude"
 * };
 *
 * // when the promise resolves, apply the renderer to the layer
 * heatmapRendererCreator.createRenderer(heatmapParams)
 *   .then(function(response){
 *     earthquakeLayer.renderer = response.renderer;
 *   });
 */
export function createRenderer(parameters: HeatmapRendererParameters): Promise<HeatmapRendererResult>;

/**
 * Allows you to update the [HeatmapRenderer#colorStops](https://developers.arcgis.com/javascript/latest/api-reference/esri-renderers-HeatmapRenderer.html#colorStops)
 * of a [HeatmapRenderer](https://developers.arcgis.com/javascript/latest/api-reference/esri-renderers-HeatmapRenderer.html) with opacity, making the low density areas
 * of the heat map to fade out.
 *
 * @param parameters - Input parameters for updating a heatmap renderer with a given fadeRatio.
 * @returns The updated HeatmapRenderer.
 * @since 4.25
 * @example
 * const renderer = heatmapRendererCreator.updateRenderer({
 *   renderer: layer.renderer
 *   fadeRatio: 0.7
 * });
 * layer.renderer = renderer;
 */
export function updateRenderer(parameters: UpdateHeatmapRendererParameters): HeatmapRenderer;

export interface HeatmapRendererParameters extends AbortOptions {
  /**
   * Indicates how much to fade the lower color stops with transparency to
   *   create a fuzzy boundary on the edge of the heatmap. A value of `0` makes a discrete boundary on the lower color stop.
   *
   * @default 0.2
   */
  fadeRatio?: number | null;
  /**
   * Indicates whether the heatmap should fade its colors to transparent. When
   *   `false`, the `fadeRatio` parameter is ignored.
   *
   * @default true
   */
  fadeToTransparent?: boolean | null;
  /**
   * The name of the field whose data will be queried for statistics and used for
   *   the basis of the data-driven visualization. The value of the `field` is used as a multiplier in the heatmap, making
   *   areas with high field values hotter than areas where the features have low field values.
   */
  field?: string | null;
  /**
   * _Since 4.31_ When defined, only features included in the filter
   *   are considered in the attribute and spatial statistics calculations when determining the final renderer.
   *   This is useful when a lot of variation exists in the data
   *   that could result in undesired data ranges. A common use case would be to set a filter that only
   *   includes features in the current extent of the view where the data is most likely to be viewed. Currently, only
   *   geometry filters with an `intersects` spatial relationship are supported. All other filter types (including `where`) are ignored.
   */
  filter?: FeatureFilter | null;
  /**
   * In authoring apps,
   *   the user may select a pre-defined heatmap scheme. Pass the scheme object to this property to avoid getting one
   *   based on the view's background.
   */
  heatmapScheme?: HeatmapScheme | null;
  /**
   * The point layer for which the visualization is generated. When a client-side layer type is provided, attribute statistics are calculated
   * only from features in the view's extent. When a server-side layer type is provided, the statistics
   * are calculated from the entire layer.
   */
  layer?: SupportedLayer | null;
  /**
   * The maximum [HeatmapColorStop#ratio](https://developers.arcgis.com/javascript/latest/api-reference/esri-renderers-support-HeatmapColorStop.html#ratio) used in the
   *   [HeatmapRenderer#colorStops](https://developers.arcgis.com/javascript/latest/api-reference/esri-renderers-HeatmapRenderer.html#colorStops) of the output renderer.
   *
   * @default 1
   */
  maxRatio?: number | null;
  /**
   * The minimum [HeatmapColorStop#ratio](https://developers.arcgis.com/javascript/latest/api-reference/esri-renderers-support-HeatmapColorStop.html#ratio) used in the
   *   [HeatmapRenderer#colorStops](https://developers.arcgis.com/javascript/latest/api-reference/esri-renderers-HeatmapRenderer.html#colorStops) of the output renderer.
   *
   * @default 0.01
   */
  minRatio?: number | null;
  /**
   * The [HeatmapRenderer#radius](https://developers.arcgis.com/javascript/latest/api-reference/esri-renderers-HeatmapRenderer.html#radius) in points that
   *   determines the area of influence of each point. A higher radius indicates points have more influence on surrounding points.
   *
   * @default 18
   */
  radius?: number | null;
  /**
   * A statistics object generated from the [heatmapStatistics](https://developers.arcgis.com/javascript/latest/api-reference/esri-smartMapping-statistics-heatmapStatistics.html) function.
   *   If statistics for the field have already been generated, then pass the object here to avoid making a second statistics
   *   query to the server.
   */
  statistics?: HeatmapStatisticsResult | null;
  /** The view instance in which the visualization will be rendered. */
  view?: MapViewOrSceneView | null;
}

/**
 * The result object of the [createRenderer()](https://developers.arcgis.com/javascript/latest/api-reference/esri-smartMapping-renderers-heatmap.html#createRenderer) method. See the table
 * below for details of each property.
 */
export interface HeatmapRendererResult {
  /** The ID of the basemap used to determine the optimal color stops of the heatmap. */
  basemapId?: string | null;
  /** Indicates whether the average color of the input view's basemap is `light` or `dark`. */
  basemapTheme?: BasemapTheme | null;
  /**
   * Indicates whether default values are used in the absence of sufficient
   *   data and/or statistics from the layer. Default values are typically used when all features have the same field
   *   value or no value at all.
   */
  defaultValuesUsed: boolean;
  /**
   * The renderer object configured to best
   *   match the view's background and the spread of the data. Set this on a layer's `renderer` property to
   *   update its visualization.
   */
  renderer: HeatmapRenderer;
  /**
   * The color scheme
   *   used by the renderer.
   */
  scheme?: HeatmapScheme | null;
  /** Basic statistics required for generating a renderer with optimal values for the given layer and view. */
  statistics: HeatmapStatisticsResult;
}

export interface UpdateHeatmapRendererParameters {
  /**
   * Indicates how much to fade the lower color stops with transparency to
   *   create a fuzzy boundary on the edge of the heatmap. A value of `0` makes a discrete boundary on the lower color stop.
   */
  fadeRatio?: number | null;
  /** The heatmap renderer for which to add or remove opacity. */
  renderer: HeatmapRenderer;
}