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

export interface TrackViewModelProperties extends GeolocationPositioningProperties, Partial<Pick<TrackViewModel, "error" | "positionFilterFunction" | "rotationEnabled">> {}

export type TrackViewModelState = "error" | "disabled" | "ready" | "waiting" | "tracking" | "feature-unsupported";

export interface TrackViewModelEvents {
  /**
   * Fires after the [Track.start()](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Track.html#start) method is called and a position is found.
   *
   * @example
   * track.on("track", ({ position }) => {
   *   const { longitude, latitude } = position.coords;
   *   console.log("Track", `${longitude.toFixed(4)}, ${latitude.toFixed(4)}`);
   * });
   */
  track: TrackViewModelTrackEvent;
  /** Fires after the [Track.start()](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Track.html#start) method is called and an error is returned. */
  "track-error": TrackViewModelTrackErrorEvent;
}

export interface TrackViewModelTrackEvent {
  /** Geolocation coordinates returned from the [Geolocation API](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Track.html#geolocationOptions). */
  position: GeolocationPosition;
}

export interface TrackViewModelTrackErrorEvent {
  /** The Error object returned if an error occurred while tracking. */
  error: GeolocationPositionError | Error;
}

/**
 * Provides the logic for the [Track](https://developers.arcgis.com/javascript/latest/references/map-components/arcgis-track/) component and [Track](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Track.html) widget, which
 * animates the [View](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-View.html)
 * to the user's location when clicked and tracks it as the location is updated.
 *
 * > [!WARNING]
 * >
 * > The Track widget is only available in [secure contexts](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts), such as HTTPS.
 * > Note that localhost is considered "potentially secure" and can be used for easy testing in browsers that support
 * > [Window.isSecureContext](https://developer.mozilla.org/en-US/docs/Web/API/isSecureContext#browser_compatibility).
 * >
 * > For additional information regarding this, visit the ArcGIS blog,
 * > [Increased web API security in Google Chrome](https://blogs.esri.com/esri/arcgis/2016/04/14/increased-web-api-security-in-google-chrome/).
 *
 * @since 4.0
 * @see [Track](https://developers.arcgis.com/javascript/latest/references/map-components/arcgis-track/) component
 * @see [Track](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Track.html) widget - _Deprecated since 4.32. Use the [Track component](https://developers.arcgis.com/javascript/latest/references/map-components/arcgis-track/) instead._
 * @see [Programming patterns: Widget viewModel pattern](https://developers.arcgis.com/javascript/latest/programming-patterns/#widget-viewmodel-pattern)
 * @example
 * let trackWidget = new Track({
 *   viewModel: {    // autocasts as new TrackViewModel()
 *     view: view,   // attaches the Track to the view
 *   }
 * };
 */
export default class TrackViewModel extends GeolocationPositioning {
  /**
   * @deprecated
   * Do not directly reference this property.
   * Use EventNames and EventTypes helpers from \@arcgis/core/Evented
   */
  "@eventTypes": TrackViewModelEvents;
  constructor(properties?: TrackViewModelProperties);
  /**
   * Error that caused the last [track-error](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Track-TrackViewModel.html#event:track-error) event to fire.
   *
   * @since 4.29
   * @example
   * if(track.viewModel.state === 'error')
   *   console.error(track.viewModel.error);
   */
  accessor error: GeolocationPositionError | Error | null | undefined;
  /**
   * A function that is used as an expression to evaluate geolocation points, and returns a boolean
   * value. If the function returns `true`, the widget will draw a graphic and navigate to the position.
   * The widget will ignore `false` values and not draw a graphic and not navigate to the position.
   *
   * Example use cases include smoothing out geolocation anomalies and geofencing.
   *
   * @since 4.27
   * @example
   * // Exclude locations that full outside an extent.
   * track.viewModel.positionFilterFunction = (value) => {
   *   const { longitude, latitude } = value.position.coords;
   *   const myLocation = new Point({ longitude, latitude });
   *   const geofenceExtent = new Extent({
   *     // whatever
   *   });
   *   return geometryEngine.within(myLocation, geofenceExtent);
   * };
   */
  accessor positionFilterFunction: PositionFilterFunction | null | undefined;
  /**
   * Indicates whether the component will automatically rotate to the device heading based on
   * the Geolocation APIs [`GeolocationCoordinates.heading`](https://developer.mozilla.org/en-US/docs/Web/API/GeolocationCoordinates/heading)
   * property. The map will not rotate if the speed is `0`,
   * or if the device is unable to provide heading information.
   *
   * @default true
   * @since 4.33
   */
  rotationEnabled: boolean;
  /**
   * The current state of the widget.
   *
   * @default "disabled"
   */
  get state(): TrackViewModelState;
  /**
   * Indicates whether new positions are being watched.
   *
   * @default false
   */
  get tracking(): boolean;
  /**
   * When executed, [tracking](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Track-TrackViewModel.html#tracking) starts at the
   * user's location.
   */
  start(): void;
  /** Stops tracking the user's location when executed. */
  stop(): void;
}