/// <reference path="../../index.d.ts" />
import type WebMap from "@arcgis/core/WebMap.js";
import type Collection from "@arcgis/core/core/Collection.js";
import type TimeExtent from "@arcgis/core/time/TimeExtent.js";
import type { PublicLitElement as LitElement } from "@arcgis/lumina";
import type { ArcgisReferenceElement, IconName } from "../types.js";
import type { TimeSliderViewModelTriggerActionEvent } from "@arcgis/core/widgets/TimeSlider/TimeSliderViewModel.js";
import type { TimeSliderSettings, Action, TimeSliderMode, TimeSliderState, Stops } from "@arcgis/core/widgets/TimeSlider/types.js";
import type { MapViewOrSceneView } from "@arcgis/core/views/MapViewOrSceneView.js";
import type { Icon } from "@esri/calcite-components/components/calcite-icon";
import type { DateLabelFormatter, TimeSliderLayout } from "@arcgis/core/widgets/TimeSlider.js";
import type { TickConfig } from "@arcgis/core/widgets/Slider/types.js";

/**
 * The Time Slider component simplifies visualization of temporal data in your application.
 *
 * @since 4.28
 */
export abstract class ArcgisTimeSlider extends LitElement {
  /**
   * Defines actions that will appear in a menu when the user clicks the ellipsis button
   * ![timeSlider-actions-menu](https://developers.arcgis.com/javascript/latest/assets/references/core/widgets/timeslider/ellipsis.avif) in the component. The
   * ellipsis button will not display if this property is `null` or if the collection is empty.
   * Each [Action](https://developers.arcgis.com/javascript/latest/references/core/widgets/TimeSlider/types/#Action) is defined with a unique id, a title,
   * and an icon.
   *
   * The [@trigger-action](https://developers.arcgis.com/javascript/latest/references/core/widgets/TimeSlider/#event-trigger-action) event fires each time an action in the menu is clicked. This event
   * can be used to execute custom code such as setting the [timeExtent](https://developers.arcgis.com/javascript/latest/references/core/widgets/TimeSlider/#timeExtent) to a specific date or copying the
   * timeExtent to the browser's clipboard.
   *
   * [![widgets-timeSlider-actions](https://developers.arcgis.com/javascript/latest/assets/references/core/widgets/timeslider/widgets-timeslider-actions.avif)](https://developers.arcgis.com/javascript/latest/sample-code/sandbox/?sample=widgets-timeslider-offset)
   *
   * @since 4.21
   * @see [Sample - TimeSlider with offset](https://developers.arcgis.com/javascript/latest/sample-code/widgets-timeslider-offset/)
   * @example
   * // Create a TimeSlider with two actions to snap the thumb to
   * // two specific time extents.
   * const timeSlider = new TimeSlider({
   *   container: "timeSliderDiv",
   *   fullTimeExtent: {
   *     start: new Date(2011, 0, 1),
   *     end: new Date(2012, 0, 1)
   *   },
   *   mode: "instant",
   *   actions: [
   *     {
   *       id: "quake",
   *       icon: "exclamation-mark-triangle",
   *       title: "Jump to Earthquake"
   *     },
   *     {
   *       id: "quake-plus-one-month",
   *       icon: "organization",
   *       title: "One month later"
   *     }
   *   ]
   * });
   *
   * // listen to timeSlider's trigger-action event
   * // check what action user clicked on and respond accordingly.
   * timeSlider.on("trigger-action", (event) => {
   *   const quake = new Date(Date.UTC(2011, 3, 11, 8, 16, 12));
   *   const oneMonthLater = new Date(quake.getTime()).setMonth(quake.getMonth() + 1);
   *   switch(event.action.id) {
   *     case "quake":
   *       timeSlider.timeExtent = {
   *         start: quake,
   *         end: quake
   *       };
   *       break;
   *     case "quake-plus-one-month":
   *       timeSlider.timeExtent = {
   *         start: oneMonthLater,
   *         end: oneMonthLater
   *       };
   *       break;
   *   }
   * });
   */
  accessor actions: Collection<Action>;
  /**
   * 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-time-slider/#destroy) method when you are done to
   * prevent memory leaks.
   *
   * @default false
   */
  accessor autoDestroyDisabled: boolean;
  /**
   * When true, the component is visually withdrawn and cannot receive user interaction.
   *
   * @default false
   * @example
   * // Create a timeslider widget that is initially disabled.
   * const timeSlider = new TimeSlider({
   *   container: "timeSliderDiv",
   *   fullTimeExtent: {
   *     start: new Date(2000, 5, 1),
   *     end: new Date(2010, 0, 1)
   *   },
   *   disabled: true
   * });
   */
  accessor disabled: boolean;
  /**
   * Lists the specific locations on the timeline where handle(s) will snap to when manipulated.
   *
   * @example
   * timeSlider.effectiveStops.forEach((stop) => {
   *   console.log(stop);
   * });
   */
  get effectiveStops(): Array<Date> | null | undefined;
  /**
   * The temporal extent of the entire slider.
   * It defines the entire time period within which you can visualize
   * your time aware data using the time slider component.
   *
   * @example
   * // Create a new TimeSlider with set dates
   * const timeSlider = new TimeSlider({
   *   container: "timeSliderDiv",
   *   view: view
   * });
   *
   * // wait for the time-aware layer to load
   * layer.when(() => {
   *   // set up time slider properties based on layer timeInfo
   *   timeSlider.fullTimeExtent = layer.timeInfo.fullTimeExtent;
   *   timeSlider.stops = {
   *    interval: layer.timeInfo.interval
   *   };
   * });
   */
  accessor fullTimeExtent: TimeExtent | null | undefined;
  /**
   * Icon which represents the component.
   * Typically used when the component is controlled by another component (e.g. by the Expand component).
   *
   * @default "clock"
   * @since 4.27
   * @see [Calcite Icons](https://developers.arcgis.com/calcite-design-system/icons/)
   */
  get icon(): Icon["icon"];
  set icon(value: IconName);
  /**
   * The component's default label.
   *
   * @since 4.11
   */
  accessor label: string;
  accessor labelFormatFunction: DateLabelFormatter | null | undefined;
  /**
   * Determines the layout used by the TimeSlider component.
   *
   * Possible values are listed below:
   * | Value   | Description |
   * | ---     | --- |
   * | auto    | Automatically uses the "compact" layout when the component width is less than 858 pixels. Otherwise the "wide" layout it used. |
   * | compact | Component elements are oriented vertically. This layout is better suited to narrower widths. |
   * | wide    | Component elements are oriented laterally. This thinner design is better suited to wide applications. |
   *
   * @default "auto"
   * @since 4.16
   * @example timeSlider.layout = "compact";
   */
  accessor layout: TimeSliderLayout;
  /**
   * When `true`, the time slider will play its animation in a loop.
   *
   * @default false
   * @example
   * // Start a time slider animation that advances every second
   * // and restarts when it reaches the end.
   * timeSlider.set({
   *   loop: true,
   *   playRate: 1000
   * });
   * timeSlider.play();
   */
  accessor loop: boolean;
  /**
   * The time slider mode. This property is used for defining if the temporal data will be displayed
   * cumulatively up to a point in time, a single instant in time, or within a time range. See
   * the following table for possible values.
   *
   * Possible Values       | Description   | Example |
   * ----------------------|-------------- | ------- |
   * instant               | The slider will show temporal data that falls on a single instance in time. Set the [timeExtent](https://developers.arcgis.com/javascript/latest/references/core/widgets/TimeSlider/#timeExtent) property's `start` and `end` dates to same date: `{start: sameDate, end: sameDate}` | <img alt="mode-instance" src="https://developers.arcgis.com/javascript/latest/assets/references/core/widgets/timeslider/mode-instance.avif"> |
   * time-window           | The slider will show temporal data that falls within a given time range. This is the default. Set [timeExtent](https://developers.arcgis.com/javascript/latest/references/core/widgets/TimeSlider/#timeExtent) property's `start` and `date` properties to desired dates. | <img alt="mode-instance" src="https://developers.arcgis.com/javascript/latest/assets/references/core/widgets/timeslider/mode-time-window.avif"> |
   * cumulative-from-start | Similar to `time-window` with the start time is always pinned to the start of the slider. Set the [timeExtent](https://developers.arcgis.com/javascript/latest/references/core/widgets/TimeSlider/#timeExtent) property's `start` date to `null` and set `end` date to a desired date: `{start: null, end: date}` | <img alt="mode-instance" src="https://developers.arcgis.com/javascript/latest/assets/references/core/widgets/timeslider/mode-from-start.avif"> |
   * cumulative-from-end   | Also, similar to the `time-window` with the end time pinned to the end of the slider. Set the [timeExtent](https://developers.arcgis.com/javascript/latest/references/core/widgets/TimeSlider/#timeExtent) property's `start` date to a desired date and set `end` date to `null`: `{start: date, end: null}` | <img alt="mode-instance" src="https://developers.arcgis.com/javascript/latest/assets/references/core/widgets/timeslider/mode-from-end.avif"> |
   *
   * @default "time-window"
   * @see [timeExtent](https://developers.arcgis.com/javascript/latest/references/core/widgets/TimeSlider/#timeExtent)
   * @example
   * // Create a single thumbed time slider that includes all historic content.
   * const timeSlider = new TimeSlider({
   *   container: "timeSliderDiv",
   *   view: view,
   *   mode: "cumulative-from-start",
   *   fullTimeExtent: {
   *     start: new Date(2000, 0, 1),
   *     end: new Date(2010, 0, 1)
   *   },
   *   timeExtent: {
   *     start: null,
   *     end: new Date(2001, 0, 1) //end date
   *   }
   * });
   */
  accessor mode: TimeSliderMode;
  /**
   * The time (in milliseconds) between animation steps.
   *
   * > [!WARNING]
   * >
   * > When a [View](https://developers.arcgis.com/javascript/latest/references/core/views/View/) is associated with a TimeSlider and the TimeSlider is playing, the playback will pause before advancing if the View is still updating.
   * > For example, if the `playRate` is set to 1,000 (one second) and the `View` takes 1.5 seconds to render then the TimeSlider thumb(s) will advance every
   * > 1.5 seconds rather than every second.
   *
   * @default 1000
   * @example
   * // Start a time slider animation that advances
   * // ten times a second and stops when it reaches the end.
   * timeSlider.set({
   *   loop: false,
   *   playRate: 100
   * });
   * timeSlider.play();
   */
  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.
   *
   * @default "disabled"
   * @example
   * // Display the current state of the view model.
   * switch (timeSlider.viewModel.state) {
   *   case "disabled":
   *     console.log("The view is not ready or some property are not set.");
   *     break;
   *   case "ready":
   *     console.log("The time slider is ready for use.");
   *     break;
   *   case "playing":
   *     console.log("The time slider is currently animating.");
   *     break;
   * }
   */
  get state(): TimeSliderState;
  /**
   * Defines specific locations on the time slider where thumbs will snap to when manipulated.
   * If unspecified, ten evenly spaced stops will be added.
   *
   * For continuous sliding, set `stops` to `null`:
   * ```js
   * timeSlider.stops = null;
   * ```
   *
   * To define regularly spaced stops, parse an object with `interval` and `timeExtent` properties
   * with types [TimeInterval](https://developers.arcgis.com/javascript/latest/references/core/time/TimeInterval/) and [TimeExtent](https://developers.arcgis.com/javascript/latest/references/core/time/TimeExtent/) respectively.
   * The [timeExtent](https://developers.arcgis.com/javascript/latest/references/core/widgets/TimeSlider/#timeExtent) property is optional and used to confine stops to a certain date range.
   * This property is useful to commence stops on a specific day of the week or month.
   * If a stop definition by interval results in excess of 10,000 stops, then the view model
   * will default to ten evenly spaced stops.
   *
   * ```js
   * // Add yearly intervals starting from the beginning of the TimeSlider.
   * timeSlider.stops = {
   *   interval: {
   *     value: 1,
   *     unit: "years"
   *   }
   * };
   * ```
   * Rather than setting the stops as time intervals, the TimeSlider can be divided into evenly spaced
   * stops using the `count` property. Similar to the previous method, divisions can be confined to a specific date range
   * using the optional timeExtent property.
   * ```js
   * // Add stops at 15 evenly spaced intervals.
   * timeSlider.stops = {
   *   count: 15
   * };
   * ```
   * For irregularly spaced stops, simply assign an array of dates as demonstrated below.
   * ```js
   * // Add nine irregular stops.
   * timeSlider.stops = {
   *   dates: [
   *     new Date(2000, 0, 1), new Date(2001, 3, 8), new Date(2002, 0, 10),
   *     new Date(2003, 12, 8), new Date(2004, 2, 19), new Date(2005, 7, 5),
   *     new Date(2006, 9, 11), new Date(2007, 11, 21), new Date(2008, 1, 10)
   *   ]
   * };
   * ```
   * Lastly, to constrain or offset division by count or interval use the optional timeExtent property.
   * ```js
   * // Add yearly stops from Christmas 2019 to Christmas 2029 only
   * timeSlider.stops = {
   *   interval: {
   *     value: 1,
   *     unit: "years"
   *   },
   *   timeExtent: {
   *     start: new Date(2019, 11, 25),
   *     end: new Date(2029, 11, 25)
   *   }
   * };
   *
   * // Likewise, add stops that represent quarters of 2019 only.
   * timeSlider.stops = {
   *   count: 4,
   *   timeExtent: {
   *     start: new Date(2019, 0, 1),
   *     end: new Date(2020, 0, 1)
   *   }
   * };
   * ```
   *
   * @default { count : 10 }
   */
  accessor stops: Stops | null | undefined;
  /**
   * When set, overrides the default TimeSlider ticks labelling system.
   * Please refer to [TickConfig](https://developers.arcgis.com/javascript/latest/references/core/widgets/Slider/types/#TickConfig) for detailed documentation
   * on how to configure tick placement, style, and behavior.
   *
   * @since 4.16
   * @example
   * // By default in "en-US" the TimeSlider will display ticks with "2010, 2011, 2012, etc".
   * // Overwrite TimeSlider tick configuration so that labels display "'10, '12, '14, etc" in red.
   * const timeSlider = new TimeSlider({
   *   container: "timeSliderDiv",
   *   fullTimeExtent: {
   *     start: new Date(2010, 0, 1),
   *     end: new Date(2020, 0, 1)
   *   },
   *   tickConfigs: [{
   *     mode: "position",
   *     values: [
   *       new Date(2010, 0, 1), new Date(2012, 0, 1), new Date(2014, 0, 1),
   *       new Date(2016, 0, 1), new Date(2018, 0, 1), new Date(2020, 0, 1)
   *     ].map((date) => date.getTime()),
   *     labelsVisible: true,
   *     labelFormatFunction: (value) => {
   *       const date = new Date(value);
   *       return `'${date.getUTCFullYear() - 2000}`;
   *     },
   *     tickCreatedFunction: (value, tickElement, labelElement) => {
   *       tickElement.classList.add("custom-ticks");
   *       labelElement.classList.add("custom-labels");
   *     }
   *   }]
   * };
   * @example
   * // this CSS goes with the snippet above.
   * #timeSlider .custom-ticks {
   *   background-color: red;
   *   width: 1px;
   *   height: 8px;
   * }
   * #timeSlider .custom-labels {
   *   font-family: Georgia, 'Times New Roman', Times, serif;
   *   font-size: 15px;
   *   color: red;
   * }
   */
  accessor tickConfigs: Array<TickConfig> | null | undefined;
  /**
   * The current time extent of the time slider. This property can be watched for
   * updates and used to update the time extent property in queries and/or the layer filters and effects.
   * The following table shows the `timeExtent` values returned for each [mode](https://developers.arcgis.com/javascript/latest/references/core/widgets/TimeSlider/#mode).
   *
   * | Mode    | The timeExtent value |
   * | ------- | -------------------- |
   * | `time-window` | `{start: startDate, end: endDate}` |
   * | `instant` | `{start: sameDate, end: sameDate}` |
   * | `cumulative-from-start` | `{start: null, end: endDate}` |
   * | `cumulative-from-end` | `{start: startDate, end: null}` |
   *
   * @example
   * // Display the time extent to the console whenever it changes.
   * const timeSlider = new TimeSlider({
   *   container: "timeSliderDiv",
   *   mode: "time-window",
   *   fullTimeExtent: {
   *     start: new Date(2019, 2, 3),
   *     end: new Date(2019, 2, 5)
   *   },
   *   timeExtent: {
   *     start: new Date(2019, 2, 1),
   *     end: new Date(2019, 2, 28)
   *   }
   * });
   *
   * reactiveUtils.watch(
   *   () => timeSlider.timeExtent,
   *   (timeExtent) => {
   *     console.log("Time extent now starts at", timeExtent.start, "and finishes at:", timeExtent.end);
   *   }
   * );
   */
  accessor timeExtent: TimeExtent | null | undefined;
  /**
   * Shows/hides time in the display.
   *
   * @default false
   * @example
   * // For time sliders with a small time extent it may be useful to display times as shown below.
   * const timeSlider = new TimeSlider({
   *   container: "timeSliderDiv",
   *   mode: "time-window",
   *   timeVisible: true,
   *   fullTimeExtent: {
   *     start: new Date(2019, 2, 3),
   *     end: new Date(2019, 2, 5)
   *   },
   *   timeExtent: {
   *     start: new Date(2019, 2, 1),
   *     end: new Date(2019, 2, 28)
   *   }
   * });
   */
  accessor timeVisible: boolean;
  /**
   * Dates and times displayed in the component will be displayed in this time zone. By default this time zone is
   * inherited from [MapView#timeZone](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/#timeZone). When a MapView is not associated with the component
   * then the property will fallback to the `system` time zone.
   *
   * **Possible Values**
   *
   * Value | Description |
   * ----- | ----------- |
   * system  | Dates and times will be displayed in the timezone of the device or browser.
   * unknown | Dates and time are not adjusted for any timezone. [TimeSlider](https://developers.arcgis.com/javascript/latest/references/core/widgets/TimeSlider/) will be disabled.
   * Specified IANA timezone | Dates and times will be displayed in the specified IANA time zone. See [wikipedia - List of tz database time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
   *
   * @since 4.28
   */
  accessor timeZone: string;
  /**
   * The view associated with the component. 
   *   > **Note:** The recommended approach is to fully migrate applications to use map and scene components and avoid using MapView and SceneView directly. However, if you are migrating a large application from widgets to components, you might prefer a more gradual transition. To support this use case, the SDK includes this `view` property which connects a component to a MapView or SceneView. Ultimately, once migration is complete, the arcgis-time-slider component will be associated with a map or scene component rather than using the `view` property.
   *
   * @example
   * ```js
   * // Create and then add a TimeSlider component and then listen to changes in the View's time extent.
   * const timeSlider = new TimeSlider({
   *   container: "timeSliderDiv",
   *   view: view,
   *   mode: "instant",
   *   fullTimeExtent: {
   *     start: new Date(2000, 0, 1),
   *     end: new Date(2010, 0, 1)
   *   },
   *   timeExtent: {
   *     start: new Date(2000, 0, 1),
   *     end: new Date(2000, 0, 1)
   *   }
   * });
   * view.ui.add(timeSlider, "top-left");
   *
   * reactiveUtils.watch(
   *   () => view.timeExtent,
   *   (timeExtent) => {
   *     console.log("New view time is: ", timeExtent.start);
   *   }
   * );
   * ```
   */
  accessor view: MapViewOrSceneView | null | undefined;
  /** @param settings */
  applyTimeSliderSettings(settings: TimeSliderSettings): Promise<void>;
  /** Permanently destroy the component. */
  destroy(): Promise<void>;
  next(): Promise<void>;
  play(): Promise<void>;
  previous(): Promise<void>;
  stop(): Promise<void>;
  /** @param webmap */
  updateWebDocument(webmap: WebMap): Promise<void>;
  "@setterTypes": {
    icon?: IconName;
  };
  /** 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: "effectiveStops" | "fullTimeExtent" | "timeExtent" | "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>;
  /** Emitted when an action is triggered on the component. */
  readonly arcgisTriggerAction: import("@arcgis/lumina").TargetedEvent<this, TimeSliderViewModelTriggerActionEvent>;
  readonly "@eventTypes": {
    arcgisPropertyChange: ArcgisTimeSlider["arcgisPropertyChange"]["detail"];
    arcgisReady: ArcgisTimeSlider["arcgisReady"]["detail"];
    arcgisTriggerAction: ArcgisTimeSlider["arcgisTriggerAction"]["detail"];
  };
}