import type SliderViewModel from "../Slider/SliderViewModel.js";
import type { HistogramBin } from "../../smartMapping/statistics/types.js";
import type { LabelFormatFunction } from "../types.js";
import type { RangeType } from "./types.js";
import type { SliderViewModelProperties } from "../Slider/SliderViewModel.js";

export interface HistogramRangeSliderViewModelProperties extends SliderViewModelProperties, Partial<Pick<HistogramRangeSliderViewModel, "average" | "bins" | "rangeType" | "standardDeviation">> {
  /**
   * A modified version of
   * [SliderViewModel.labelFormatFunction](https://developers.arcgis.com/javascript/latest/references/core/widgets/Slider/SliderViewModel/#labelFormatFunction),
   * which is a custom function used to format labels. Overrides the default label formatter.
   *
   * @example
   * // For thumb values, rounds each label to whole numbers.
   * // Note the actual value of the thumb continues to be stored
   * // based on the indicated data `precision` despite this formatting
   * sliderViewModel.labelFormatFunction = function(value, type) {
   *   return (type === "value") ? value.toFixed(0) : value;
   * }
   */
  labelFormatFunction?: LabelFormatFunction;
}

/**
 * Provides the logic for the [HistogramRangeSlider](https://developers.arcgis.com/javascript/latest/references/core/widgets/HistogramRangeSlider/) widget.
 *
 * @since 4.12
 * @see [HistogramRangeSlider](https://developers.arcgis.com/javascript/latest/references/core/widgets/HistogramRangeSlider/)
 * @see [Programming patterns: Widget viewModel pattern](https://developers.arcgis.com/javascript/latest/programming-patterns/#widget-viewmodel-pattern)
 */
