/**
 * This object contains a helper method for generating a pie chart for every feature.
 *
 *
 * For example, suppose you have a layer of U.S. counties with fields containing the total sales of various crops:
 * wheat, soybeans, corn, cotton, and vegetables.
 * You can use the [createRenderer()](https://developers.arcgis.com/javascript/latest/api-reference/esri-smartMapping-renderers-pieChart.html#createRenderer) method in this module to generate a chart for each feature visualizing the proportion
 * of each crop type for every county.
 *
 * > [!WARNING]
 * >
 * > **Known Limitations**
 * >
 * > Only supported in 2D [MapView](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html).
 * > Only supported in layers with `point` and `polygon` geometries.
 *
 * @since 4.24
 * @see [PieChartRenderer](https://developers.arcgis.com/javascript/latest/api-reference/esri-renderers-PieChartRenderer.html)
 */
import type CSVLayer from "../../layers/CSVLayer.js";
import type FeatureLayer from "../../layers/FeatureLayer.js";
import type GeoJSONLayer from "../../layers/GeoJSONLayer.js";
import type OGCFeatureLayer from "../../layers/OGCFeatureLayer.js";
import type OrientedImageryLayer from "../../layers/OrientedImageryLayer.js";
import type ParquetLayer from "../../layers/ParquetLayer.js";
import type StreamLayer from "../../layers/StreamLayer.js";
import type SubtypeGroupLayer from "../../layers/SubtypeGroupLayer.js";
import type WFSLayer from "../../layers/WFSLayer.js";
import type KnowledgeGraphSublayer from "../../layers/knowledgeGraph/KnowledgeGraphSublayer.js";
import type AggregateField from "../../layers/support/AggregateField.js";
import type FeatureFilter from "../../layers/support/FeatureFilter.js";
import type SubtypeSublayer from "../../layers/support/SubtypeSublayer.js";
import type PieChartRenderer from "../../renderers/PieChartRenderer.js";
import type * as sizeCreator from "./size.js";
import type MapView from "../../views/MapView.js";
import type { AbortOptions } from "../../core/promiseUtils.js";
import type { RendererLegendTitleOption } from "../../renderers/support/types.js";
import type { SupportedLayer } from "../types.js";
import type { Attribute, UniqueValuesResult } from "../statistics/types.js";
import type { PieChartScheme, BasemapTheme } from "../symbology/types.js";

/**
 * Generates a [PieChartRenderer](https://developers.arcgis.com/javascript/latest/api-reference/esri-renderers-PieChartRenderer.html) based on a set of numeric fields.
 *
 * @param parameters - Input parameters for generating a pie chart visualization based on a set of numeric fields.
 *   See the table below for details of each parameter.
 * @returns Resolves to an instance of [RendererResult](https://developers.arcgis.com/javascript/latest/api-reference/esri-smartMapping-renderers-pieChart.html#RendererResult).
 * @example
 * const layer = new FeatureLayer({
 *   url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/USA_County_Crops_2007/FeatureServer/0"
 * });
 *
 * // will create a visualization of predominant crop by U.S. county
 *
 * const parameters = {
 *   layer: layer,
 *   view: view,
 *   attributes: [{
 *     field: "M217_07",
 *     label: "Vegetables"
 *   }, {
 *     field: "M188_07",
 *     label: "Cotton"
 *   }, {
 *     field: "M172_07",
 *     label: "Wheat"
 *   }, {
 *     field: "M193_07",
 *     label: "Soybeans"
 *   }, {
 *     field: "M163_07",
 *     label: "Corn"
 *   }],
 *   includeSizeVariable: true,
 *   sizeOptimizationEnabled: true,
 *   shape: "donut"
 * };
 *
 * // when the promise resolves, apply the renderer to the layer
 * const { renderer } = await pieChartRendererCreator.createRenderer(parameters);
 * layer.renderer = renderer;
 */
export function createRenderer(parameters: RendererParameters): Promise<RendererResult>;

/**
 * Generates a [PieChartRenderer](https://developers.arcgis.com/javascript/latest/api-reference/esri-renderers-PieChartRenderer.html) to use for a
 * [FeatureReductionCluster](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureReductionCluster.html) visualization based off an input layer's
 * [UniqueValueRenderer](https://developers.arcgis.com/javascript/latest/api-reference/esri-renderers-UniqueValueRenderer.html) or [ClassBreaksRenderer](https://developers.arcgis.com/javascript/latest/api-reference/esri-renderers-ClassBreaksRenderer.html). This method
 * also generates aggregate fields that must be provided to the [FeatureReductionCluster](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureReductionCluster.html)
 * object to properly render.
 *
 * @param parameters - Input parameters for generating a pie chart visualization for clustering.
 *   See the table below for details of each parameter.
 * @returns Resolves to an instance of [ClusterRendererResult](https://developers.arcgis.com/javascript/latest/api-reference/esri-smartMapping-renderers-pieChart.html#ClusterRendererResult).
 * @since 4.25
 * @example
 * const { renderer, fields } = await pieChartRendererCreator.createRendererForClustering({
 *   layer,
 *   shape: "donut"
 * });
 *
 * const featureReduction = {
 *   type: "cluster",
 *   renderer,
 *   fields
 * };
 *
 * layer.featureReduction = featureReduction;
 */
export function createRendererForClustering(parameters: ClusterRendererParameters): Promise<ClusterRendererResult>;

