/// <reference path="../../index.d.ts" />
import type ClassBreakInfo from "@arcgis/core/renderers/support/ClassBreakInfo.js";
import type { PublicLitElement as LitElement } from "@arcgis/lumina";
import type { ClassBreaksRendererResult } from "@arcgis/core/smartMapping/renderers/size.js";
import type { HistogramResult } from "@arcgis/core/smartMapping/statistics/types.js";
import type { ArcgisReferenceElement, IconName } from "../types.js";
import type { ThumbDragEvent, ThumbChangeEvent } from "@arcgis/core/widgets/Slider/types.js";
import type { SizeBreak, HistogramConfig } from "@arcgis/core/widgets/smartMapping/types.js";
import type { LabelFormatFunction, InputParseFunction } from "@arcgis/core/widgets/types.js";
import type { ClassedSizeSliderStyle } from "@arcgis/core/widgets/smartMapping/ClassedSizeSlider.js";
import type { SmartMappingSliderBaseState } from "@arcgis/core/widgets/smartMapping/SmartMappingSliderBase.js";

/**
 * > [!WARNING]
 * >
 * > This is a **legacy component**. It relies on an underlying widget as part of our migration to native web components.
 * >
 * > A fully native replacement for this component is in development. Once it reaches feature parity, the legacy component will be deprecated and no longer maintained. At that point, development should use the native component.
 *
 * The Classed Size Slider component is designed for authoring and exploring data-driven visualizations in any
 * layer that can be rendered with size in a [ClassBreaksRenderer](https://developers.arcgis.com/javascript/latest/references/core/renderers/ClassBreaksRenderer/).
 *
 * See the image below for a summary of the configurable options available on this slider.
 *
 * ![Classed Size Slider with annotations](https://developers.arcgis.com/javascript/latest/assets/references/core/widgets/sliders/classedsizeslider-labels.avif "Classed Size Slider with annotations")
 *
 * The [updateFromRendererResult()](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-slider-classed-size-legacy/#updateFromRendererResult) method can be used to intelligently populate slider properties including
 * [max](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-slider-classed-size-legacy/#max), [min](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-slider-classed-size-legacy/#min), the [classBreakInfos](https://developers.arcgis.com/javascript/latest/references/core/renderers/ClassBreaksRenderer/#classBreakInfos) configuration,
 * and the slider's histogram after the renderer has been created from the result of the [createClassBreaksRenderer](https://developers.arcgis.com/javascript/latest/references/core/smartMapping/renderers/size/#createClassBreaksRenderer)
 * method.
 *
 * ```js
 * const sizeRendererCreator = await import("@arcgis/core/smartMapping/renderers/size.js");
 * const viewElement = document.querySelector("arcgis-map")!;
 * const classedSizeSlider = document.querySelector("arcgis-slider-classed-size-legacy")!;
 *
 * const featureLayer = new FeatureLayer({
 *   url: "https://services.arcgis.com/P3ePLMYs2RVChkJx/arcgis/rest/services/ACS_Median_Income_by_Race_and_Age_Selp_Emp_Boundaries/FeatureServer/1",
 * });
 *
 * await viewElement.viewOnReady();
 * viewElement.map?.add(featureLayer);
 *
 * const params = {
 *   layer: featureLayer,
 *   field: "B19049_001E",
 *   view: viewElement.view,
 *   numClasses: 4,
 * };
 *
 * const rendererResult = await sizeRendererCreator.createClassBreaksRenderer(params);
 *
 * featureLayer.renderer = rendererResult.renderer;
 *
 * const histogramResult = await histogram({
 *   ...params,
 *   numBins: 30,
 * });
 *
 * await classedSizeSlider?.updateFromRendererResult(rendererResult, histogramResult);
 * ```
 *
 * This slider should be used to update the [classBreakInfos](https://developers.arcgis.com/javascript/latest/references/core/renderers/ClassBreaksRenderer/#classBreakInfos)
 * in a ClassBreaksRenderer. It is the responsibility of the app developer
 * to set up event listeners on this slider that update the breaks of the appropriate renderer.
 *
 * ```js
 * const updateRendererFromSlider = async () => {
 *   const renderer = featureLayer?.renderer?.clone();
 *   if (!renderer || !("classBreakInfos" in renderer) || !renderer.classBreakInfos?.[0]) {
 *     return;
 *   }
 *   renderer.classBreakInfos = (await classedSizeSlider.updateClassBreakInfos(renderer.classBreakInfos);
 *   featureLayer.renderer = renderer;
 * };
 *
 * classedSizeSlider.addEventListener("arcgisThumbChange", updateRendererFromSlider);
 * classedSizeSlider.addEventListener("arcgisThumbDrag", updateRendererFromSlider);
 * classedSizeSlider.addEventListener("arcgisPropertyChange", updateRendererFromSlider);
 * ```
 *
 * @since 5.0
 * @see [sizeRendererCreator](https://developers.arcgis.com/javascript/latest/references/core/smartMapping/renderers/size/)
 * @see [ClassBreaksRenderer](https://developers.arcgis.com/javascript/latest/references/core/renderers/ClassBreaksRenderer/)
 */
