/// <reference path="../../index.d.ts" />
import type { PublicLitElement as LitElement } from "@arcgis/lumina";
import type { ArcgisReferenceElement, IconName } from "../types.js";
import type { AnimateEvent, ArcgisValuePickerSubcomponent, Layout } from "./types.js";
import type { T9nMeta } from "@arcgis/lumina/controllers";

/**
 * The Value Picker component allows users to step or play through an iterable set of data. The component alone acts as a shell, consisting
 * of a play/pause button, a next button, a previous button, and a slot for adding a component to Value Picker. Value Picker is not associated with a
 * [View](https://developers.arcgis.com/javascript/latest/references/core/views/View/) nor does it require that the dataset adheres to a specific structure
 * for it to function. The [arcgis-value-picker-label](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker-label/), [arcgis-value-picker-slider](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker-slider/),
 * [arcgis-value-picker-combobox](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker-combobox/), and [arcgis-value-picker-collection](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker-collection/) components provide the user with a few different options
 * for placing their data into a Value Picker with minimal configuration. Value Picker handles the different shapes of these components automatically by asserting
 * that all slotted components will extend the
 * [ArcgisValuePickerSubcomponent](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker/types/#ArcgisValuePickerSubcomponent)
 * interface, which allows Value picker to send and receive generic sets of instructions that are interpreted by the slotted component.
 *
 * ### Configuring Value Picker
 *
 * #### Configuring Value Picker without slotted components
 *
 * ![value-picker-nodata](https://developers.arcgis.com/javascript/latest/assets/references/components/value-picker/value-picker-nodata.avif)
 *
 * ```html
 * <arcgis-map itemId="462c629e8e604c15baf45627c4f337d6">
 *   <arcgis-value-picker slot="top-right"></arcgis-value-picker>
 * </arcgis-map>
 * ```
 *
 * If a user wishes to use Value Picker with a component or dataset that can't be accurately represented by the slottable components, the component may be placed
 * adjacent to the empty Value Picker, and events fired by Value Picker can be used to orchestrate the behavior of the adjacent component.
 * For example, when the user clicks the play button, Value Picker will emit [@arcgisAnimate](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker/#event-arcgisAnimate) each time
 * [playRate](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker/#playRate) ms have elapsed since the button was clicked, which the user could listen to and iterate the index of
 * their dataset on an interval as a result.
 *
 * ```js
 * const valuePicker = document.querySelector("arcgis-value-picker");
 * const basemapGallery = document.querySelector("arcgis-basemap-gallery");
 *
 * const basemaps = new Collection([
 *   Basemap.fromId("topo-vector"),
 *   Basemap.fromId("hybrid"),
 *   Basemap.fromId("streets"),
 *   Basemap.fromId("satellite"),
 *   Basemap.fromId("oceans"),
 * ]);
 *
 * basemapGallery.source = new LocalBasemapsSource({ basemaps });
 * basemapGallery.activeBasemap = basemaps.getItemAt(0);
 *
 * valuePicker.addEventListener("arcgisAnimate", () => {
 *   const currentIndex = basemaps.indexOf(basemapGallery.activeBasemap);
 *   basemapGallery.activeBasemap = basemaps.getItemAt(currentIndex + 1);
 * });
 * ```
 *
 * #### Configuring Value Picker with slotted components
 *
 * A single component may be placed into the Value Picker slot by placing one element inside of the other:
 *
 * ```html
 * <arcgis-value-picker>
 *   <arcgis-value-picker-slider></arcgis-value-picker-slider>
 * </arcgis-value-picker>
 * ```
 *
 * #### 1. Using a label component to step through a list of items
 *
 * Consider using the [arcgis-value-picker-label](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker-label/) component to step through a small, fixed list of predefined values. This component provides a strict
 * interface that steps back and forth, so it's a good option for temporal data, or data that shows progression dependent on the element's position in the list.
 *
 * ![value-picker-label](https://developers.arcgis.com/javascript/latest/assets/references/components/value-picker/value-picker-label.avif)
 *
 * ```js
 * const mapElement = document.querySelector("arcgis-map");
 * const valuePickerLabel = document.querySelector("arcgis-value-picker-label");
 *
 * const labelItems = [
 *   { value: "2017", label: "Tree cover in 2017" },
 *   { value: "2018", label: "Tree cover in 2018" },
 *   { value: "2019", label: "Tree cover in 2019" },
 *   { value: "2020", label: "Tree cover in 2020" },
 *   { value: "2021", label: "Tree cover in 2021" }
 * ];
 *
 * valuePickerLabel.items = labelItems;
 *
 * valuePickerLabel.currentValue = labelItems[0];
 * ```
 *
 * The user's interaction can be handled by monitoring the [arcgis-value-picker-label.currentValue](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker-label/#currentValue) property.
 *
 * ```js
 * valuePickerLabel.addEventListener("arcgisPropertyChange", () => {
 *   const year = Number(valuePickerLabel.currentValue.value);
 *   mapElement.view.timeExtent = {
 *     start: new Date(year, 0, 1),
 *     end: new Date(year + 1, 0, 1),
 *   };
 *   console.log("The current year is: ", valuePickerLabel.currentValue.value);
 * });
 * ```
 *
 * #### 2. Using a slider component to traverse a list of items
 *
 * Consider using the [arcgis-value-picker-slider](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker-slider/) component to quickly traverse through a set of data
 * that can be represented along a fixed numeric range. This is a good option for sets of elements spaced along an interval, or mutating
 * a continuous parameter such as layer opacity.
 *
 * ![value-picker-slider](https://developers.arcgis.com/javascript/latest/assets/references/components/value-picker/value-picker-slider.avif)
 *
 * ```js
 * const valuePickerSlider = document.querySelector("arcgis-value-picker-slider");
 *
 * valuePickerSlider.steps = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
 * valuePickerSlider.labels = [0, 20, 40, 60, 80, 100];
 * valuePickerSlider.majorTicks = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
 * valuePickerSlider.minorTicks = [5, 15, 25, 35, 45, 55, 65, 75, 85, 95];
 * valuePickerSlider.currentValue = 100;
 * valuePickerSlider.labelFormatter = (value) => `${value}%`;
 * ```
 *
 * The user's interaction can be handled by monitoring the [arcgis-value-picker-slider.currentValue](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker-slider/#currentValue) property.
 *
 * ```js
 * valuePickerSlider.addEventListener("arcgisPropertyChange", () => {
 *   layer.opacity = valuePickerSlider.currentValue / 100;
 *   console.log("The current layer opacity is: ", valuePickerSlider.currentValue / 100);
 * });
 * ```
 *
 * Note that [arcgis-value-picker-slider.labels](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker-slider/#labels), [arcgis-value-picker-slider.majorTicks](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker-slider/#majorTicks), and [arcgis-value-picker-slider.minorTicks](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker-slider/#minorTicks)
 * are all independent of each other and optional.
 *
 * #### 3. Using a combobox component to select from a list of items
 *
 * Consider using the [arcgis-value-picker-combobox](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker-combobox/) component to step through a longer list of items that cannot be clicked through
 * one by one. The combobox component allows the user to open the list as a dropdown and make a selection, or narrow the size of the list by searching for an element or keyword.
 *
 * ![value-picker-combobox](https://developers.arcgis.com/javascript/latest/assets/references/components/value-picker/value-picker-combobox.avif)
 *
 * ```js
 * const valuePickerCombobox = document.querySelector("arcgis-value-picker-combobox");
 *
 * const comboboxItems = [
 *   { value: "Bare", label: "Isolate Bare Ground Areas" },
 *   { value: "Built", label: "Isolate Built Areas" },
 *   { value: "Trees", label: "Isolate Trees" },
 *   { value: "Water", label: "Isolate Water Areas" },
 *   { value: "Crops", label: "Isolate Crop Areas" },
 * ];
 *
 * valuePickerCombobox.items = comboboxItems;
 *
 * valuePickerCombobox.currentValue = comboboxItems[0];
 * ```
 *
 * The user's interaction can be handled by monitoring the [arcgis-value-picker-combobox.currentValue](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker-combobox/#currentValue) property.
 *
 * ```js
 * valuePickerCombobox.addEventListener("arcgisPropertyChange", () => {
 *   layer.rasterFunction = {
 *     functionName: valuePickerCombobox.currentValue.value,
 *   };
 *   console.log("The current land cover category is: ", valuePickerCombobox.currentValue.value);
 * });
 * ```
 *
 * #### 4. Using a collection component to step through an arbitrary set of data
 *
 * Consider using the [arcgis-value-picker-collection](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker-collection/) component when a visual representation for the dataset is not necessary.
 * This is also a good option for datasets already in the form of a [Collection](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/).
 *
 * ![value-picker-collection](https://developers.arcgis.com/javascript/latest/assets/references/components/value-picker/value-picker-collection.avif)
 *
 * ```js
 * const Collection = (await import("@arcgis/core/core/Collection.js")).default;
 *
 * const mapElement = document.querySelector("arcgis-map");
 * const valuePickerCollection = document.querySelector("arcgis-value-picker-collection");
 *
 * const basemapCollection = new Collection(["topo-vector", "streets", "osm"]);
 *
 * valuePickerCollection.items = basemapCollection;
 *
 * valuePickerCollection.currentValue = "topo-vector";
 * ```
 *
 * The user's interaction can be handled by monitoring the [arcgis-value-picker-collection.currentValue](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker-collection/#currentValue) property.
 *
 * ```js
 * valuePickerCollection.addEventListener("arcgisPropertyChange", () => {
 *   mapElement.basemap = valuePickerCollection.currentValue;
 *   console.log("The current basemap is: ", valuePickerCollection.currentValue);
 * });
 * ```
 *
 * @slot  - Default slot for adding a component to value-picker. User is responsible for positioning the content via CSS.
 * @internal
 * @since 5.1
 */