export interface RendererParameters extends AbortOptions {
  /**
   * A set of complementary numeric fields/expressions used to create the charts.
   *   For example, if creating an election map, you would indicate the name of each field representing
   *   the candidate or political party where their total counts are stored.
   */
  attributes?: Attribute[] | 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;
  /**
   * Indicates whether the generated renderer is for a binning or clustering visualization.
   *   If `true`, then the input field(s) in this method should refer to [aggregate fields](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-AggregateField.html) defined in the `featureReduction` property of the layer.
   */
  forBinning?: boolean | null;
  /**
   * Indicates whether to include data-driven size in the final
   *   renderer. If `true`, features will be assigned a sized based on the sum of all values in the `attributes` param.
   *   Features with small total counts will be sized with small charts and features with large total counts will be
   *   sized with large charts. Enabling this option
   *   is good for visualizing how influential a particular feature is compared to the dataset as a whole.
   *   It removes bias introduced by features with large geographic areas, but relatively small data values.
   */
  includeSizeVariable?: boolean | null;
  /**
   * The layer
   *   for which the visualization is generated. When a client-side layer type is provided, attribute and spatial 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, unless a `valueExpression` is provided.
   */
  layer?: SupportedLayer | null;
  /**
   * Provides options for modifying [Legend](https://developers.arcgis.com/javascript/latest/references/map-components/arcgis-legend/)
   *   properties describing the visualization.
   */
  legendOptions?: RendererLegendTitleOption | null;
  /**
   * Only for polygon layers. Indicates whether the
   *   polygon's background fill symbol outline width should vary based on view scale.
   *
   * @default false
   */
  outlineOptimizationEnabled?: boolean | null;
  /**
   * In authoring apps,
   *   the user may select a pre-defined color scheme. Pass the scheme object to this property to avoid
   *   getting one based on the background of the `view`.
   */
  pieChartScheme?: PieChartScheme | null;
  /**
   * Determines whether to create a pie chart or a donut chart.
   *
   * @default "pie"
   */
  shape?: "donut" | "pie" | null;
  /**
   * Indicates whether
   *   chart sizes should vary based on view scale.
   *
   * @default false
   */
  sizeOptimizationEnabled?: boolean | null;
  /** The view instance in which the visualization will be rendered. */
  view?: MapView | null;
}

/**
 * The result object of the [createRenderer()](https://developers.arcgis.com/javascript/latest/api-reference/esri-smartMapping-renderers-pieChart.html#createRenderer) method. See the table
 * below for details of each property.
 */
export interface RendererResult {
  /** The ID of the basemap used to determine the optimal color schemes for the charts. */
  basemapId?: string | null;
  /** Indicates whether the average color of the input view's basemap is `light` or `dark`. */
  basemapTheme?: BasemapTheme | null;
  /** The color scheme used by the renderer. */
  pieChartScheme: PieChartScheme;
  /**
   * The generated pie chart renderer.
   *   Set this on a layer's `renderer` property to update its visualization.
   */
  renderer: PieChartRenderer;
  /**
   * A size visual
   *   variable representing the sum of all attributes included in the pie chart. This is returned
   *   if the `includeSizeVariable` parameter is true.
   */
  size?: sizeCreator.VisualVariableResult | null;
  /**
   * Contains
   *   the total counts of each attribute used in the renderer.
   */
  statistics: UniqueValuesResult;
}

/**
 * The result object of the [createRendererForClustering()](https://developers.arcgis.com/javascript/latest/api-reference/esri-smartMapping-renderers-pieChart.html#createRendererForClustering) method. See the table
 * below for details of each property.
 */
export interface ClusterRendererResult {
  /**
   * The aggregate fields used by the `renderer`.
   *   Set this on a [FeatureReductionCluster#fields](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureReductionCluster.html#fields) property of the
   *   [FeatureReductionCluster](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureReductionCluster.html) instance alongside the `renderer`
   *   to update the clustering visualization to pie charts.
   */
  fields: AggregateField[];
  /**
   * The generated pie chart renderer to use for clustering.
   *   Set this on a [FeatureReductionCluster#renderer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureReductionCluster.html#renderer) property of the
   *   [FeatureReductionCluster](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-FeatureReductionCluster.html) instance
   *   to update its visualization.
   */
  renderer: PieChartRenderer;
}

export interface ClusterRendererParameters extends AbortOptions {
  /**
   * Includes the `defaultSymbol` defined in the input layer's renderer in
   *   the output pie chart renderer.
   *
   * @default true
   */
  defaultSymbolEnabled?: boolean | null;
  /**
   * The layer
   *   for which the visualization is generated. To use the output cluster renderer, you must first enable clustering on the layer.
   */
  layer: FeatureLayer | GeoJSONLayer | CSVLayer | OGCFeatureLayer | WFSLayer | ParquetLayer | SubtypeGroupLayer | SubtypeSublayer | KnowledgeGraphSublayer | OrientedImageryLayer | StreamLayer;
  /**
   * Provides options for modifying [Legend](https://developers.arcgis.com/javascript/latest/references/map-components/arcgis-legend/)
   *   properties describing the visualization.
   */
  legendOptions?: RendererLegendTitleOption | null;
  /**
   * Determines whether to create a pie chart or a donut chart.
   *
   * @default "pie"
   */
  shape?: "donut" | "pie" | null;
}