export abstract class ArcgisSliderClassedSizeLegacy extends LitElement {
  /**
   * If true, the component will not be destroyed automatically when it is
   * disconnected from the document. This is useful when you want to move the
   * component to a different place on the page, or temporarily hide it. If this
   * is set, make sure to call the [destroy()](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-slider-classed-size-legacy/#destroy) method when you are done to
   * prevent memory leaks.
   *
   * @default false
   */
  accessor autoDestroyDisabled: boolean;
  /**
   * An array of class breaks with associated sizes. The size mapped to each break should
   * be used to update the renderer of a layer. A minimum of two breaks must be provided to the slider.
   *
   * @example
   * ```js
   * classedSizeSlider.breaks = [
   *   { min: 0, max: 20, size: 6 },
   *   { min: 20, max: 40, size: 12 },
   *   { min: 40, max: 60, size: 24 },
   *   { min: 60, max: 80, size: 48 },
   * ];
   * ```
   */
  accessor breaks: Array<SizeBreak>;
  /**
   * The histogram associated with the data represented on the slider. The bins are typically
   * generated using the [histogram](https://developers.arcgis.com/javascript/latest/references/core/smartMapping/statistics/histogram/) statistics function.
   *
   * @example
   * ```js
   * const histogramResult = await histogram({
   *   layer: featureLayer,
   *   field: "fieldName",
   *   numBins: 30,
   * });
   *
   * slider.histogramConfig = {
   *   bins: histogramResult.bins
   * };
   * ```
   * @see [histogram](https://developers.arcgis.com/javascript/latest/references/core/smartMapping/statistics/histogram/)
   */
  accessor histogramConfig: HistogramConfig | null | undefined;
  /**
   * Icon which represents the component.
   * Typically used when the component is controlled by another component (e.g. by the Expand component).
   *
   * @see [Calcite Icons](https://developers.arcgis.com/calcite-design-system/icons/)
   */
  accessor icon: IconName;
  /**
   * A function used to format user inputs. As opposed to [labelFormatFunction](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-slider-classed-size-legacy/#labelFormatFunction), which formats
   * thumb labels, the `inputFormatFunction` formats thumb values in the input element when the user begins
   * to edit them.
   *
   * The image below demonstrates how slider input values resemble corresponding slider values by default
   * and won't match the formatting set in `labelFormatFunction`.
   *
   * ![Slider without input formatter](https://developers.arcgis.com/javascript/latest/assets/references/core/widgets/sliders/slider-no-input-formatter.avif "Slider without input formatter")
   *
   * If you want to format slider input values so they match thumb labels, you can pass the same function set in `labelFormatFunction` to
   * `inputFormatFunction` for consistent formatting.
   *
   * ![Slider with input formatter](https://developers.arcgis.com/javascript/latest/assets/references/core/widgets/sliders/slider-input-formatter.avif "Slider with input formatter")
   *
   * However, if an `inputFormatFunction` is specified, you must also write a corresponding
   * [inputParseFunction](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-slider-classed-size-legacy/#inputParseFunction) to parse user inputs to understandable slider values. In most cases, if
   * you specify an `inputFormatFunction`, you should set the [labelFormatFunction](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-slider-classed-size-legacy/#labelFormatFunction) to the same value
   * for consistency between labels and inputs.
   *
   * This property overrides the default input formatter, which formats by calling `toString()` on the input value.
   *       
   *
   * @see [inputParseFunction](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-slider-classed-size-legacy/#inputParseFunction)
   * @example
   * ```js
   * // Formats the slider input to abbreviated numbers with units
   * // e.g. a thumb at position 1500 will render with an input label of 1.5k
   * slider.inputFormatFunction = (value: number): string => {
   *   if (value >= 1000000) {
   *     return (value / 1000000).toPrecision(3) + "m";
   *   }
   *   if (value >= 100000) {
   *     return (value / 1000).toPrecision(3) + "k";
   *   }
   *   if (value >= 1000) {
   *     return (value / 1000).toPrecision(2) + "k";
   *   }
   *   return value.toFixed(0);
   * };
   * ```
   */
  accessor inputFormatFunction: LabelFormatFunction | null | undefined;
  /**
   * Function used to parse slider inputs formatted by the [inputFormatFunction](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-slider-classed-size-legacy/#inputFormatFunction).
   * This property must be set if an `inputFormatFunction` is set. Otherwise the slider values will
   * likely not update to their expected positions.
   *
   * Overrides the default input parses, which is a parsed floating point number.
   *
   * @see [inputFormatFunction](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-slider-classed-size-legacy/#inputFormatFunction)
   * @example
   * ```js
   * // Parses the slider input (a string value) to a number value understandable to the slider
   * // This assumes the slider was already configured with an inputFormatFunction
   * // For example, if the input is 1.5k this function will parse
   * // it to a value of 1500
   * colorSlider.inputParseFunction = (value: string): number => {
   *   const charLength = value.length;
   *   const valuePrefix = parseFloat(value.substring(0, charLength - 1));
   *   const finalChar = value.substring(charLength - 1);
   *
   *   if (parseFloat(finalChar) >= 0) {
   *     return parseFloat(value);
   *   }
   *   if (finalChar === "k") {
   *     return valuePrefix * 1000;
   *   }
   *   if (finalChar === "m") {
   *     return valuePrefix * 1000000;
   *   }
   *   return parseFloat(value);
   * };
   *           ```
   */
  accessor inputParseFunction: InputParseFunction | null | undefined;
  /**
   * A function used to format labels on the thumbs, min, max, and average values. Overrides the default label formatter. This function also supports date formatting.
   *
   * @example
   * ```js
   * // For thumb values, rounds each label to whole numbers
   * slider.labelFormatFunction = (value: number, type?: SliderFormatType): string => {
   *   return (type === "value") ? value.toFixed(0) : value.toString();
   * };
   * ```
   */
  accessor labelFormatFunction: LabelFormatFunction | null | undefined;
  /**
   * The maximum value or upper bound of the slider. Once the slider has rendered with the [updateFromRendererResult()](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-slider-classed-size-legacy/#updateFromRendererResult) method,
   * the user may change this property by selecting the label containing the max value on the slider UI. It is the responsibility of the app developer
   * to set up event listeners that update the breaks of the appropriate renderer.
   *
   * @example
   * ```js
   * classedSizeSlider.max = 150;
   * ```
   */
  accessor max: number;
  /**
   * The minimum value or lower bound of the slider. Once the slider has rendered with the [updateFromRendererResult()](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-slider-classed-size-legacy/#updateFromRendererResult) method,
   * the user may change this property by selecting the label containing the min value on the slider UI. It is the responsibility of the app developer
   * to set up event listeners that update the breaks of the appropriate renderer.
   *
   * @example
   * ```js
   * classedSizeSlider.min = -150;
   * ```
   */
  accessor min: number;
  /**
   * Defines how slider thumb values should be rounded. This number indicates the number
   * of decimal places slider thumb _values_ should round to when they have been moved.
   *
   * Keep in mind this property rounds thumb values and shouldn't be used exclusively for formatting purposes.
   *
   * @default 4
   * @example
   * ```js
   * // Rounds slider thumb values to 7 decimal places
   * slider.precision = 7;
   * ```
   */
  accessor precision: number;
  /**
   * By assigning the `id` attribute of the Map or Scene component to this property, you can position a child component anywhere in the DOM while still maintaining a connection to the Map or Scene.
   *
   * @see [Associate components with a Map or Scene component](https://developers.arcgis.com/javascript/latest/programming-patterns/#associate-components-with-a-map-or-scene-component)
   */
  accessor referenceElement: ArcgisReferenceElement | string | undefined;
  /**
   * Exposes various properties of the component that can be styled. The result object from the [createClassBreaksRenderer()](https://developers.arcgis.com/javascript/latest/references/core/smartMapping/renderers/size/#createClassBreaksRenderer)
   * method can be used to match the `trackFillColor` to the current layer symbology.
   *
   * @see [Color](https://developers.arcgis.com/javascript/latest/references/core/Color/)
   * @example
   * ```js
   * classedSizeSlider.sliderStyle = {
   *   trackFillColor: rendererResult.renderer.classBreakInfos[0].symbol.color ?? new Color([149, 149, 149]),
   *   trackBackgroundColor: new Color([224, 224, 224]),
   * };
   * ```
   */
  accessor sliderStyle: ClassedSizeSliderStyle;
  /** The current state of the component. */
  get state(): SmartMappingSliderBaseState;
  /** Permanently destroy the component. */
  destroy(): Promise<void>;
  /**
   * A convenience function used to update the
   * [classBreakInfos](https://developers.arcgis.com/javascript/latest/references/core/renderers/ClassBreaksRenderer/#classBreakInfos)
   * of a [ClassBreaksRenderer](https://developers.arcgis.com/javascript/latest/references/core/renderers/ClassBreaksRenderer/) associated with this slider.
   *
   * The number of breaks from the renderer must match the number of breaks in the slider.
   * Generally, the input breaks for this method should come from the same renderer as one
   * used to create the slider with the [updateFromRendererResult()](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-slider-classed-size-legacy/#updateFromRendererResult) method.
   *
   * @param breakInfos - The classBreakInfos
   *   from a [ClassBreaksRenderer](https://developers.arcgis.com/javascript/latest/references/core/renderers/ClassBreaksRenderer/) instance to update based on
   *   the properties of the slider.
   * @returns The updated classBreakInfos to set
   *   on a ClassBreaksRenderer object.
   * @example
   * ```js
   * const renderer = featureLayer?.renderer?.clone();
   * renderer.classBreakInfos = (await classedSizeSlider.updateClassBreakInfos(renderer.classBreakInfos));
   * featureLayer.renderer = renderer;
   * ```
   */
  updateClassBreakInfos(breakInfos: ClassBreakInfo[]): Promise<ClassBreakInfo[] | null | undefined>;
  /**
   * A convenience function used to update the properties a ClassedSizeSlider from the result
   * of the [createClassBreaksRenderer()](https://developers.arcgis.com/javascript/latest/references/core/smartMapping/renderers/size/#createClassBreaksRenderer) method.
   * This method is used to configure an empty ClassedSizeSlider to be used with the layer data, and is useful for cases when the app allows the end user to switch data variables.
   * Note that this method always expects `rendererResult` to be defined for the slider to function, but `histogramResult` is optional.
   *
   * @param rendererResult - The result object from the [createClassBreaksRenderer()](https://developers.arcgis.com/javascript/latest/references/core/smartMapping/renderers/size/#createClassBreaksRenderer)
   *   method.
   * @param histogramResult - The result histogram object from the [histogram()](https://developers.arcgis.com/javascript/latest/references/core/smartMapping/statistics/histogram/#histogram)
   *   method.
   * @example
   * ```js
   * const rendererResult = await sizeRendererCreator.createClassBreaksRenderer(params);
   *
   * featureLayer.renderer = rendererResult.renderer;
   *
   * const histogramResult = await histogram({
   *   ...params,
   *   numBins: 30,
   * });
   *
   * await classedSizeSlider?.updateFromRendererResult(rendererResult, histogramResult);
   * ```
   */
  updateFromRendererResult(rendererResult: ClassBreaksRendererResult, histogramResult?: HistogramResult): Promise<void>;
  /** Emitted when the value of a property is changed. Use this to listen to changes to properties. */
  readonly arcgisPropertyChange: import("@arcgis/lumina").TargetedEvent<this, { name: "breaks" | "histogramConfig" | "max" | "min" | "precision" | "sliderStyle" | "state"; }>;
  /** Emitted when the component associated with a map or scene view is ready to be interacted with. */
  readonly arcgisReady: import("@arcgis/lumina").TargetedEvent<this, void>;
  /** Fires when a user changes the value of a thumb via the arrow keys or by keyboard editing of the label on the slider. */
  readonly arcgisThumbChange: import("@arcgis/lumina").TargetedEvent<this, ThumbChangeEvent>;
  /** Fires when a user drags a thumb on the component. */
  readonly arcgisThumbDrag: import("@arcgis/lumina").TargetedEvent<this, ThumbDragEvent>;
  readonly "@eventTypes": {
    arcgisPropertyChange: ArcgisSliderClassedSizeLegacy["arcgisPropertyChange"]["detail"];
    arcgisReady: ArcgisSliderClassedSizeLegacy["arcgisReady"]["detail"];
    arcgisThumbChange: ArcgisSliderClassedSizeLegacy["arcgisThumbChange"]["detail"];
    arcgisThumbDrag: ArcgisSliderClassedSizeLegacy["arcgisThumbDrag"]["detail"];
  };
}