export default class HistogramRangeSliderViewModel extends SliderViewModel {
  constructor(properties?: HistogramRangeSliderViewModelProperties);
  /**
   * The statistical average of the data in the histogram. You would typically
   * get this value from the `avg` property of
   * [SummaryStatisticsResult](https://developers.arcgis.com/javascript/latest/references/core/smartMapping/statistics/types/#SummaryStatisticsResult),
   * which is the result of the
   * [summaryStatistics](https://developers.arcgis.com/javascript/latest/references/core/smartMapping/statistics/summaryStatistics/) function.
   *
   * @example
   * // sets result returned from a smart mapping method
   * // to the histogram
   * histogramSliderVM.average = response.statistics.avg;
   * @example histogramSliderVM.average = 34.5;
   */
  accessor average: number | null | undefined;
  /**
   * An array of objects representing each bin in the histogram. This
   * information is typically returned from the
   * [histogram](https://developers.arcgis.com/javascript/latest/references/core/smartMapping/statistics/histogram/) function.
   *
   * @example
   * // sets the bins of the histogram from the bins in the histogram() result
   * histogramVM.bins = histogramResult.bins;
   * @example
   * // Creates a histogram with 7 bins.
   * histogramVM.bins = [
   *   { minValue: 0, maxValue: 10, count: 4 },
   *   { minValue: 10.1, maxValue: 20, count: 14 },
   *   { minValue: 20.1, maxValue: 30, count: 9 },
   *   { minValue: 30.1, maxValue: 40, count: 34 },
   *   { minValue: 40.1, maxValue: 50, count: 351 },
   *   { minValue: 50.1, maxValue: 60, count: 100 },
   *   { minValue: 60.1, maxValue: 70, count: 1 }
   * ];
   */
  accessor bins: HistogramBin[] | null | undefined;
  /**
   * A modified version of
   * [SliderViewModel.labelFormatFunction](https://developers.arcgis.com/javascript/latest/references/core/widgets/Slider/SliderViewModel/#labelFormatFunction),
   * which is a custom function used to format labels. Overrides the default label formatter.
   *
   * @example
   * // For thumb values, rounds each label to whole numbers.
   * // Note the actual value of the thumb continues to be stored
   * // based on the indicated data `precision` despite this formatting
   * sliderViewModel.labelFormatFunction = function(value, type) {
   *   return (type === "value") ? value.toFixed(0) : value;
   * }
   */
  accessor labelFormatFunction: LabelFormatFunction;
  /**
   * Determines the SQL where clause generated in [generateWhereClause()](https://developers.arcgis.com/javascript/latest/references/core/widgets/HistogramRangeSlider/HistogramRangeSliderViewModel/#generateWhereClause)
   * for filtering purposes. The value set here determines the number of [values](https://developers.arcgis.com/javascript/latest/references/core/widgets/HistogramRangeSlider/HistogramRangeSliderViewModel/#values)
   * allowed on the slider.
   *
   * See the table below for a description and requirements of all possible values. `value1` refers to
   * the value of the first thumb position. `value2` refers to the value of the final thumb position, if applicable.
   *
   * Possible Value | Number of [values](https://developers.arcgis.com/javascript/latest/references/core/widgets/HistogramRangeSlider/HistogramRangeSliderViewModel/#values) | [Where clause](https://developers.arcgis.com/javascript/latest/references/core/widgets/HistogramRangeSlider/HistogramRangeSliderViewModel/#generateWhereClause)
   * ---------------|----------------------------|----------------------
   * equal | 1 | `${field} = ${value1}`
   * not-equal | 1 | `${field} <> ${value1}`
   * less-than | 1 | `${field} < ${value1}`
   * greater-than | 1 | `${field} > ${value1}`
   * at-most | 1 | `${field} <= ${value1}`
   * at-least | 1 | `${field} >= ${value1}`
   * between | 2 | `${field} BETWEEN ${value1} AND ${value2}`
   * not-between | 2 | `${field} NOT BETWEEN ${value1} AND ${value2}`
   *
   * @default "equal"
   * @see [generateWhereClause()](https://developers.arcgis.com/javascript/latest/references/core/widgets/HistogramRangeSlider/HistogramRangeSliderViewModel/#generateWhereClause)
   * @example
   * // renders the histogram so that all bins between
   * // the two handles are shaded with a blue color
   * slider.viewModel.rangeType = "between";
   *
   * // filters the layer view based on the configuration
   * // of the slider
   * layerView.filter = {
   *   where: slider.viewModel.generateWhereClause("POPULATION")
   * };
   *
   * // if slider min is 1,000 and max is 10,000, the following is generated
   * // layerView.filter.where = 'POPULATION >= 1000 AND POPULATION <= 10000'
   */
  accessor rangeType: RangeType;
  /**
   * Indicates the standard deviation of the dataset
   * above and below the `average`.
   *
   * @example
   * // stddev returned from summaryStatistics
   * slider.viewModel.standardDeviation = stats.stddev;
   */
  accessor standardDeviation: number | null | undefined;
  /**
   * Generates a SQL where clause based on a given field and the slider's
   * [rangeType](https://developers.arcgis.com/javascript/latest/references/core/widgets/HistogramRangeSlider/HistogramRangeSliderViewModel/#rangeType). This is a convenience function for data filtering
   * or data queries.
   *
   * @param field - Name of the field used in the where clause. This
   *   field should correspond to the data used to generate the histogram
   *   associated with the slider.
   * @returns The SQL where clause to apply to a filter or query.
   * @see [rangeType](https://developers.arcgis.com/javascript/latest/references/core/widgets/HistogramRangeSlider/HistogramRangeSliderViewModel/#rangeType)
   * @see [FeatureLayerView.filter](https://developers.arcgis.com/javascript/latest/references/core/views/layers/FeatureLayerView/#filter)
   * @see [FeatureEffect.filter](https://developers.arcgis.com/javascript/latest/references/core/layers/support/FeatureEffect/#filter)
   * @see [FeatureLayerView.queryFeatures()](https://developers.arcgis.com/javascript/latest/references/core/views/layers/FeatureLayerView/#queryFeatures)
   * @example
   * // renders the histogram so that all bins between
   * // the two handles are shaded with a blue color by default
   * slider.viewModel.rangeType = "between";
   *
   * // filters the layerview based on the configuration
   * // of the slider
   * layerView.filter = {
   *   where: slider.viewModel.generateWhereClause("POPULATION")
   * }
   */
  generateWhereClause(field: string): string | null | undefined;
}