import type Graphic from "../Graphic.js";
import type Widget from "./Widget.js";
import type LocateViewModel from "./Locate/LocateViewModel.js";
import type { Icon } from "@esri/calcite-components/components/calcite-icon";
import type { MapViewOrSceneView } from "../views/MapViewOrSceneView.js";
import type { WidgetProperties } from "./Widget.js";
import type { LocateViewModelEvents, LocateViewModelProperties } from "./Locate/LocateViewModel.js";
import type { GoToOverride } from "./support/types.js";
import type { GraphicProperties } from "../Graphic.js";

export interface LocateProperties extends WidgetProperties, Partial<Pick<Locate, "geolocationOptions" | "goToLocationEnabled" | "goToOverride" | "popupEnabled" | "scale" | "view">> {
  /**
   * The graphic used to show the user's location on the map.
   *
   * @example
   * let locateWidget = new Locate({
   *   viewModel: { // autocasts as new LocateViewModel()
   *     view: view,  // assigns the locate widget to a view
   *     graphic: new Graphic({
   *       symbol: { type: "simple-marker" }  // overwrites the default symbol used for the
   *       // graphic placed at the location of the user when found
   *     })
   *   }
   * });
   */
  graphic?: GraphicProperties;
  /**
   * Icon displayed in the widget's button.
   *
   * @default "compass"
   * @since 4.28
   * @see [Calcite Icon Search](https://developers.arcgis.com/calcite-design-system/icons/)
   * @see [Calcite Icon Search](https://developers.arcgis.com/calcite-design-system/icons/)
   */
  icon?: Icon["icon"] | null;
  /**
   * The widget's default label.
   *
   * @since 4.8
   */
  label?: string | null;
  /**
   * The view model for this widget. This is a class that contains all the logic
   * (properties and methods) that controls this widget's behavior. See the
   * [LocateViewModel](https://developers.arcgis.com/javascript/latest/references/core/widgets/Locate/LocateViewModel/) class to access
   * all properties and methods on the widget.
   */
  viewModel?: LocateViewModelProperties;
}

export interface LocateEvents extends LocateViewModelEvents {}

/**
 * Provides a simple widget that animates the [View](https://developers.arcgis.com/javascript/latest/references/core/views/View/)
 * to the user's current location. The view rotates according to the direction
 * where the tracked device is heading towards. By default the widget looks like the following:
 *
 * ![locate-button](https://developers.arcgis.com/javascript/latest/assets/references/core/widgets/widgets-locate.png)
 *
 * The default heading symbol will display if the device has a speed greater than zero and the browser provides heading information:
 *
 * ![heading-indicator](https://developers.arcgis.com/javascript/latest/assets/references/core/widgets/widgets-track-heading.png)
 *
 * > [!WARNING]
 * >
 * > The Locate widget is not supported on insecure origins.
 * > To use it, switch your application to a secure origin, such as HTTPS.
 * > Note that localhost is considered "potentially secure" and can be used for easy testing in browsers that supports
 * > [Window.isSecureContext](https://developer.mozilla.org/en-US/docs/Web/API/isSecureContext#browser_compatibility).
 * >
 * > **Known Limitation**
 * >
 * > The Locate widget does not work concurrently with the [Track](https://developers.arcgis.com/javascript/latest/references/core/widgets/Track/) widget.
 * > Only one of the widgets can be used at a time.
 *
 * You can use the view's [DefaultUI](https://developers.arcgis.com/javascript/latest/references/core/views/ui/DefaultUI/) to add widgets
 * to the view's user interface via the `ui` property on the view.
 * The snippet below demonstrates this.
 *
 * @deprecated since version 4.32. Use the [Locate component](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-locate/) instead. For information on widget deprecation, read about [Esri's move to web components](https://developers.arcgis.com/javascript/latest/components-transition-plan/).
 * @since 4.0
 * @see [LocateViewModel](https://developers.arcgis.com/javascript/latest/references/core/widgets/Locate/LocateViewModel/)
 * @see [DefaultUI](https://developers.arcgis.com/javascript/latest/references/core/views/ui/DefaultUI/)
 * @example
 * let locateWidget = new Locate({
 *   view: view,   // Attaches the Locate button to the view
 *   graphic: new Graphic({
 *     symbol: { type: "simple-marker" }  // overwrites the default symbol used for the
 *     // graphic placed at the location of the user when found
 *   })
 * });
 *
 * view.ui.add(locateWidget, "top-right");
 */
