/**
 * This object contains a helper method for generating default labels to be set on
 * a layer's [cluster configuration](https://developers.arcgis.com/javascript/latest/references/core/layers/support/FeatureReductionCluster/#labelingInfo).
 * The default label is based on the layer's renderer. In most cases the default label configuration will
 * be the total number of features in the cluster. This value will be rounded and formatted (e.g. instead of `2385`, the
 * cluster label will display `2.4k`). In some cases, such as renderers with a [SizeVariable](https://developers.arcgis.com/javascript/latest/references/core/renderers/visualVariables/SizeVariable/),
 * the default label will display the average value of the attribute represented by the size variable.
 *
 * [![clustering-generated-labels](https://developers.arcgis.com/javascript/latest/assets/references/core/layers/clustering/clustering-generated-labels.png)](https://developers.arcgis.com/javascript/latest/sample-code/featurereduction-cluster-filter/)
 *
 * This includes secondary labeling schemes you can experiment with in your clusters. This module only applies to layers with a point geometry type.
 *
 * @since 4.16
 * @see [FeatureReductionCluster.labelingInfo](https://developers.arcgis.com/javascript/latest/references/core/layers/support/FeatureReductionCluster/#labelingInfo)
 * @see [Sample - Point clustering - generate suggested configuration](https://developers.arcgis.com/javascript/latest/sample-code/featurereduction-cluster-filter/)
 */
import type LabelClass from "../../layers/support/LabelClass.js";
import type MapView from "../../views/MapView.js";
import type { ClusteringSupportedLayer } from "../types.js";
import type { ClusterableRenderer } from "../../views/2d/layers/types.js";

/**
 * Generates default [FeatureReductionCluster.labelingInfo](https://developers.arcgis.com/javascript/latest/references/core/layers/support/FeatureReductionCluster/#labelingInfo)
 * schemes to be set on a FeatureLayer's [FeatureLayer.featureReduction](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#featureReduction) configuration.
 * Returns one or more suggested LabelClasses
 * for a given layer based on its renderer. It also returns a suggested
 * [FeatureReductionCluster.clusterMinSize](https://developers.arcgis.com/javascript/latest/references/core/layers/support/FeatureReductionCluster/#clusterMinSize) to
 * ensure labels fit inside clusters.
 *
 * If a renderer has a non-scale dependent [SizeVariable](https://developers.arcgis.com/javascript/latest/references/core/renderers/visualVariables/SizeVariable/), then the average value of the field or expression
 * used to determine the cluster size will be suggested as the default label value. In all other scenarios,
 * the suggested label will display the cluster count in the center of the label.
 *
 * @param parameters - The function parameters.
 * @returns Returns an object containing suggested primary
 *   and secondary labeling schemes to be set on the layer's `featureReduction` property.
 * @example
 * // Sets suggested labels on the clusters based on the underlying renderer
 * clusterLabelCreator.getLabelSchemes({
 *   layer: featureLayer,
 *   view: view
 * }).then(function(labelSchemes){
 *   const featureReduction = featureLayer.featureReduction.clone();
 *   const { labelingInfo, clusterMinSize } = labelSchemes.primaryScheme;
 *   featureReduction.labelingInfo = labelingInfo;
 *   featureReduction.clusterMinSize = clusterMinSize;
 *
 *   featureLayer.featureReduction = featureReduction;
 * }).catch(function(error){
 *   console.error(error);
 * });
 */
export function getLabelSchemes(parameters: SchemeParameters): Promise<Schemes | null | undefined>;

export interface SchemeParameters {
  /**
   * The name of the [AggregateField.name](https://developers.arcgis.com/javascript/latest/references/core/layers/support/AggregateField/#name)
   *   to use in the primary label scheme. If not specified, then the label will be based on the data used to vary cluster size.
   */
  field?: string;
  /**
   * The renderer to set on the input layer when clustering is enabled.
   *   Specify this parameter if the layer's renderer does not match the renderer that will be used when clustering is enabled.
   *   This cannot be a [HeatmapRenderer](https://developers.arcgis.com/javascript/latest/references/core/renderers/HeatmapRenderer/).
   */
  renderer?: ClusterableRenderer;
  /** The point layer that has or will have clustering enabled. */
  layer: ClusteringSupportedLayer;
  /** The view where the input layer will be rendered. */
  view: MapView;
}

/** Contains a suggested labelingInfo to be set on the layer's [featureReduction.labelingInfo](https://developers.arcgis.com/javascript/latest/references/core/layers/support/FeatureReductionCluster/#labelingInfo). */
export interface Scheme {
  /**
   * The name of the generated cluster labeling scheme.
   *   This can be used in the UI of web map authoring apps.
   */
  name: string;
  /**
   * An array of
   *   LabelClass objects to set on the layer's [featureReduction.labelingInfo](https://developers.arcgis.com/javascript/latest/references/core/layers/support/FeatureReductionCluster/#labelingInfo)
   *   property.
   */
  labelingInfo: LabelClass[];
  /**
   * The suggested
   *   [featureReduction.clusterMinSize](https://developers.arcgis.com/javascript/latest/references/core/layers/support/FeatureReductionCluster/#clusterMinSize)
   *   required to fit labels within clusters.
   */
  clusterMinSize: number;
  /**
   * The name of the aggregate field the labeling scheme is based on.
   *   This can be used in the UI of web map authoring apps.
   */
  fieldName: string;
}

/** The return object of the [getLabelSchemes()](https://developers.arcgis.com/javascript/latest/references/core/smartMapping/labels/clusters/#getLabelSchemes) method. */
export interface Schemes {
  /** Includes the primary labeling scheme suggested for the input layer's clusters. */
  primaryScheme: Scheme;
  /** Includes secondary labeling schemes suggested for the input layer's clusters. */
  secondarySchemes: Scheme[];
}