import type GeolocationPositioning from "../support/GeolocationPositioning.js";
import type { GeolocationPositioningProperties } from "../support/GeolocationPositioning.js";

export interface LocateViewModelProperties extends GeolocationPositioningProperties, Partial<Pick<LocateViewModel, "error" | "popupEnabled">> {}

export type LocateViewModelState = "disabled" | "ready" | "locating" | "feature-unsupported" | "error";

export interface LocateViewModelEvents {
  /**
   * Fires after the `locate()` method is called and succeeds.
   *
   * @see [locate()](https://developers.arcgis.com/javascript/latest/references/core/widgets/Locate/LocateViewModel/#locate)
   * @example
   * locateBtn.on("locate", ({ position }) => {
   *   const { longitude, latitude } = position.coords;
   *   console.log(`lat: ${latitude.toFixed(4)}, long: ${longitude.toFixed(4)}`);
   * })
   */
  locate: LocateViewModelLocateEvent;
  /**
   * Fires after the [Locate.locate()](https://developers.arcgis.com/javascript/latest/references/core/widgets/Locate/#locate) method is called and fails.
   *
   * @see [locate()](https://developers.arcgis.com/javascript/latest/references/core/widgets/Locate/LocateViewModel/#locate)
   */
  "locate-error": LocateViewModelLocateErrorEvent;
}

export interface LocateViewModelLocateEvent {
  /** Position returned from the [Geolocation API](https://developers.arcgis.com/javascript/latest/references/core/widgets/Locate/#geolocationOptions). */
  position: GeolocationPosition;
}

export interface LocateViewModelLocateErrorEvent {
  /** The Error object that occurred while locating. */
  error: GeolocationPositionError | Error;
}

/**
 * Provides the logic for the [Locate](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-locate/) component and [Locate](https://developers.arcgis.com/javascript/latest/references/core/widgets/Locate/) widget, which
 * animates the [View](https://developers.arcgis.com/javascript/latest/references/core/views/View/)
 * to the user's current location.
 *
 * > [!WARNING]
 * >
 * > The ([geolocation](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/Using_geolocation)) functionality 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)
 * > (currently Chrome and Firefox).
 * >
 * > As of version 4.2, the Locate Button no longer displays in non-secure web apps. At version
 * > [4.1](https://blogs.esri.com/esri/arcgis/2016/04/14/increased-web-api-security-in-google-chrome/)
 * > this only applied to Google Chrome.
 *
 * @deprecated since version 4.34. 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 [Locate](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-locate/) component
 * @see [Locate](https://developers.arcgis.com/javascript/latest/references/core/widgets/Locate/) widget - _Deprecated since 4.32. Use the [Locate component](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-locate/) instead._
 * @see [Programming patterns: Widget viewModel pattern](https://developers.arcgis.com/javascript/latest/programming-patterns/#widget-viewmodel-pattern)
 * @example
 * let locateWidget = new Locate({
 *   viewModel: { // autocasts as new LocateViewModel()
 *     view: view   // attaches the Locate button to the view
 *   },
 *   container: "locateDiv"
 * });
 */
export default class LocateViewModel extends GeolocationPositioning {
  /**
   * @deprecated
   * Do not directly reference this property.
   * Use EventNames and EventTypes helpers from \@arcgis/core/Evented
   */
  "@eventTypes": LocateViewModelEvents;
  constructor(properties?: LocateViewModelProperties);
  /**
   * Error that caused the last [locate-error](https://developers.arcgis.com/javascript/latest/references/core/widgets/Locate/LocateViewModel/#event:locate-error) event to fire.
   *
   * @since 4.29
   * @example
   * if(locate.viewModel.state === 'error')
   *   console.error(locate.viewModel.error);
   */
  accessor error: GeolocationPositionError | Error | null | undefined;
  /**
   * Indicates whether to display the [Popup](https://developers.arcgis.com/javascript/latest/references/core/widgets/Popup/) of the result graphic from the
   * [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;
  /**
   * The current state of the widget.
   *
   * @default "disabled"
   */
  get state(): LocateViewModelState;
  /**
   * 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/LocateViewModel/#event-locate).
   * @example
   * let locateWidget = new Locate({
   *   viewModel: { // autocasts as new LocateViewModel()
   *     view: view
   *   },
   *   container: "locateDiv"
   * });
   *
   * locateWidget.locate().then(function(){
   *   // Fires after the user's location has been found
   * });
   */
  locate(): Promise<GeolocationPosition | null>;
}