export default class Locate extends Widget {
  /**
   * @deprecated
   * Do not directly reference this property.
   * Use EventNames and EventTypes helpers from \@arcgis/core/Evented
   */
  "@eventTypes": LocateEvents;
  /**
   * @example
   * // typical usage
   * let locate = new Locate({
   *   view: view
   * });
   */
  constructor(properties?: LocateProperties);
  /**
   * The browser's Geolocation API Position options for locating. Refer to
   * [Geolocation API Specification](https://www.w3.org/TR/geolocation-API/#position-options)
   * for details.
   */
  accessor geolocationOptions: PositionOptions | null | undefined;
  /**
   * Indicates whether the widget should navigate the view to the position and scale of the geolocated result.
   *
   * @default true
   */
  accessor goToLocationEnabled: boolean;
  /**
   * This function provides the ability to override either the
   * [MapView goTo()](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/#goTo) or
   * [SceneView goTo()](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/#goTo) methods.
   *
   * @since 4.8
   * @see [MapView.goTo()](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/#goTo)
   * @see [SceneView.goTo()](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/#goTo)
   * @example
   * // The following snippet uses Search but can be applied to any
   * // widgets that support the goToOverride property.
   * search.goToOverride = function(view, goToParams) {
   *   goToParams.options = {
   *     duration: updatedDuration
   *   };
   *   return view.goTo(goToParams.target, goToParams.options);
   * };
   */
  accessor goToOverride: GoToOverride | null | undefined;
  /**
   * The graphic used to show the user's location on the map.
   *
   * @example
   * let locateWidget = new Locate({
   *   viewModel: { // autocasts as new LocateViewModel()
   *     view: view,  // assigns the locate widget to a view
   *     graphic: new Graphic({
   *       symbol: { type: "simple-marker" }  // overwrites the default symbol used for the
   *       // graphic placed at the location of the user when found
   *     })
   *   }
   * });
   */
  get graphic(): Graphic;
  set graphic(value: GraphicProperties);
  /**
   * Icon displayed in the widget's button.
   *
   * @default "compass"
   * @since 4.28
   * @see [Calcite Icon Search](https://developers.arcgis.com/calcite-design-system/icons/)
   * @see [Calcite Icon Search](https://developers.arcgis.com/calcite-design-system/icons/)
   */
  get icon(): Icon["icon"];
  set icon(value: Icon["icon"] | null | undefined);
  /**
   * The widget's default label.
   *
   * @since 4.8
   */
  get label(): string;
  set label(value: string | null | undefined);
  /**
   * Indicates whether to display the [Popup](https://developers.arcgis.com/javascript/latest/references/core/widgets/Popup/) of the result graphic from the
   * [LocateViewModel.locate()](https://developers.arcgis.com/javascript/latest/references/core/widgets/Locate/LocateViewModel/#locate) method.
   *
   * @default true
   * @since 4.19
   * @see [Search.popupEnabled](https://developers.arcgis.com/javascript/latest/references/core/widgets/Search/#popupEnabled)
   */
  accessor popupEnabled: boolean;
  /**
   * Indicates the scale to set on the view when navigating to the position of the geolocated
   * result once a location is returned from the [locate](https://developers.arcgis.com/javascript/latest/references/core/widgets/Locate/#event-locate) event.
   * If a scale value is not explicitly set, then the view will navigate to a default scale of `2500`.
   * For 2D views the value should be within the [effectiveMinScale](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/#constraints)
   * and [effectiveMaxScale](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/#constraints).
   *
   * @since 4.7
   * @example
   * reactiveUtils.watch(
   *   () => mapView.scale,
   *   (currentScale) => console.log("scale: %s", currentScale)
   * );
   *
   * mapView.when(function(){
   *   // Create an instance of the Locate widget
   *   let locateWidget = new Locate({
   *     view: mapView,
   *     scale: 5000
   *   });
   *
   *   // and add it to the view's UI
   *   mapView.ui.add(locateWidget, "top-left");
   *
   *   locateWidget.locate();
   *
   *   locateWidget.on("locate", function(locateEvent){
   *     console.log(locateEvent);
   *     console.log("locate: %s", mapView.scale);
   *   })
   * });
   */
  accessor scale: number | null | undefined;
  /** A reference to the [MapView](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/) or [SceneView](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/). Set this to link the widget to a specific view. */
  accessor view: MapViewOrSceneView | null | undefined;
  /**
   * The view model for this widget. This is a class that contains all the logic
   * (properties and methods) that controls this widget's behavior. See the
   * [LocateViewModel](https://developers.arcgis.com/javascript/latest/references/core/widgets/Locate/LocateViewModel/) class to access
   * all properties and methods on the widget.
   */
  get viewModel(): LocateViewModel;
  set viewModel(value: LocateViewModelProperties);
  /**
   * This function provides the ability to interrupt and cancel the process of
   * programmatically obtaining the location of the user's device.
   *
   * @since 4.9
   */
  cancelLocate(): void;
  /**
   * Animates the view to the user's location.
   *
   * @returns Resolves to an object with the same specification as the event
   *                   object defined in the [locate event](https://developers.arcgis.com/javascript/latest/references/core/widgets/Locate/#event-locate).
   * @example
   * let locateWidget = new Locate({
   *   view: view,
   *   container: "locateDiv"
   * });
   *
   * locateWidget.locate().then(function(){
   *   // Fires after the user's location has been found
   * });
   */
  locate(): Promise<GeolocationPosition | null>;
}