export abstract class ArcgisValuePicker 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-value-picker/#destroy) method when you are done to
   * prevent memory leaks.
   *
   * @default false
   */
  accessor autoDestroyDisabled: boolean;
  /**
   * An optional caption that renders under the Value Picker component to give context for the user. This is particularly
   * useful when an application is using more than one Value Picker instance.
   *
   * @default ""
   */
  accessor caption: string | undefined;
  /**
   * When true, the component is visually withdrawn and cannot be interacted with. If the slotted component also has a `disabled` property,
   * it will be kept in sync with this property.
   *
   * @default false
   */
  accessor disabled: boolean;
  /**
   * When set to `true`, the next button is not displayed.
   *
   * @default false
   */
  accessor hideNextButton: boolean;
  /**
   * When set to `true`, the play/pause button is not displayed.
   *
   * @default false
   */
  accessor hidePlayButton: boolean;
  /**
   * When set to `true`, the previous button is not displayed.
   *
   * @default false
   */
  accessor hidePreviousButton: boolean;
  /**
   * Icon which represents the component.
   * Typically used when the component is controlled by another component (e.g. by the Expand component).
   *
   * @default "list-rectangle"
   * @see [Calcite Icons](https://developers.arcgis.com/calcite-design-system/icons/)
   */
  accessor icon: IconName;
  /**
   * The component's default label.
   *
   * @default ""
   */
  accessor label: string | undefined;
  /**
   * Indicates the axis that the Value Picker buttons should be oriented along.
   *
   * Horizontal layouts are best for wider components that don't require a lot of vertical space,
   * or components that iterate from left to right over a dataset. Some examples of these are
   * horizontal sliders, collapsable dropdowns, or label components.
   *
   * Vertical layouts are best for taller components or components that should iterate vertically.
   * Some examples include vertical sliders or list components that require a larger space to allow the user to scroll through the list.
   *
   * @default "horizontal"
   */
  accessor layout: Layout;
  /**
   * When set to `true`, playback will restart from the first element of the slotted component's dataset
   * once it reaches the end. Note that this will not allow the Value Picker buttons to be used to manually loop back to the first element.
   *
   * @default false
   */
  accessor loop: boolean;
  /** @internal */
  protected messages: {
      componentLabel: string;
      next: string;
      previous: string;
      play: string;
      pause: string;
  } & T9nMeta<{
      componentLabel: string;
      next: string;
      previous: string;
      play: string;
      pause: string;
  }>;
  /**
   * Specifies the interval, in milliseconds, on which the component will call `step("next")` on the slotted component.
   *
   * @default 1000
   */
  accessor playRate: 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;
  /** The current state of the component. */
  get state(): "playing" | "ready";
  /** Permanently destroy the component. */
  destroy(): Promise<void>;
  /**
   * Selects the next index from the slotted component's dataset.
   *
   * @example
   * ```js
   * const valuePicker = document.querySelector("arcgis-value-picker");
   * const valuePickerSlider = document.querySelector("arcgis-value-picker-slider");
   *
   * valuePickerSlider.steps = [1, 2, 3, 4, 5];
   * valuePickerSlider.currentValue = 1;
   *
   * console.log(`Current value: ${valuePickerSlider.currentValue}`); // "Current value: 1"
   * valuePicker.next();
   * console.log(`Current value: ${valuePickerSlider.currentValue}`); // "Current value: 2"
   * ```
   */
  next(): void;
  /** Stops the component from playing. */
  pause(): void;
  /**
   * Start playing. Value Picker will call `step("next")` on the slotted component at an interval defined by [playRate](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker/#playRate).
   *
   * @example
   * ```js
   * // Start a continuously looping ValuePicker.
   * const valuePicker = document.querySelector("arcgis-value-picker");
   * const valuePickerSlider = document.querySelector("arcgis-value-picker-slider");
   *
   * valuePickerSlider.steps = [1, 2, 3];
   * valuePickerSlider.currentValue = 1;
   * valuePicker.loop = true;
   *
   * valuePickerSlider.addEventListener("arcgisPropertyChange", () => {
   *   console.log(valuePickerSlider.currentValue);
   * });
   *
   * valuePicker.play();
   * // output: 1, 2, 3, 1, 2, 3, 1...
   * ```
   */
  play(): void;
  /**
   * Selects the previous index from the slotted component's dataset.
   *
   * @example
   * ```js
   * const valuePicker = document.querySelector("arcgis-value-picker");
   * const valuePickerSlider = document.querySelector("arcgis-value-picker-slider");
   *
   * valuePickerSlider.steps = [1, 2, 3, 4, 5];
   * valuePickerSlider.currentValue = 3;
   *
   * console.log(`Current value: ${valuePickerSlider.currentValue}`); // "Current value: 3"
   * valuePicker.previous();
   * console.log(`Current value: ${valuePickerSlider.currentValue}`); // "Current value: 2"
   * ```
   */
  previous(): void;
  /**
   * Fires on each playback tick after the user presses the play button. The event payload contains `{ first: boolean }` and fires for
   * the first time after [playRate](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker/#playRate) ms have elapsed since the user pressed the play button. Users should
   * listen to this event to manually iterate an external dataset on an interval.
   */
  readonly arcgisAnimate: import("@arcgis/lumina").TargetedEvent<this, AnimateEvent>;
  /** Fires when the Value Picker's next button is pressed or when the [next()](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker/#next) method is invoked. */
  readonly arcgisNext: import("@arcgis/lumina").TargetedEvent<this, void>;
  /** Fires when the Value Picker's pause button is pressed or when the [pause()](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker/#pause) method is invoked. */
  readonly arcgisPause: import("@arcgis/lumina").TargetedEvent<this, void>;
  /** Fires when the Value Picker's play button is pressed or when the [play()](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker/#play) method is invoked. */
  readonly arcgisPlay: import("@arcgis/lumina").TargetedEvent<this, void>;
  /** Fires when the Value Picker's previous button is pressed or when the [previous()](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-value-picker/#previous) method is invoked. */
  readonly arcgisPrevious: import("@arcgis/lumina").TargetedEvent<this, 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: "layout" | "loop" | "playRate" | "state"; }>;
  /** Fires when the contents of Value Picker's slot changes. */
  readonly arcgisSlottedElementChange: import("@arcgis/lumina").TargetedEvent<this, { slottedElement: ArcgisValuePickerSubcomponent | undefined; }>;
  readonly "@eventTypes": {
    arcgisAnimate: ArcgisValuePicker["arcgisAnimate"]["detail"];
    arcgisNext: ArcgisValuePicker["arcgisNext"]["detail"];
    arcgisPause: ArcgisValuePicker["arcgisPause"]["detail"];
    arcgisPlay: ArcgisValuePicker["arcgisPlay"]["detail"];
    arcgisPrevious: ArcgisValuePicker["arcgisPrevious"]["detail"];
    arcgisPropertyChange: ArcgisValuePicker["arcgisPropertyChange"]["detail"];
    arcgisSlottedElementChange: ArcgisValuePicker["arcgisSlottedElementChange"]["detail"];
  };
}