/**
 * A set of utilities for working with geodetic calculations.
 *
 * > [!WARNING]
 * >
 * > **Notes**
 * >
 * > Verify that `isLoaded()` returns `true` before using this module.
 * > Use `load()` to load this module's dependencies.
 *
 * @since 4.34
 */
import type Point from "../Point.js";
import type { LengthUnit } from "../../core/units.js";
import type { GeodeticCurveType } from "../types.js";

export interface Options {
  /**
   * The type of geodetic curve along which distance will be measured.
   * The default curveType of geodesic returns the shortest distance between `point1` and `point2`.
   *
   * @default "geodesic"
   */
  curveType?: Exclude<GeodeticCurveType, "shape-preserving">;
  /**
   * The length unit of the distance.
   *
   * @default "meters"
   */
  unit?: LengthUnit;
}

/**
 * Object returned by the [calculateDistanceAndAzimuth()](https://developers.arcgis.com/javascript/latest/references/core/geometry/operators/geodeticUtilsOperator/#calculateDistanceAndAzimuth) method.
 * Azimuths are in positive degrees from 0 to 360, measured clockwise from due north.
 */
export interface CalculateDistanceAndAzimuthResult {
  /** The geodetic distance between `point1` and `point2`. */
  distance: number;
  /** The azimuth in degrees from `point1` to `point2`. */
  azimuth12: number;
  /**
   * The azimuth in degrees from `point2` to `point1`.
   *
   * For example, Berlin is almost due north of Rome.
   * The azimuth from Rome to Berlin is 3°; close to due north (0°) but a little east.
   * The azimuth from Berlin to Rome is 183°; close to due south (180°) but a little west.
   *
   * For another example, Shanghai is almost due east of Wuhan.
   * The azimuth from Wuhan to Shanghai is 82°; close to due east (90°) but a little north.
   * The azimuth from Shanghai to Wuhan is 266°; close to due west (270°) but a little south.
   */
  azimuth21: number;
}

/**
 * Indicates if all dependencies of this module have been loaded.
 *
 * @returns Returns `true` if this module's dependencies have been loaded.
 */
export function isLoaded(): boolean;

/**
 * Loads this module's dependencies. This method must be called first if `isLoaded` returns `false`.
 *
 * @returns Resolves when the dependencies have been loaded.
 * @see [isLoaded()](https://developers.arcgis.com/javascript/latest/references/core/geometry/operators/geodeticUtilsOperator/#isLoaded)
 */
export function load(): Promise<void>;

/**
 * Geodetically calculates the distance and direction between two points.
 * Unless the `unit` option is set, the default is meters.
 *
 * ![Calculate Distance and Azimuth operator](https://developers.arcgis.com/javascript/latest/assets/references/core/operators/calculateDistanceAndAzimuth.png "Calculate Distance and Azimuth operator")
 *
 * @param point1 - The starting point.
 * @param point2 - The ending point.
 * @param options - Additional options.
 * @returns Returns an object containing the distance and azimuths between the two points.
 * @example
 * if (!geodeticUtilsOperator.isLoaded()) {
 *   await geodeticUtilsOperator.load();
 * }
 *
 * const distanceAndAzimuthResult = geodeticUtilsOperator.calculateDistanceAndAzimuth(
 *   new Point({ x: -118.805, y: 34.027, spatialReference: { wkid: 4326 } }),
 *   new Point({ x: -118.802, y: 34.029, spatialReference: { wkid: 4326 } })
 * );
 */
export function calculateDistanceAndAzimuth(point1: Point, point2: Point, options?: Options): CalculateDistanceAndAzimuthResult;

/**
 * Geodetically calculates a point location at a defined distance and direction from a known point.
 * Unless the `unit` option is set, the default is meters.
 *
 * ![Point From Distance operator](https://developers.arcgis.com/javascript/latest/assets/references/core/operators/pointFromDistance.png "Point From Distance operator")
 *
 * @param point - Origin location.
 * @param distance - Distance from the origin point.
 * @param azimuth - Direction in degrees (0 +/- 360) from the origin point, where both 0 and 360 degrees represent due north.
 * A positive azimuth is measured clockwise from north.
 * A negative azimuth is measured counter-clockwise from north.
 * @param options - Additional options.
 * @returns Returns the new point or `null` if the point cannot be represented in the spatial reference.
 * @example
 * if (!geodeticUtilsOperator.isLoaded()) {
 *   await geodeticUtilsOperator.load();
 * }
 *
 * const point = geodeticUtilsOperator.pointFromDistance(
 *   new Point({ x: -118.805, y: 34.027, spatialReference: { wkid: 4326 } }),
 *   350,
 *   45
 * );
 */
export function pointFromDistance(point: Point, distance: number, azimuth: number, options?: Options): Point | null | undefined;